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
@@ -16,14 +16,13 @@ from enum import Enum
16
16
  from typing import (
17
17
  Any,
18
18
  Optional,
19
- Tuple,
20
19
  )
21
20
 
22
- import anymarkup
23
21
  import jinja2
24
22
  import jinja2.meta
25
23
  import jsonpath_ng
26
24
  import networkx
25
+ from pydantic import Json
27
26
 
28
27
  from reconcile.change_owners.approver import (
29
28
  Approver,
@@ -34,13 +33,7 @@ from reconcile.change_owners.bundle import (
34
33
  FileDiffResolver,
35
34
  FileRef,
36
35
  )
37
- from reconcile.change_owners.diff import (
38
- SHA256SUM_FIELD_NAME,
39
- SHA256SUM_PATH,
40
- Diff,
41
- DiffType,
42
- extract_diffs,
43
- )
36
+ from reconcile.change_owners.diff import Diff
44
37
  from reconcile.gql_definitions.change_owners.queries.change_types import (
45
38
  ChangeTypeChangeDetectorChangeTypeProviderV1,
46
39
  ChangeTypeChangeDetectorJsonPathProviderV1,
@@ -62,11 +55,12 @@ class ChangeTypePriority(Enum):
62
55
  CRITICAL = "critical"
63
56
  URGENT = "urgent"
64
57
  HIGH = "high"
58
+ PROGRESSIVE_DELIVERY = "progressive-delivery"
65
59
  MEDIUM = "medium"
66
60
  LOW = "low"
67
61
 
68
62
 
69
- def parent_of_jsonpath(path: jsonpath_ng.JSONPath) -> Optional[jsonpath_ng.JSONPath]:
63
+ def parent_of_jsonpath(path: jsonpath_ng.JSONPath) -> jsonpath_ng.JSONPath | None:
70
64
  # todo - figure out if this is enough of if we have other
71
65
  # structures where a parent can be extracted
72
66
  if isinstance(path, jsonpath_ng.Child):
@@ -86,6 +80,20 @@ class DiffCoverage:
86
80
 
87
81
  parent: Optional["DiffCoverage"] = None
88
82
 
83
+ @property
84
+ def diff_fragments(self) -> Sequence["DiffCoverage"]:
85
+ return self._split_into
86
+
87
+ @property
88
+ def change_owner_labels(self) -> set[str]:
89
+ """
90
+ Returns a list of change-owner labels of all involved change-type contexts.
91
+ """
92
+ labels = {label for c in self.coverage for label in c.change_owner_labels or {}}
93
+ for _split in self._split_into:
94
+ labels.update(_split.change_owner_labels)
95
+ return labels
96
+
89
97
  def relative_path(self) -> jsonpath_ng.JSONPath:
90
98
  if self.parent:
91
99
  path = remove_prefix_from_path(self.diff.path, self.parent.diff.path)
@@ -192,7 +200,7 @@ class DiffCoverage:
192
200
 
193
201
  return None
194
202
 
195
- def add_covering_context(self, ctx: "ChangeTypeContext"):
203
+ def add_covering_context(self, ctx: "ChangeTypeContext") -> None:
196
204
  self.coverage.append(ctx)
197
205
  for s in self._split_into:
198
206
  s.add_covering_context(ctx)
@@ -216,172 +224,6 @@ class DiffCoverage:
216
224
  return coverages
217
225
 
218
226
 
219
- @dataclass
220
- class BundleFileChange:
221
- """
222
- Represents a file within an app-interface bundle that changed during an MR.
223
- It holds the old and new state of that file, along with precise differences
224
- between those states.
225
- """
226
-
227
- fileref: FileRef
228
- old: Optional[dict[str, Any]]
229
- new: Optional[dict[str, Any]]
230
- diffs: list[Diff]
231
- _diff_coverage: dict[str, DiffCoverage] = field(init=False, default_factory=dict)
232
-
233
- def __post_init__(self) -> None:
234
- self._diff_coverage = {d.path_str(): DiffCoverage(d, []) for d in self.diffs}
235
-
236
- def cover_changes(self, change_type_context: "ChangeTypeContext") -> list[Diff]:
237
- """
238
- Figure out if a ChangeTypeV1 covers detected changes within the BundleFile.
239
- Base idea:
240
-
241
- - a ChangeTypeV1 defines path patterns that are considered self-approvable
242
- - if a change (diff) is located under one of the allowed paths of the
243
- ChangeTypeV1, it is considered "covered" by that ChangeTypeV1 in a certain
244
- context (e.g. a RoleV1) and allows the approvers of that context (e.g.
245
- the members of that role) to approve that particular change.
246
-
247
- The change-type contexts that cover a change, are registered in the
248
- `DiffCoverage.coverage` list right next to the Diff that is covered.
249
- """
250
- covered_diffs = {}
251
- # observe the new state for added fields or list items or entire object sutrees
252
- covered_diffs.update(
253
- self._cover_changes_for_diffs(
254
- self._filter_diffs([DiffType.ADDED, DiffType.CHANGED]),
255
- self.new,
256
- change_type_context,
257
- )
258
- )
259
- # look at the old state for removed fields or list items or object subtrees
260
- covered_diffs.update(
261
- self._cover_changes_for_diffs(
262
- self._filter_diffs([DiffType.REMOVED]), self.old, change_type_context
263
- )
264
- )
265
- return list(covered_diffs.values())
266
-
267
- def _cover_changes_for_diffs(
268
- self,
269
- diffs: list[DiffCoverage],
270
- file_content: Any,
271
- change_type_context: "ChangeTypeContext",
272
- ) -> dict[str, Diff]:
273
-
274
- covered_diffs = {}
275
- if diffs:
276
- for (
277
- allowed_path
278
- ) in change_type_context.change_type_processor.allowed_changed_paths(
279
- self.fileref, file_content, change_type_context
280
- ):
281
- for dc in diffs:
282
- if dc.changed_path_covered_by_path(allowed_path):
283
- covered_diffs[dc.diff.path_str()] = dc.diff
284
- dc.coverage.append(change_type_context)
285
- elif SHA256SUM_PATH != allowed_path and dc.path_under_changed_path(
286
- allowed_path
287
- ):
288
- # the self-service path allowed by the change-type is covering
289
- # only parts of the diff. we will split the diff into a
290
- # smaller part, that can be covered by the change-type.
291
- # but the rest of the diff needs to be covered by another
292
- # change-type, either in full or again as a split.
293
- sub_dc = dc.split(allowed_path, change_type_context)
294
- if not sub_dc:
295
- raise Exception(
296
- f"unable to create a subdiff for path {allowed_path} on diff {dc.diff.path_str()}"
297
- )
298
- covered_diffs[str(allowed_path)] = sub_dc.diff
299
-
300
- return covered_diffs
301
-
302
- def _filter_diffs(self, diff_types: list[DiffType]) -> list[DiffCoverage]:
303
- return [
304
- d for d in self._diff_coverage.values() if d.diff.diff_type in diff_types
305
- ]
306
-
307
- def all_changes_covered(self) -> bool:
308
- return all(d.is_covered() for d in self.diff_coverage)
309
-
310
- def raw_diff_count(self) -> int:
311
- return len(self._diff_coverage)
312
-
313
- @property
314
- def diff_coverage(self) -> Sequence[DiffCoverage]:
315
- """
316
- returns the meaningful set of diffs, potentially more fine grained than
317
- what was originally detected for to the BundleFileChange.
318
- """
319
- coverages: list[DiffCoverage] = []
320
- for dc in self._diff_coverage.values():
321
- coverages.extend(dc.fine_grained_diff_coverages().values())
322
- return coverages
323
-
324
- def involved_change_types(self) -> list["ChangeTypeProcessor"]:
325
- """
326
- returns all the change-types that are involved in the coverage
327
- of all changes
328
- """
329
- change_types = []
330
- for dc in self.diff_coverage:
331
- for ctx in dc.coverage:
332
- change_types.append(ctx.change_type_processor)
333
- return change_types
334
-
335
-
336
- def parse_resource_file_content(content: Optional[Any]) -> tuple[Any, Optional[str]]:
337
- if content:
338
- try:
339
- data = anymarkup.parse(content, force_types=None)
340
- return data, data.get("$schema")
341
- except Exception:
342
- # not parsable content - we will just deal with the plain content
343
- return content, None
344
- else:
345
- return None, None
346
-
347
-
348
- def create_bundle_file_change(
349
- path: str,
350
- schema: Optional[str],
351
- file_type: BundleFileType,
352
- old_file_content: Any,
353
- new_file_content: Any,
354
- ) -> Optional[BundleFileChange]:
355
- """
356
- this is a factory method that creates a BundleFileChange object based
357
- on the old and new content of a file from app-interface. it detects differences
358
- within the old and new state of the file and represents them as instances
359
- of the Diff dataclass. for diff detection, the amazing `deepdiff` python
360
- library is used.
361
- """
362
- fileref = FileRef(path=path, schema=schema, file_type=file_type)
363
-
364
- # try to parse the content of a resourcefile
365
- # it falls back to the plain file content if parsing does not work
366
- if file_type == BundleFileType.RESOURCEFILE:
367
- old_file_content, _ = parse_resource_file_content(old_file_content)
368
- new_file_content, _ = parse_resource_file_content(new_file_content)
369
-
370
- diffs = extract_diffs(
371
- old_file_content=old_file_content,
372
- new_file_content=new_file_content,
373
- )
374
-
375
- if diffs:
376
- return BundleFileChange(
377
- fileref=fileref,
378
- old=old_file_content,
379
- new=new_file_content,
380
- diffs=diffs,
381
- )
382
- return None
383
-
384
-
385
227
  class PathExpression:
386
228
  """
387
229
  PathExpression is a wrapper around a JSONPath expression that can contain
@@ -411,14 +253,12 @@ class PathExpression:
411
253
  if self.parsed_jsonpath:
412
254
  return self.parsed_jsonpath
413
255
 
414
- expr = self.template.render(
415
- {
416
- self.CTX_FILE_PATH_VAR_NAME: ctx.context_file.path,
417
- }
418
- )
256
+ expr = self.template.render({
257
+ self.CTX_FILE_PATH_VAR_NAME: ctx.context_file.path,
258
+ })
419
259
  return parse_jsonpath(expr)
420
260
 
421
- def __eq__(self, obj):
261
+ def __eq__(self, obj: object) -> bool:
422
262
  return (
423
263
  isinstance(obj, PathExpression)
424
264
  and obj.jsonpath_expression == self.jsonpath_expression
@@ -426,20 +266,35 @@ class PathExpression:
426
266
 
427
267
 
428
268
  @dataclass
429
- class OwnershipContext:
269
+ class FileChange:
270
+ file_ref: FileRef
271
+ old: dict[str, Any] | None
272
+ new: dict[str, Any] | None
273
+ old_backrefs: set[FileRef] = field(default_factory=set)
274
+ new_backrefs: set[FileRef] = field(default_factory=set)
275
+
276
+
277
+ class OwnershipContext(ABC):
278
+ @abstractmethod
279
+ def find_ownership_context(
280
+ self,
281
+ context_schema: str | None,
282
+ change: FileChange,
283
+ ) -> list[FileRef]: ...
284
+
285
+
286
+ @dataclass
287
+ class ForwardrefOwnershipContext(OwnershipContext):
430
288
  selector: jsonpath_ng.JSONPath
431
- when: Optional[str]
289
+ when: str | None = None
432
290
 
433
291
  def find_ownership_context(
434
292
  self,
435
- context_schema: Optional[str],
436
- old_data: Optional[dict[str, Any]] = None,
437
- new_data: Optional[dict[str, Any]] = None,
293
+ context_schema: str | None,
294
+ change: FileChange,
438
295
  ) -> list[FileRef]:
439
-
440
- # extract contexts
441
- old_contexts = {e.value for e in self.selector.find(old_data)}
442
- new_contexts = {e.value for e in self.selector.find(new_data)}
296
+ old_contexts = {e.value for e in self.selector.find(change.old)}
297
+ new_contexts = {e.value for e in self.selector.find(change.new)}
443
298
 
444
299
  # apply conditions
445
300
  if self.when == "added":
@@ -461,6 +316,46 @@ class OwnershipContext:
461
316
  ]
462
317
 
463
318
 
319
+ @dataclass
320
+ class BackrefOwnershipContext(OwnershipContext):
321
+ selector: jsonpath_ng.JSONPath
322
+ file_diff_resolver: FileDiffResolver
323
+ when: str | None = None
324
+
325
+ def find_ownership_context(
326
+ self,
327
+ context_schema: str | None,
328
+ change: FileChange,
329
+ ) -> list[FileRef]:
330
+ # get backref datafile content
331
+ backref_datafile_content = {
332
+ ref: self.file_diff_resolver.lookup_file_diff(ref)
333
+ for ref in change.old_backrefs.union(change.new_backrefs)
334
+ }
335
+
336
+ # extract contexts
337
+ # we only care for those backrefs that mention the changed file at the selector
338
+ old_contexts = {
339
+ ref
340
+ for ref, data in backref_datafile_content.items()
341
+ if any(f.value == change.file_ref.path for f in self.selector.find(data[0]))
342
+ }
343
+ new_contexts = {
344
+ ref
345
+ for ref, data in backref_datafile_content.items()
346
+ if any(f.value == change.file_ref.path for f in self.selector.find(data[1]))
347
+ }
348
+
349
+ # apply conditions
350
+ if self.when == "added":
351
+ return list(new_contexts.difference(old_contexts))
352
+ if self.when == "removed":
353
+ return list(old_contexts.difference(new_contexts))
354
+ if self.when is None and old_contexts == new_contexts:
355
+ return list(old_contexts)
356
+ return []
357
+
358
+
464
359
  @dataclass
465
360
  class ContextExpansion:
466
361
  """
@@ -475,16 +370,22 @@ class ContextExpansion:
475
370
  def expand_from_file_ref(
476
371
  self,
477
372
  file_ref: FileRef,
478
- expansion_trail: Set[Tuple[str, FileRef]],
373
+ expansion_trail: Set[tuple[str, FileRef]],
479
374
  ) -> list["ResolvedContext"]:
480
375
  old_data, new_data = self.file_diff_resolver.lookup_file_diff(file_ref)
481
- return self.expand(old_data, new_data, expansion_trail)
376
+ return self.expand(
377
+ FileChange(
378
+ file_ref=file_ref,
379
+ old=old_data,
380
+ new=new_data,
381
+ ),
382
+ expansion_trail,
383
+ )
482
384
 
483
385
  def expand(
484
386
  self,
485
- old_data: Optional[dict[str, Any]],
486
- new_data: Optional[dict[str, Any]],
487
- expansion_trail: Set[Tuple[str, FileRef]],
387
+ change: FileChange,
388
+ expansion_trail: Set[tuple[str, FileRef]],
488
389
  ) -> list["ResolvedContext"]:
489
390
  """
490
391
  Find context based on the `self.context`, lookup the file diff for
@@ -493,17 +394,18 @@ class ContextExpansion:
493
394
  """
494
395
  context_file_refs = self.context.find_ownership_context(
495
396
  context_schema=self.change_type.context_schema,
496
- old_data=old_data,
497
- new_data=new_data,
397
+ change=change,
498
398
  )
499
- expaned_context_file_refs: list["ResolvedContext"] = []
399
+ expaned_context_file_refs: list[ResolvedContext] = []
500
400
  for ref in context_file_refs:
501
401
  ref_old_data, ref_new_data = self.file_diff_resolver.lookup_file_diff(ref)
502
402
  expaned_context_file_refs.extend(
503
403
  self.change_type.find_context_file_refs(
504
- ref,
505
- old_data=ref_old_data,
506
- new_data=ref_new_data,
404
+ change=FileChange(
405
+ file_ref=ref,
406
+ old=ref_old_data,
407
+ new=ref_new_data,
408
+ ),
507
409
  expansion_trail=expansion_trail,
508
410
  )
509
411
  )
@@ -528,28 +430,25 @@ class ChangeDetector(ABC):
528
430
  Represents an item from a change-types `change` list.
529
431
  """
530
432
 
531
- context_schema: Optional[str]
532
- change_schema: Optional[str]
533
- context: Optional[OwnershipContext]
433
+ context_schema: str | None
434
+ change_schema: str | None
435
+ context: OwnershipContext | None
534
436
 
535
437
  @abstractmethod
536
438
  def find_context_file_refs(
537
439
  self,
538
- old_data: Optional[dict[str, Any]] = None,
539
- new_data: Optional[dict[str, Any]] = None,
540
- ) -> list[FileRef]:
541
- ...
440
+ change: FileChange,
441
+ ) -> list[FileRef]: ...
542
442
 
543
443
 
544
444
  @dataclass
545
445
  class JsonPathChangeDetector(ChangeDetector):
546
446
  json_path_selectors: list[str]
547
447
 
548
- def __post_init__(self):
448
+ def __post_init__(self) -> None:
549
449
  self._json_path_expressions = [
550
450
  PathExpression(jsonpath_expression)
551
451
  for jsonpath_expression in self.json_path_selectors
552
- + [f"'{SHA256SUM_FIELD_NAME}'"]
553
452
  ]
554
453
 
555
454
  @property
@@ -558,12 +457,12 @@ class JsonPathChangeDetector(ChangeDetector):
558
457
 
559
458
  def find_context_file_refs(
560
459
  self,
561
- old_data: Optional[dict[str, Any]] = None,
562
- new_data: Optional[dict[str, Any]] = None,
460
+ change: FileChange,
563
461
  ) -> list[FileRef]:
564
462
  if self.context:
565
463
  return self.context.find_ownership_context(
566
- self.context_schema, old_data, new_data
464
+ context_schema=self.context_schema,
465
+ change=change,
567
466
  )
568
467
  return []
569
468
 
@@ -577,19 +476,22 @@ class ChangeTypeProcessor:
577
476
  """
578
477
 
579
478
  name: str
479
+ labels: Json | None
580
480
  description: str
581
481
  priority: ChangeTypePriority
582
482
  context_type: BundleFileType
583
- context_schema: Optional[str]
483
+ context_schema: str | None
584
484
  disabled: bool
585
485
  implicit_ownership: list[ChangeTypeImplicitOwnershipV1]
486
+ restrictive: bool | None = False
586
487
 
587
- def __post_init__(self):
488
+ def __post_init__(self) -> None:
588
489
  self._expressions_by_file_type_schema: dict[
589
- tuple[BundleFileType, Optional[str]], list[PathExpression]
490
+ tuple[BundleFileType, str | None], list[PathExpression]
590
491
  ] = defaultdict(list)
591
492
  self._change_detectors: list[ChangeDetector] = []
592
493
  self._context_expansions: list[ContextExpansion] = []
494
+ self._heritage: set[str] = set()
593
495
 
594
496
  @property
595
497
  def change_detectors(self) -> Sequence[ChangeDetector]:
@@ -597,10 +499,8 @@ class ChangeTypeProcessor:
597
499
 
598
500
  def find_context_file_refs(
599
501
  self,
600
- file_ref: FileRef,
601
- old_data: Optional[dict[str, Any]],
602
- new_data: Optional[dict[str, Any]],
603
- expansion_trail: Set[Tuple[str, FileRef]],
502
+ change: FileChange,
503
+ expansion_trail: Set[tuple[str, FileRef]],
604
504
  ) -> list[ResolvedContext]:
605
505
  """
606
506
  ChangeTypeV1 are attached to bundle files, react to changes within
@@ -659,31 +559,31 @@ class ChangeTypeProcessor:
659
559
 
660
560
  # prevent infinite ownership resolution
661
561
  expansion_trail_copy = set(expansion_trail)
662
- if (self.name, file_ref) in expansion_trail_copy:
562
+ if (self.name, change.file_ref) in expansion_trail_copy:
663
563
  return contexts
664
564
 
665
- expansion_trail_copy.add((self.name, file_ref))
565
+ expansion_trail_copy.add((self.name, change.file_ref))
666
566
 
667
567
  # direct context extraction
668
568
  # the changed file itself is giving the context for approver extraction
669
569
  # see doc string for more details
670
- if self.context_schema is None or self.context_schema == file_ref.schema:
570
+ if self.context_schema is None or self.context_schema == change.file_ref.schema:
671
571
  contexts.append(
672
572
  ResolvedContext(
673
- owned_file_ref=file_ref,
674
- context_file_ref=file_ref,
573
+ owned_file_ref=change.file_ref,
574
+ context_file_ref=change.file_ref,
675
575
  change_type=self,
676
576
  )
677
577
  )
678
578
 
679
579
  # expand context based on change-type composition
680
580
  for ce in self._context_expansions:
681
- for ec in ce.expand(old_data, new_data, expansion_trail_copy):
581
+ for ec in ce.expand(change, expansion_trail_copy):
682
582
  # add expanded contexts (derived owned files)
683
583
  contexts.append(
684
584
  ResolvedContext(
685
585
  owned_file_ref=ec.owned_file_ref,
686
- context_file_ref=file_ref,
586
+ context_file_ref=change.file_ref,
687
587
  change_type=ec.change_type,
688
588
  )
689
589
  )
@@ -693,8 +593,8 @@ class ChangeTypeProcessor:
693
593
  # file with a `context.selector`
694
594
  # see doc string for more details
695
595
  for c in self.change_detectors:
696
- if c.change_schema == file_ref.schema:
697
- for ctx_file_ref in c.find_context_file_refs(old_data, new_data):
596
+ if c.change_schema == change.file_ref.schema:
597
+ for ctx_file_ref in c.find_context_file_refs(change):
698
598
  contexts.append(
699
599
  ResolvedContext(
700
600
  owned_file_ref=ctx_file_ref,
@@ -740,7 +640,7 @@ class ChangeTypeProcessor:
740
640
  def _allowed_changed_paths_for_file_type_and_schema(
741
641
  self,
742
642
  file_type: BundleFileType,
743
- file_schema: Optional[str],
643
+ file_schema: str | None,
744
644
  file_content: Any,
745
645
  ctx: "ChangeTypeContext",
746
646
  ) -> list[jsonpath_ng.JSONPath]:
@@ -750,16 +650,14 @@ class ChangeTypeProcessor:
750
650
  file_schema,
751
651
  ) in self._expressions_by_file_type_schema:
752
652
  for change_type_path_expression in self._expressions_by_file_type_schema[
753
- (file_type, file_schema)
653
+ file_type, file_schema
754
654
  ]:
755
- paths.extend(
756
- [
757
- p.full_path
758
- for p in change_type_path_expression.jsonpath_for_context(
759
- ctx
760
- ).find(file_content)
761
- ]
762
- )
655
+ paths.extend([
656
+ p.full_path
657
+ for p in change_type_path_expression.jsonpath_for_context(ctx).find(
658
+ file_content
659
+ )
660
+ ])
763
661
  return paths
764
662
 
765
663
  def add_change_detector(
@@ -770,7 +668,7 @@ class ChangeTypeProcessor:
770
668
  self._change_detectors.append(detector)
771
669
  change_schema = detector.change_schema or self.context_schema
772
670
  expressions = self._expressions_by_file_type_schema[
773
- (self.context_type, change_schema)
671
+ self.context_type, change_schema
774
672
  ]
775
673
  for path_expression in detector.json_path_expressions:
776
674
  if path_expression not in expressions:
@@ -780,9 +678,34 @@ class ChangeTypeProcessor:
780
678
  f"{type(detector)} is not a supported change detection provider within ChangeTypes"
781
679
  )
782
680
 
783
- def add_context_expansion(self, context_expansion: ContextExpansion):
681
+ def add_context_expansion(self, context_expansion: ContextExpansion) -> None:
784
682
  self._context_expansions.append(context_expansion)
785
683
 
684
+ def inherit_from(self, other: "ChangeTypeProcessor") -> None:
685
+ for detector in other.change_detectors:
686
+ self.add_change_detector(detector)
687
+ other._heritage = self.lineage.union(other._heritage)
688
+
689
+ @property
690
+ def lineage(self) -> set[str]:
691
+ return self._heritage.union({self.name})
692
+
693
+
694
+ def build_ownership_context(
695
+ file_diff_resolver: FileDiffResolver,
696
+ selector: jsonpath_ng.JSONPath,
697
+ when: str | None = None,
698
+ where: str | None = None,
699
+ ) -> OwnershipContext:
700
+ """
701
+ create an OwnershipContext object based on the provided parameters
702
+ """
703
+ if where == "backrefs":
704
+ return BackrefOwnershipContext(
705
+ file_diff_resolver=file_diff_resolver, selector=selector, when=when
706
+ )
707
+ return ForwardrefOwnershipContext(selector=selector, when=when)
708
+
786
709
 
787
710
  def init_change_type_processors(
788
711
  change_types: Sequence[ChangeTypeV1], file_diff_resolver: FileDiffResolver
@@ -795,11 +718,13 @@ def init_change_type_processors(
795
718
  # build raw change-type-processor
796
719
  processors[change_type.name] = ChangeTypeProcessor(
797
720
  name=change_type.name,
721
+ labels=change_type.labels,
798
722
  description=change_type.description,
799
723
  priority=ChangeTypePriority(change_type.priority),
800
724
  context_type=BundleFileType[change_type.context_type.upper()],
801
725
  context_schema=change_type.context_schema,
802
726
  disabled=bool(change_type.disabled),
727
+ restrictive=bool(change_type.restrictive),
803
728
  implicit_ownership=change_type.implicit_ownership or [],
804
729
  )
805
730
  # register inheritance edges for cycle detection
@@ -814,9 +739,11 @@ def init_change_type_processors(
814
739
  if isinstance(change_detector, ChangeTypeChangeDetectorJsonPathProviderV1):
815
740
  ownership_context = None
816
741
  if change_detector.context:
817
- ownership_context = OwnershipContext(
742
+ ownership_context = build_ownership_context(
743
+ file_diff_resolver=file_diff_resolver,
818
744
  selector=parse_jsonpath(change_detector.context.selector),
819
745
  when=change_detector.context.when,
746
+ where=change_detector.context.where,
820
747
  )
821
748
  processor.add_change_detector(
822
749
  JsonPathChangeDetector(
@@ -840,11 +767,13 @@ def init_change_type_processors(
840
767
  processors[ct.name].add_context_expansion(
841
768
  ContextExpansion(
842
769
  change_type=processor,
843
- context=OwnershipContext(
770
+ context=build_ownership_context(
771
+ file_diff_resolver=file_diff_resolver,
844
772
  selector=parse_jsonpath(
845
773
  change_detector.ownership_context.selector
846
774
  ),
847
775
  when=change_detector.ownership_context.when,
776
+ where=change_detector.ownership_context.where,
848
777
  ),
849
778
  file_diff_resolver=file_diff_resolver,
850
779
  )
@@ -875,8 +804,13 @@ def init_change_type_processors(
875
804
  f"change-type '{ctp.name}' inherits from '{d}' "
876
805
  "but has a different context_schema"
877
806
  )
878
- for detector in processors[d].change_detectors:
879
- ctp.add_change_detector(detector)
807
+
808
+ # the higher level change type adopts the change detectors from his decentents
809
+ ctp.inherit_from(processors[d])
810
+
811
+ # the decentents adopt the context expansions from the higher level change type
812
+ for ce in ctp._context_expansions:
813
+ processors[d].add_context_expansion(ce)
880
814
 
881
815
  return processors
882
816
 
@@ -909,7 +843,8 @@ class ChangeTypeContext:
909
843
  origin: str
910
844
  context_file: FileRef
911
845
  approvers: list[Approver]
912
- approver_reachability: Optional[list[ApproverReachability]] = None
846
+ approver_reachability: list[ApproverReachability] | None = None
847
+ change_owner_labels: set[str] | None = None
913
848
 
914
849
  @property
915
850
  def disabled(self) -> bool:
@@ -927,20 +862,3 @@ JSON_PATH_ROOT = "$"
927
862
 
928
863
  def change_path_covered_by_allowed_path(changed_path: str, allowed_path: str) -> bool:
929
864
  return changed_path.startswith(allowed_path) or allowed_path == JSON_PATH_ROOT
930
-
931
-
932
- def get_priority_for_changes(
933
- bundle_file_changes: list[BundleFileChange],
934
- ) -> Optional[ChangeTypePriority]:
935
- """
936
- Finds the lowest priority of all change types involved in the provided bundle file changes.
937
- """
938
- priorities: set[ChangeTypePriority] = set()
939
- for bfc in bundle_file_changes:
940
- for ct in bfc.involved_change_types():
941
- priorities.add(ct.priority)
942
- # get the lowest priority
943
- for p in reversed(ChangeTypePriority):
944
- if p in priorities:
945
- return p
946
- return None