qontract-reconcile 0.10.0__py3-none-any.whl → 0.10.1.dev1203__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (844) hide show
  1. qontract_reconcile-0.10.1.dev1203.dist-info/METADATA +500 -0
  2. qontract_reconcile-0.10.1.dev1203.dist-info/RECORD +771 -0
  3. {qontract_reconcile-0.10.0.dist-info → qontract_reconcile-0.10.1.dev1203.dist-info}/WHEEL +1 -2
  4. {qontract_reconcile-0.10.0.dist-info → qontract_reconcile-0.10.1.dev1203.dist-info}/entry_points.txt +4 -2
  5. reconcile/acs_notifiers.py +126 -0
  6. reconcile/acs_policies.py +243 -0
  7. reconcile/acs_rbac.py +596 -0
  8. reconcile/aus/advanced_upgrade_service.py +621 -8
  9. reconcile/aus/aus_label_source.py +115 -0
  10. reconcile/aus/base.py +1053 -353
  11. reconcile/{utils → aus}/cluster_version_data.py +27 -12
  12. reconcile/aus/healthchecks.py +77 -0
  13. reconcile/aus/metrics.py +158 -0
  14. reconcile/aus/models.py +245 -5
  15. reconcile/aus/node_pool_spec.py +35 -0
  16. reconcile/aus/ocm_addons_upgrade_scheduler_org.py +225 -110
  17. reconcile/aus/ocm_upgrade_scheduler.py +76 -71
  18. reconcile/aus/ocm_upgrade_scheduler_org.py +81 -23
  19. reconcile/aus/version_gate_approver.py +204 -0
  20. reconcile/aus/version_gates/__init__.py +12 -0
  21. reconcile/aus/version_gates/handler.py +33 -0
  22. reconcile/aus/version_gates/ingress_gate_handler.py +32 -0
  23. reconcile/aus/version_gates/ocp_gate_handler.py +26 -0
  24. reconcile/aus/version_gates/sts_version_gate_handler.py +100 -0
  25. reconcile/aws_account_manager/README.md +5 -0
  26. reconcile/aws_account_manager/integration.py +373 -0
  27. reconcile/aws_account_manager/merge_request_manager.py +114 -0
  28. reconcile/aws_account_manager/metrics.py +39 -0
  29. reconcile/aws_account_manager/reconciler.py +403 -0
  30. reconcile/aws_account_manager/utils.py +41 -0
  31. reconcile/aws_ami_cleanup/integration.py +273 -0
  32. reconcile/aws_ami_share.py +18 -14
  33. reconcile/aws_cloudwatch_log_retention/integration.py +253 -0
  34. reconcile/aws_iam_keys.py +1 -1
  35. reconcile/aws_iam_password_reset.py +56 -20
  36. reconcile/aws_saml_idp/integration.py +204 -0
  37. reconcile/aws_saml_roles/integration.py +322 -0
  38. reconcile/aws_support_cases_sos.py +2 -2
  39. reconcile/aws_version_sync/integration.py +430 -0
  40. reconcile/aws_version_sync/merge_request_manager/merge_request.py +156 -0
  41. reconcile/aws_version_sync/merge_request_manager/merge_request_manager.py +160 -0
  42. reconcile/aws_version_sync/utils.py +64 -0
  43. reconcile/blackbox_exporter_endpoint_monitoring.py +2 -5
  44. reconcile/change_owners/README.md +34 -0
  45. reconcile/change_owners/approver.py +7 -9
  46. reconcile/change_owners/bundle.py +134 -9
  47. reconcile/change_owners/change_log_tracking.py +236 -0
  48. reconcile/change_owners/change_owners.py +204 -194
  49. reconcile/change_owners/change_types.py +183 -265
  50. reconcile/change_owners/changes.py +488 -0
  51. reconcile/change_owners/decision.py +120 -41
  52. reconcile/change_owners/diff.py +63 -92
  53. reconcile/change_owners/implicit_ownership.py +19 -16
  54. reconcile/change_owners/self_service_roles.py +158 -35
  55. reconcile/change_owners/tester.py +20 -18
  56. reconcile/checkpoint.py +4 -6
  57. reconcile/cli.py +1523 -242
  58. reconcile/closedbox_endpoint_monitoring_base.py +10 -17
  59. reconcile/cluster_auth_rhidp/integration.py +257 -0
  60. reconcile/cluster_deployment_mapper.py +2 -5
  61. reconcile/cna/assets/asset.py +4 -7
  62. reconcile/cna/assets/null.py +2 -5
  63. reconcile/cna/integration.py +2 -3
  64. reconcile/cna/state.py +6 -9
  65. reconcile/dashdotdb_base.py +31 -10
  66. reconcile/dashdotdb_cso.py +3 -6
  67. reconcile/dashdotdb_dora.py +530 -0
  68. reconcile/dashdotdb_dvo.py +10 -13
  69. reconcile/dashdotdb_slo.py +75 -19
  70. reconcile/database_access_manager.py +753 -0
  71. reconcile/deadmanssnitch.py +207 -0
  72. reconcile/dynatrace_token_provider/dependencies.py +69 -0
  73. reconcile/dynatrace_token_provider/integration.py +656 -0
  74. reconcile/dynatrace_token_provider/metrics.py +62 -0
  75. reconcile/dynatrace_token_provider/model.py +14 -0
  76. reconcile/dynatrace_token_provider/ocm.py +140 -0
  77. reconcile/dynatrace_token_provider/validate.py +48 -0
  78. reconcile/endpoints_discovery/integration.py +348 -0
  79. reconcile/endpoints_discovery/merge_request.py +96 -0
  80. reconcile/endpoints_discovery/merge_request_manager.py +178 -0
  81. reconcile/external_resources/aws.py +204 -0
  82. reconcile/external_resources/factories.py +163 -0
  83. reconcile/external_resources/integration.py +194 -0
  84. reconcile/external_resources/integration_secrets_sync.py +47 -0
  85. reconcile/external_resources/manager.py +405 -0
  86. reconcile/external_resources/meta.py +17 -0
  87. reconcile/external_resources/metrics.py +95 -0
  88. reconcile/external_resources/model.py +350 -0
  89. reconcile/external_resources/reconciler.py +265 -0
  90. reconcile/external_resources/secrets_sync.py +465 -0
  91. reconcile/external_resources/state.py +258 -0
  92. reconcile/gabi_authorized_users.py +19 -11
  93. reconcile/gcr_mirror.py +43 -34
  94. reconcile/github_org.py +4 -6
  95. reconcile/github_owners.py +1 -1
  96. reconcile/github_repo_invites.py +2 -5
  97. reconcile/gitlab_fork_compliance.py +14 -13
  98. reconcile/gitlab_housekeeping.py +185 -91
  99. reconcile/gitlab_labeler.py +15 -14
  100. reconcile/gitlab_members.py +126 -120
  101. reconcile/gitlab_owners.py +53 -66
  102. reconcile/gitlab_permissions.py +167 -6
  103. reconcile/glitchtip/README.md +150 -0
  104. reconcile/glitchtip/integration.py +99 -51
  105. reconcile/glitchtip/reconciler.py +99 -70
  106. reconcile/glitchtip_project_alerts/__init__.py +0 -0
  107. reconcile/glitchtip_project_alerts/integration.py +333 -0
  108. reconcile/glitchtip_project_dsn/integration.py +43 -43
  109. reconcile/gql_definitions/acs/__init__.py +0 -0
  110. reconcile/gql_definitions/acs/acs_instances.py +83 -0
  111. reconcile/gql_definitions/acs/acs_policies.py +239 -0
  112. reconcile/gql_definitions/acs/acs_rbac.py +111 -0
  113. reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +46 -8
  114. reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +38 -8
  115. reconcile/gql_definitions/app_interface_metrics_exporter/__init__.py +0 -0
  116. reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +61 -0
  117. reconcile/gql_definitions/aws_account_manager/__init__.py +0 -0
  118. reconcile/gql_definitions/aws_account_manager/aws_accounts.py +177 -0
  119. reconcile/gql_definitions/aws_ami_cleanup/__init__.py +0 -0
  120. reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +161 -0
  121. reconcile/gql_definitions/aws_saml_idp/__init__.py +0 -0
  122. reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +117 -0
  123. reconcile/gql_definitions/aws_saml_roles/__init__.py +0 -0
  124. reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +117 -0
  125. reconcile/gql_definitions/aws_saml_roles/roles.py +97 -0
  126. reconcile/gql_definitions/aws_version_sync/__init__.py +0 -0
  127. reconcile/gql_definitions/aws_version_sync/clusters.py +83 -0
  128. reconcile/gql_definitions/aws_version_sync/namespaces.py +143 -0
  129. reconcile/gql_definitions/change_owners/queries/change_types.py +16 -29
  130. reconcile/gql_definitions/change_owners/queries/self_service_roles.py +45 -11
  131. reconcile/gql_definitions/cluster_auth_rhidp/__init__.py +0 -0
  132. reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +128 -0
  133. reconcile/gql_definitions/cna/queries/cna_provisioners.py +6 -8
  134. reconcile/gql_definitions/cna/queries/cna_resources.py +3 -5
  135. reconcile/gql_definitions/common/alerting_services_settings.py +2 -2
  136. reconcile/gql_definitions/common/app_code_component_repos.py +9 -5
  137. reconcile/gql_definitions/{glitchtip/glitchtip_settings.py → common/app_interface_custom_messages.py} +14 -16
  138. reconcile/gql_definitions/common/app_interface_dms_settings.py +86 -0
  139. reconcile/gql_definitions/common/app_interface_repo_settings.py +2 -2
  140. reconcile/gql_definitions/common/app_interface_state_settings.py +3 -5
  141. reconcile/gql_definitions/common/app_interface_vault_settings.py +3 -5
  142. reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +120 -0
  143. reconcile/gql_definitions/common/apps.py +72 -0
  144. reconcile/gql_definitions/common/aws_vpc_requests.py +109 -0
  145. reconcile/gql_definitions/common/aws_vpcs.py +84 -0
  146. reconcile/gql_definitions/common/clusters.py +120 -254
  147. reconcile/gql_definitions/common/clusters_minimal.py +11 -35
  148. reconcile/gql_definitions/common/clusters_with_dms.py +72 -0
  149. reconcile/gql_definitions/common/clusters_with_peering.py +70 -98
  150. reconcile/gql_definitions/common/github_orgs.py +2 -2
  151. reconcile/gql_definitions/common/jira_settings.py +68 -0
  152. reconcile/gql_definitions/common/jiralert_settings.py +68 -0
  153. reconcile/gql_definitions/common/namespaces.py +74 -32
  154. reconcile/gql_definitions/common/namespaces_minimal.py +4 -10
  155. reconcile/gql_definitions/common/ocm_env_telemeter.py +95 -0
  156. reconcile/gql_definitions/common/ocm_environments.py +4 -2
  157. reconcile/gql_definitions/common/pagerduty_instances.py +5 -5
  158. reconcile/gql_definitions/common/pgp_reencryption_settings.py +5 -11
  159. reconcile/gql_definitions/common/pipeline_providers.py +45 -90
  160. reconcile/gql_definitions/common/quay_instances.py +64 -0
  161. reconcile/gql_definitions/common/quay_orgs.py +68 -0
  162. reconcile/gql_definitions/common/reserved_networks.py +94 -0
  163. reconcile/gql_definitions/common/saas_files.py +133 -95
  164. reconcile/gql_definitions/common/saas_target_namespaces.py +41 -26
  165. reconcile/gql_definitions/common/saasherder_settings.py +2 -2
  166. reconcile/gql_definitions/common/slack_workspaces.py +62 -0
  167. reconcile/gql_definitions/common/smtp_client_settings.py +2 -2
  168. reconcile/gql_definitions/common/state_aws_account.py +77 -0
  169. reconcile/gql_definitions/common/users.py +3 -2
  170. reconcile/gql_definitions/cost_report/__init__.py +0 -0
  171. reconcile/gql_definitions/cost_report/app_names.py +68 -0
  172. reconcile/gql_definitions/cost_report/cost_namespaces.py +86 -0
  173. reconcile/gql_definitions/cost_report/settings.py +77 -0
  174. reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +42 -12
  175. reconcile/gql_definitions/dynatrace_token_provider/__init__.py +0 -0
  176. reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +79 -0
  177. reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +84 -0
  178. reconcile/gql_definitions/endpoints_discovery/__init__.py +0 -0
  179. reconcile/gql_definitions/endpoints_discovery/namespaces.py +127 -0
  180. reconcile/gql_definitions/external_resources/__init__.py +0 -0
  181. reconcile/gql_definitions/external_resources/aws_accounts.py +73 -0
  182. reconcile/gql_definitions/external_resources/external_resources_modules.py +78 -0
  183. reconcile/gql_definitions/external_resources/external_resources_namespaces.py +1111 -0
  184. reconcile/gql_definitions/external_resources/external_resources_settings.py +98 -0
  185. reconcile/gql_definitions/fragments/aus_organization.py +34 -39
  186. reconcile/gql_definitions/fragments/aws_account_common.py +62 -0
  187. reconcile/gql_definitions/fragments/aws_account_managed.py +57 -0
  188. reconcile/gql_definitions/fragments/aws_account_sso.py +35 -0
  189. reconcile/gql_definitions/fragments/aws_infra_management_account.py +2 -2
  190. reconcile/gql_definitions/fragments/aws_vpc.py +47 -0
  191. reconcile/gql_definitions/fragments/aws_vpc_request.py +65 -0
  192. reconcile/gql_definitions/fragments/aws_vpc_request_subnet.py +29 -0
  193. reconcile/gql_definitions/fragments/deplopy_resources.py +7 -7
  194. reconcile/gql_definitions/fragments/disable.py +28 -0
  195. reconcile/gql_definitions/fragments/jumphost_common_fields.py +2 -2
  196. reconcile/gql_definitions/fragments/membership_source.py +47 -0
  197. reconcile/gql_definitions/fragments/minimal_ocm_organization.py +29 -0
  198. reconcile/gql_definitions/fragments/oc_connection_cluster.py +4 -9
  199. reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
  200. reconcile/gql_definitions/fragments/pipeline_provider_retention.py +30 -0
  201. reconcile/gql_definitions/fragments/prometheus_instance.py +48 -0
  202. reconcile/gql_definitions/fragments/resource_limits_requirements.py +29 -0
  203. reconcile/gql_definitions/fragments/{resource_requirements.py → resource_requests_requirements.py} +3 -3
  204. reconcile/gql_definitions/fragments/resource_values.py +2 -2
  205. reconcile/gql_definitions/fragments/saas_target_namespace.py +55 -12
  206. reconcile/gql_definitions/fragments/serviceaccount_token.py +38 -0
  207. reconcile/gql_definitions/fragments/terraform_state.py +36 -0
  208. reconcile/gql_definitions/fragments/upgrade_policy.py +5 -3
  209. reconcile/gql_definitions/fragments/user.py +3 -2
  210. reconcile/gql_definitions/fragments/vault_secret.py +2 -2
  211. reconcile/gql_definitions/gitlab_members/gitlab_instances.py +6 -2
  212. reconcile/gql_definitions/gitlab_members/permissions.py +3 -5
  213. reconcile/gql_definitions/glitchtip/glitchtip_instance.py +16 -2
  214. reconcile/gql_definitions/glitchtip/glitchtip_project.py +22 -23
  215. reconcile/gql_definitions/glitchtip_project_alerts/__init__.py +0 -0
  216. reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +173 -0
  217. reconcile/gql_definitions/integrations/integrations.py +62 -45
  218. reconcile/gql_definitions/introspection.json +51176 -0
  219. reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +13 -5
  220. reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +79 -0
  221. reconcile/gql_definitions/jira/__init__.py +0 -0
  222. reconcile/gql_definitions/jira/jira_servers.py +80 -0
  223. reconcile/gql_definitions/jira_permissions_validator/__init__.py +0 -0
  224. reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +131 -0
  225. reconcile/gql_definitions/jumphosts/jumphosts.py +3 -5
  226. reconcile/gql_definitions/ldap_groups/__init__.py +0 -0
  227. reconcile/gql_definitions/ldap_groups/roles.py +111 -0
  228. reconcile/gql_definitions/ldap_groups/settings.py +79 -0
  229. reconcile/gql_definitions/maintenance/__init__.py +0 -0
  230. reconcile/gql_definitions/maintenance/maintenances.py +101 -0
  231. reconcile/gql_definitions/membershipsources/__init__.py +0 -0
  232. reconcile/gql_definitions/membershipsources/roles.py +112 -0
  233. reconcile/gql_definitions/ocm_labels/__init__.py +0 -0
  234. reconcile/gql_definitions/ocm_labels/clusters.py +112 -0
  235. reconcile/gql_definitions/ocm_labels/organizations.py +78 -0
  236. reconcile/gql_definitions/ocm_subscription_labels/__init__.py +0 -0
  237. reconcile/gql_definitions/openshift_cluster_bots/__init__.py +0 -0
  238. reconcile/gql_definitions/openshift_cluster_bots/clusters.py +126 -0
  239. reconcile/gql_definitions/openshift_groups/managed_groups.py +2 -2
  240. reconcile/gql_definitions/openshift_groups/managed_roles.py +3 -2
  241. reconcile/gql_definitions/openshift_serviceaccount_tokens/__init__.py +0 -0
  242. reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +132 -0
  243. reconcile/gql_definitions/quay_membership/quay_membership.py +3 -5
  244. reconcile/gql_definitions/rhidp/__init__.py +0 -0
  245. reconcile/gql_definitions/rhidp/organizations.py +96 -0
  246. reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +2 -2
  247. reconcile/gql_definitions/service_dependencies/service_dependencies.py +9 -31
  248. reconcile/gql_definitions/sharding/aws_accounts.py +2 -2
  249. reconcile/gql_definitions/sharding/ocm_organization.py +63 -0
  250. reconcile/gql_definitions/skupper_network/site_controller_template.py +2 -2
  251. reconcile/gql_definitions/skupper_network/skupper_networks.py +12 -38
  252. reconcile/gql_definitions/slack_usergroups/clusters.py +2 -2
  253. reconcile/gql_definitions/slack_usergroups/permissions.py +8 -15
  254. reconcile/gql_definitions/slack_usergroups/users.py +3 -2
  255. reconcile/gql_definitions/slo_documents/__init__.py +0 -0
  256. reconcile/gql_definitions/slo_documents/slo_documents.py +142 -0
  257. reconcile/gql_definitions/status_board/__init__.py +0 -0
  258. reconcile/gql_definitions/status_board/status_board.py +163 -0
  259. reconcile/gql_definitions/statuspage/statuspages.py +56 -7
  260. reconcile/gql_definitions/templating/__init__.py +0 -0
  261. reconcile/gql_definitions/templating/template_collection.py +130 -0
  262. reconcile/gql_definitions/templating/templates.py +108 -0
  263. reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +4 -8
  264. reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +8 -8
  265. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +6 -8
  266. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +45 -56
  267. reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +4 -8
  268. reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +4 -8
  269. reconcile/gql_definitions/terraform_init/__init__.py +0 -0
  270. reconcile/gql_definitions/terraform_init/aws_accounts.py +93 -0
  271. reconcile/gql_definitions/terraform_repo/__init__.py +0 -0
  272. reconcile/gql_definitions/terraform_repo/terraform_repo.py +141 -0
  273. reconcile/gql_definitions/terraform_resources/database_access_manager.py +158 -0
  274. reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +153 -162
  275. reconcile/gql_definitions/terraform_tgw_attachments/__init__.py +0 -0
  276. reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +119 -0
  277. reconcile/gql_definitions/unleash_feature_toggles/__init__.py +0 -0
  278. reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +113 -0
  279. reconcile/gql_definitions/vault_instances/vault_instances.py +17 -50
  280. reconcile/gql_definitions/vault_policies/vault_policies.py +2 -2
  281. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +49 -12
  282. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +7 -2
  283. reconcile/integrations_manager.py +25 -13
  284. reconcile/jenkins/types.py +5 -1
  285. reconcile/jenkins_base.py +36 -0
  286. reconcile/jenkins_job_builder.py +10 -48
  287. reconcile/jenkins_job_builds_cleaner.py +40 -25
  288. reconcile/jenkins_job_cleaner.py +1 -3
  289. reconcile/jenkins_roles.py +22 -26
  290. reconcile/jenkins_webhooks.py +9 -6
  291. reconcile/jenkins_worker_fleets.py +11 -6
  292. reconcile/jira_permissions_validator.py +340 -0
  293. reconcile/jira_watcher.py +3 -5
  294. reconcile/ldap_groups/__init__.py +0 -0
  295. reconcile/ldap_groups/integration.py +279 -0
  296. reconcile/ldap_users.py +3 -0
  297. reconcile/ocm/types.py +39 -59
  298. reconcile/ocm_additional_routers.py +0 -1
  299. reconcile/ocm_addons_upgrade_tests_trigger.py +10 -15
  300. reconcile/ocm_aws_infrastructure_access.py +30 -32
  301. reconcile/ocm_clusters.py +217 -130
  302. reconcile/ocm_external_configuration_labels.py +15 -0
  303. reconcile/ocm_github_idp.py +1 -1
  304. reconcile/ocm_groups.py +25 -5
  305. reconcile/ocm_internal_notifications/__init__.py +0 -0
  306. reconcile/ocm_internal_notifications/integration.py +119 -0
  307. reconcile/ocm_labels/__init__.py +0 -0
  308. reconcile/ocm_labels/integration.py +409 -0
  309. reconcile/ocm_machine_pools.py +517 -108
  310. reconcile/ocm_upgrade_scheduler_org_updater.py +15 -11
  311. reconcile/openshift_base.py +609 -207
  312. reconcile/openshift_cluster_bots.py +344 -0
  313. reconcile/openshift_clusterrolebindings.py +15 -15
  314. reconcile/openshift_groups.py +42 -45
  315. reconcile/openshift_limitranges.py +1 -0
  316. reconcile/openshift_namespace_labels.py +22 -28
  317. reconcile/openshift_namespaces.py +22 -22
  318. reconcile/openshift_network_policies.py +4 -8
  319. reconcile/openshift_prometheus_rules.py +43 -0
  320. reconcile/openshift_resourcequotas.py +2 -16
  321. reconcile/openshift_resources.py +12 -10
  322. reconcile/openshift_resources_base.py +304 -328
  323. reconcile/openshift_rolebindings.py +18 -20
  324. reconcile/openshift_saas_deploy.py +105 -21
  325. reconcile/openshift_saas_deploy_change_tester.py +30 -35
  326. reconcile/openshift_saas_deploy_trigger_base.py +39 -36
  327. reconcile/openshift_saas_deploy_trigger_cleaner.py +41 -27
  328. reconcile/openshift_saas_deploy_trigger_configs.py +1 -2
  329. reconcile/openshift_saas_deploy_trigger_images.py +1 -2
  330. reconcile/openshift_saas_deploy_trigger_moving_commits.py +1 -2
  331. reconcile/openshift_saas_deploy_trigger_upstream_jobs.py +1 -2
  332. reconcile/openshift_serviceaccount_tokens.py +138 -74
  333. reconcile/openshift_tekton_resources.py +89 -24
  334. reconcile/openshift_upgrade_watcher.py +110 -62
  335. reconcile/openshift_users.py +16 -15
  336. reconcile/openshift_vault_secrets.py +11 -6
  337. reconcile/oum/__init__.py +0 -0
  338. reconcile/oum/base.py +387 -0
  339. reconcile/oum/labelset.py +55 -0
  340. reconcile/oum/metrics.py +71 -0
  341. reconcile/oum/models.py +69 -0
  342. reconcile/oum/providers.py +59 -0
  343. reconcile/oum/standalone.py +196 -0
  344. reconcile/prometheus_rules_tester/integration.py +31 -23
  345. reconcile/quay_base.py +4 -1
  346. reconcile/quay_membership.py +1 -2
  347. reconcile/quay_mirror.py +111 -61
  348. reconcile/quay_mirror_org.py +34 -21
  349. reconcile/quay_permissions.py +7 -3
  350. reconcile/quay_repos.py +24 -32
  351. reconcile/queries.py +263 -198
  352. reconcile/query_validator.py +3 -5
  353. reconcile/resource_scraper.py +3 -4
  354. reconcile/{template_tester.py → resource_template_tester.py} +3 -3
  355. reconcile/rhidp/__init__.py +0 -0
  356. reconcile/rhidp/common.py +214 -0
  357. reconcile/rhidp/metrics.py +20 -0
  358. reconcile/rhidp/ocm_oidc_idp/__init__.py +0 -0
  359. reconcile/rhidp/ocm_oidc_idp/base.py +221 -0
  360. reconcile/rhidp/ocm_oidc_idp/integration.py +56 -0
  361. reconcile/rhidp/ocm_oidc_idp/metrics.py +22 -0
  362. reconcile/rhidp/sso_client/__init__.py +0 -0
  363. reconcile/rhidp/sso_client/base.py +266 -0
  364. reconcile/rhidp/sso_client/integration.py +60 -0
  365. reconcile/rhidp/sso_client/metrics.py +39 -0
  366. reconcile/run_integration.py +293 -0
  367. reconcile/saas_auto_promotions_manager/integration.py +69 -24
  368. reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py +208 -0
  369. reconcile/saas_auto_promotions_manager/merge_request_manager/desired_state.py +28 -0
  370. reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request.py +3 -4
  371. reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager_v2.py +172 -0
  372. reconcile/saas_auto_promotions_manager/merge_request_manager/metrics.py +42 -0
  373. reconcile/saas_auto_promotions_manager/merge_request_manager/mr_parser.py +226 -0
  374. reconcile/saas_auto_promotions_manager/merge_request_manager/open_merge_requests.py +23 -0
  375. reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +108 -32
  376. reconcile/saas_auto_promotions_manager/meta.py +4 -0
  377. reconcile/saas_auto_promotions_manager/publisher.py +32 -4
  378. reconcile/saas_auto_promotions_manager/s3_exporter.py +77 -0
  379. reconcile/saas_auto_promotions_manager/subscriber.py +110 -23
  380. reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py +48 -41
  381. reconcile/saas_file_validator.py +16 -6
  382. reconcile/sendgrid_teammates.py +27 -12
  383. reconcile/service_dependencies.py +0 -3
  384. reconcile/signalfx_endpoint_monitoring.py +2 -5
  385. reconcile/skupper_network/integration.py +10 -11
  386. reconcile/skupper_network/models.py +3 -5
  387. reconcile/skupper_network/reconciler.py +28 -35
  388. reconcile/skupper_network/site_controller.py +8 -8
  389. reconcile/slack_base.py +4 -7
  390. reconcile/slack_usergroups.py +249 -171
  391. reconcile/sql_query.py +324 -171
  392. reconcile/status.py +0 -1
  393. reconcile/status_board.py +275 -0
  394. reconcile/statuspage/__init__.py +0 -5
  395. reconcile/statuspage/atlassian.py +219 -80
  396. reconcile/statuspage/integration.py +9 -97
  397. reconcile/statuspage/integrations/__init__.py +0 -0
  398. reconcile/statuspage/integrations/components.py +77 -0
  399. reconcile/statuspage/integrations/maintenances.py +111 -0
  400. reconcile/statuspage/page.py +107 -72
  401. reconcile/statuspage/state.py +6 -11
  402. reconcile/statuspage/status.py +8 -12
  403. reconcile/templates/rosa-classic-cluster-creation.sh.j2 +60 -0
  404. reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +61 -0
  405. reconcile/templating/__init__.py +0 -0
  406. reconcile/templating/lib/__init__.py +0 -0
  407. reconcile/templating/lib/merge_request_manager.py +180 -0
  408. reconcile/templating/lib/model.py +20 -0
  409. reconcile/templating/lib/rendering.py +191 -0
  410. reconcile/templating/renderer.py +410 -0
  411. reconcile/templating/validator.py +153 -0
  412. reconcile/terraform_aws_route53.py +13 -10
  413. reconcile/terraform_cloudflare_dns.py +92 -122
  414. reconcile/terraform_cloudflare_resources.py +15 -13
  415. reconcile/terraform_cloudflare_users.py +27 -27
  416. reconcile/terraform_init/__init__.py +0 -0
  417. reconcile/terraform_init/integration.py +165 -0
  418. reconcile/terraform_init/merge_request.py +57 -0
  419. reconcile/terraform_init/merge_request_manager.py +102 -0
  420. reconcile/terraform_repo.py +403 -0
  421. reconcile/terraform_resources.py +266 -168
  422. reconcile/terraform_tgw_attachments.py +417 -167
  423. reconcile/terraform_users.py +40 -17
  424. reconcile/terraform_vpc_peerings.py +310 -142
  425. reconcile/terraform_vpc_resources/__init__.py +0 -0
  426. reconcile/terraform_vpc_resources/integration.py +220 -0
  427. reconcile/terraform_vpc_resources/merge_request.py +57 -0
  428. reconcile/terraform_vpc_resources/merge_request_manager.py +107 -0
  429. reconcile/typed_queries/alerting_services_settings.py +1 -2
  430. reconcile/typed_queries/app_interface_custom_messages.py +24 -0
  431. reconcile/typed_queries/app_interface_deadmanssnitch_settings.py +17 -0
  432. reconcile/typed_queries/app_interface_metrics_exporter/__init__.py +0 -0
  433. reconcile/typed_queries/app_interface_metrics_exporter/onboarding_status.py +13 -0
  434. reconcile/typed_queries/app_interface_repo_url.py +1 -2
  435. reconcile/typed_queries/app_interface_state_settings.py +1 -3
  436. reconcile/typed_queries/app_interface_vault_settings.py +1 -2
  437. reconcile/typed_queries/app_quay_repos_escalation_policies.py +14 -0
  438. reconcile/typed_queries/apps.py +11 -0
  439. reconcile/typed_queries/aws_vpc_requests.py +9 -0
  440. reconcile/typed_queries/aws_vpcs.py +12 -0
  441. reconcile/typed_queries/cloudflare.py +10 -0
  442. reconcile/typed_queries/clusters.py +7 -5
  443. reconcile/typed_queries/clusters_minimal.py +6 -5
  444. reconcile/typed_queries/clusters_with_dms.py +16 -0
  445. reconcile/typed_queries/cost_report/__init__.py +0 -0
  446. reconcile/typed_queries/cost_report/app_names.py +22 -0
  447. reconcile/typed_queries/cost_report/cost_namespaces.py +43 -0
  448. reconcile/typed_queries/cost_report/settings.py +15 -0
  449. reconcile/typed_queries/dynatrace.py +10 -0
  450. reconcile/typed_queries/dynatrace_environments.py +14 -0
  451. reconcile/typed_queries/dynatrace_token_provider_token_specs.py +14 -0
  452. reconcile/typed_queries/external_resources.py +46 -0
  453. reconcile/typed_queries/get_state_aws_account.py +20 -0
  454. reconcile/typed_queries/glitchtip.py +10 -0
  455. reconcile/typed_queries/jenkins.py +25 -0
  456. reconcile/typed_queries/jira.py +7 -0
  457. reconcile/typed_queries/jira_settings.py +16 -0
  458. reconcile/typed_queries/jiralert_settings.py +22 -0
  459. reconcile/typed_queries/ocm.py +8 -0
  460. reconcile/typed_queries/pagerduty_instances.py +2 -7
  461. reconcile/typed_queries/quay.py +23 -0
  462. reconcile/typed_queries/repos.py +20 -8
  463. reconcile/typed_queries/reserved_networks.py +12 -0
  464. reconcile/typed_queries/saas_files.py +221 -167
  465. reconcile/typed_queries/slack.py +7 -0
  466. reconcile/typed_queries/slo_documents.py +12 -0
  467. reconcile/typed_queries/status_board.py +58 -0
  468. reconcile/typed_queries/tekton_pipeline_providers.py +1 -2
  469. reconcile/typed_queries/terraform_namespaces.py +1 -2
  470. reconcile/typed_queries/terraform_tgw_attachments/__init__.py +0 -0
  471. reconcile/typed_queries/terraform_tgw_attachments/aws_accounts.py +16 -0
  472. reconcile/typed_queries/unleash.py +10 -0
  473. reconcile/typed_queries/users.py +11 -0
  474. reconcile/typed_queries/vault.py +10 -0
  475. reconcile/unleash_feature_toggles/__init__.py +0 -0
  476. reconcile/unleash_feature_toggles/integration.py +287 -0
  477. reconcile/utils/acs/__init__.py +0 -0
  478. reconcile/utils/acs/base.py +81 -0
  479. reconcile/utils/acs/notifiers.py +143 -0
  480. reconcile/utils/acs/policies.py +163 -0
  481. reconcile/utils/acs/rbac.py +277 -0
  482. reconcile/utils/aggregated_list.py +11 -9
  483. reconcile/utils/amtool.py +6 -4
  484. reconcile/utils/aws_api.py +279 -66
  485. reconcile/utils/aws_api_typed/__init__.py +0 -0
  486. reconcile/utils/aws_api_typed/account.py +23 -0
  487. reconcile/utils/aws_api_typed/api.py +273 -0
  488. reconcile/utils/aws_api_typed/dynamodb.py +16 -0
  489. reconcile/utils/aws_api_typed/iam.py +67 -0
  490. reconcile/utils/aws_api_typed/organization.py +152 -0
  491. reconcile/utils/aws_api_typed/s3.py +26 -0
  492. reconcile/utils/aws_api_typed/service_quotas.py +79 -0
  493. reconcile/utils/aws_api_typed/sts.py +36 -0
  494. reconcile/utils/aws_api_typed/support.py +79 -0
  495. reconcile/utils/aws_helper.py +42 -3
  496. reconcile/utils/batches.py +11 -0
  497. reconcile/utils/binary.py +7 -9
  498. reconcile/utils/cloud_resource_best_practice/__init__.py +0 -0
  499. reconcile/utils/cloud_resource_best_practice/aws_rds.py +66 -0
  500. reconcile/utils/clusterhealth/__init__.py +0 -0
  501. reconcile/utils/clusterhealth/providerbase.py +39 -0
  502. reconcile/utils/clusterhealth/telemeter.py +39 -0
  503. reconcile/utils/config.py +3 -4
  504. reconcile/utils/deadmanssnitch_api.py +86 -0
  505. reconcile/utils/differ.py +205 -0
  506. reconcile/utils/disabled_integrations.py +4 -6
  507. reconcile/utils/dynatrace/__init__.py +0 -0
  508. reconcile/utils/dynatrace/client.py +93 -0
  509. reconcile/utils/early_exit_cache.py +289 -0
  510. reconcile/utils/elasticsearch_exceptions.py +5 -0
  511. reconcile/utils/environ.py +2 -2
  512. reconcile/utils/exceptions.py +4 -0
  513. reconcile/utils/expiration.py +4 -8
  514. reconcile/utils/extended_early_exit.py +210 -0
  515. reconcile/utils/external_resource_spec.py +34 -12
  516. reconcile/utils/external_resources.py +48 -20
  517. reconcile/utils/filtering.py +16 -0
  518. reconcile/utils/git.py +49 -16
  519. reconcile/utils/github_api.py +10 -9
  520. reconcile/utils/gitlab_api.py +333 -190
  521. reconcile/utils/glitchtip/client.py +97 -100
  522. reconcile/utils/glitchtip/models.py +89 -11
  523. reconcile/utils/gql.py +157 -58
  524. reconcile/utils/grouping.py +17 -0
  525. reconcile/utils/helm.py +89 -18
  526. reconcile/utils/helpers.py +51 -0
  527. reconcile/utils/imap_client.py +5 -6
  528. reconcile/utils/internal_groups/__init__.py +0 -0
  529. reconcile/utils/internal_groups/client.py +160 -0
  530. reconcile/utils/internal_groups/models.py +71 -0
  531. reconcile/utils/jenkins_api.py +10 -34
  532. reconcile/utils/jinja2/__init__.py +0 -0
  533. reconcile/utils/{jinja2_ext.py → jinja2/extensions.py} +6 -4
  534. reconcile/utils/jinja2/filters.py +142 -0
  535. reconcile/utils/jinja2/utils.py +278 -0
  536. reconcile/utils/jira_client.py +165 -8
  537. reconcile/utils/jjb_client.py +47 -35
  538. reconcile/utils/jobcontroller/__init__.py +0 -0
  539. reconcile/utils/jobcontroller/controller.py +413 -0
  540. reconcile/utils/jobcontroller/models.py +195 -0
  541. reconcile/utils/jsonpath.py +4 -5
  542. reconcile/utils/jump_host.py +13 -12
  543. reconcile/utils/keycloak.py +106 -0
  544. reconcile/utils/ldap_client.py +35 -6
  545. reconcile/utils/lean_terraform_client.py +115 -6
  546. reconcile/utils/membershipsources/__init__.py +0 -0
  547. reconcile/utils/membershipsources/app_interface_resolver.py +60 -0
  548. reconcile/utils/membershipsources/models.py +91 -0
  549. reconcile/utils/membershipsources/resolver.py +110 -0
  550. reconcile/utils/merge_request_manager/__init__.py +0 -0
  551. reconcile/utils/merge_request_manager/merge_request_manager.py +99 -0
  552. reconcile/utils/merge_request_manager/parser.py +67 -0
  553. reconcile/utils/metrics.py +511 -1
  554. reconcile/utils/models.py +123 -0
  555. reconcile/utils/mr/README.md +198 -0
  556. reconcile/utils/mr/__init__.py +14 -10
  557. reconcile/utils/mr/app_interface_reporter.py +2 -2
  558. reconcile/utils/mr/aws_access.py +4 -4
  559. reconcile/utils/mr/base.py +51 -31
  560. reconcile/utils/mr/clusters_updates.py +10 -7
  561. reconcile/utils/mr/glitchtip_access_reporter.py +2 -4
  562. reconcile/utils/mr/labels.py +14 -1
  563. reconcile/utils/mr/notificator.py +1 -3
  564. reconcile/utils/mr/ocm_update_recommended_version.py +1 -2
  565. reconcile/utils/mr/ocm_upgrade_scheduler_org_updates.py +7 -3
  566. reconcile/utils/mr/promote_qontract.py +203 -0
  567. reconcile/utils/mr/user_maintenance.py +24 -4
  568. reconcile/utils/oauth2_backend_application_session.py +132 -0
  569. reconcile/utils/oc.py +194 -170
  570. reconcile/utils/oc_connection_parameters.py +40 -51
  571. reconcile/utils/oc_filters.py +11 -13
  572. reconcile/utils/oc_map.py +14 -35
  573. reconcile/utils/ocm/__init__.py +30 -1
  574. reconcile/utils/ocm/addons.py +228 -0
  575. reconcile/utils/ocm/base.py +618 -5
  576. reconcile/utils/ocm/cluster_groups.py +5 -56
  577. reconcile/utils/ocm/clusters.py +111 -99
  578. reconcile/utils/ocm/identity_providers.py +66 -0
  579. reconcile/utils/ocm/label_sources.py +75 -0
  580. reconcile/utils/ocm/labels.py +139 -54
  581. reconcile/utils/ocm/manifests.py +39 -0
  582. reconcile/utils/ocm/ocm.py +182 -928
  583. reconcile/utils/ocm/products.py +758 -0
  584. reconcile/utils/ocm/search_filters.py +20 -28
  585. reconcile/utils/ocm/service_log.py +32 -79
  586. reconcile/utils/ocm/sre_capability_labels.py +51 -0
  587. reconcile/utils/ocm/status_board.py +66 -0
  588. reconcile/utils/ocm/subscriptions.py +49 -59
  589. reconcile/utils/ocm/syncsets.py +39 -0
  590. reconcile/utils/ocm/upgrades.py +181 -0
  591. reconcile/utils/ocm_base_client.py +71 -36
  592. reconcile/utils/openshift_resource.py +113 -67
  593. reconcile/utils/output.py +18 -11
  594. reconcile/utils/pagerduty_api.py +16 -10
  595. reconcile/utils/parse_dhms_duration.py +13 -1
  596. reconcile/utils/prometheus.py +123 -0
  597. reconcile/utils/promotion_state.py +56 -19
  598. reconcile/utils/promtool.py +5 -8
  599. reconcile/utils/quay_api.py +13 -25
  600. reconcile/utils/raw_github_api.py +3 -5
  601. reconcile/utils/repo_owners.py +2 -8
  602. reconcile/utils/rest_api_base.py +126 -0
  603. reconcile/utils/rosa/__init__.py +0 -0
  604. reconcile/utils/rosa/rosa_cli.py +310 -0
  605. reconcile/utils/rosa/session.py +201 -0
  606. reconcile/utils/ruamel.py +16 -0
  607. reconcile/utils/runtime/__init__.py +0 -1
  608. reconcile/utils/runtime/desired_state_diff.py +9 -20
  609. reconcile/utils/runtime/environment.py +33 -8
  610. reconcile/utils/runtime/integration.py +28 -12
  611. reconcile/utils/runtime/meta.py +1 -3
  612. reconcile/utils/runtime/runner.py +8 -11
  613. reconcile/utils/runtime/sharding.py +93 -36
  614. reconcile/utils/saasherder/__init__.py +1 -1
  615. reconcile/utils/saasherder/interfaces.py +143 -138
  616. reconcile/utils/saasherder/models.py +201 -43
  617. reconcile/utils/saasherder/saasherder.py +508 -378
  618. reconcile/utils/secret_reader.py +22 -27
  619. reconcile/utils/semver_helper.py +15 -1
  620. reconcile/utils/slack_api.py +124 -36
  621. reconcile/utils/smtp_client.py +1 -2
  622. reconcile/utils/sqs_gateway.py +10 -6
  623. reconcile/utils/state.py +276 -127
  624. reconcile/utils/terraform/config_client.py +6 -7
  625. reconcile/utils/terraform_client.py +284 -125
  626. reconcile/utils/terrascript/cloudflare_client.py +38 -17
  627. reconcile/utils/terrascript/cloudflare_resources.py +67 -18
  628. reconcile/utils/terrascript/models.py +2 -3
  629. reconcile/utils/terrascript/resources.py +1 -2
  630. reconcile/utils/terrascript_aws_client.py +1292 -540
  631. reconcile/utils/three_way_diff_strategy.py +157 -0
  632. reconcile/utils/unleash/__init__.py +11 -0
  633. reconcile/utils/{unleash.py → unleash/client.py} +35 -29
  634. reconcile/utils/unleash/server.py +145 -0
  635. reconcile/utils/vault.py +42 -32
  636. reconcile/utils/vaultsecretref.py +2 -4
  637. reconcile/utils/vcs.py +250 -0
  638. reconcile/vault_replication.py +38 -31
  639. reconcile/vpc_peerings_validator.py +82 -13
  640. tools/app_interface_metrics_exporter.py +70 -0
  641. tools/app_interface_reporter.py +44 -157
  642. tools/cli_commands/container_images_report.py +154 -0
  643. tools/cli_commands/cost_report/__init__.py +0 -0
  644. tools/cli_commands/cost_report/aws.py +137 -0
  645. tools/cli_commands/cost_report/cost_management_api.py +155 -0
  646. tools/cli_commands/cost_report/model.py +49 -0
  647. tools/cli_commands/cost_report/openshift.py +166 -0
  648. tools/cli_commands/cost_report/openshift_cost_optimization.py +187 -0
  649. tools/cli_commands/cost_report/response.py +124 -0
  650. tools/cli_commands/cost_report/util.py +72 -0
  651. tools/cli_commands/cost_report/view.py +524 -0
  652. tools/cli_commands/erv2.py +620 -0
  653. tools/cli_commands/gpg_encrypt.py +5 -8
  654. tools/cli_commands/systems_and_tools.py +489 -0
  655. tools/glitchtip_access_revalidation.py +1 -1
  656. tools/qontract_cli.py +2301 -673
  657. tools/saas_metrics_exporter/__init__.py +0 -0
  658. tools/saas_metrics_exporter/commit_distance/__init__.py +0 -0
  659. tools/saas_metrics_exporter/commit_distance/channel.py +63 -0
  660. tools/saas_metrics_exporter/commit_distance/commit_distance.py +103 -0
  661. tools/saas_metrics_exporter/commit_distance/metrics.py +19 -0
  662. tools/saas_metrics_exporter/main.py +99 -0
  663. tools/saas_promotion_state/__init__.py +0 -0
  664. tools/saas_promotion_state/saas_promotion_state.py +105 -0
  665. tools/sd_app_sre_alert_report.py +145 -0
  666. tools/template_validation.py +107 -0
  667. e2e_tests/cli.py +0 -83
  668. e2e_tests/create_namespace.py +0 -43
  669. e2e_tests/dedicated_admin_rolebindings.py +0 -44
  670. e2e_tests/dedicated_admin_test_base.py +0 -39
  671. e2e_tests/default_network_policies.py +0 -47
  672. e2e_tests/default_project_labels.py +0 -52
  673. e2e_tests/network_policy_test_base.py +0 -17
  674. e2e_tests/test_base.py +0 -56
  675. qontract_reconcile-0.10.0.dist-info/LICENSE +0 -201
  676. qontract_reconcile-0.10.0.dist-info/METADATA +0 -63
  677. qontract_reconcile-0.10.0.dist-info/RECORD +0 -586
  678. qontract_reconcile-0.10.0.dist-info/top_level.txt +0 -4
  679. reconcile/ecr_mirror.py +0 -152
  680. reconcile/github_scanner.py +0 -74
  681. reconcile/gitlab_integrations.py +0 -63
  682. reconcile/gql_definitions/ocm_oidc_idp/clusters.py +0 -195
  683. reconcile/gql_definitions/ocp_release_mirror/ocp_release_mirror.py +0 -287
  684. reconcile/integrations_validator.py +0 -18
  685. reconcile/jenkins_plugins.py +0 -129
  686. reconcile/kafka_clusters.py +0 -208
  687. reconcile/ocm_cluster_admin.py +0 -42
  688. reconcile/ocm_oidc_idp.py +0 -198
  689. reconcile/ocp_release_mirror.py +0 -373
  690. reconcile/prometheus_rules_tester_old.py +0 -436
  691. reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager.py +0 -279
  692. reconcile/saas_auto_promotions_manager/utils/vcs.py +0 -141
  693. reconcile/sentry_config.py +0 -613
  694. reconcile/sentry_helper.py +0 -69
  695. reconcile/test/conftest.py +0 -187
  696. reconcile/test/fixtures.py +0 -24
  697. reconcile/test/saas_auto_promotions_manager/conftest.py +0 -69
  698. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py +0 -110
  699. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/data_keys.py +0 -10
  700. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_housekeeping.py +0 -200
  701. reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_merge_request_manager.py +0 -151
  702. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +0 -63
  703. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/data_keys.py +0 -4
  704. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_multiple_namespaces.py +0 -46
  705. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_namespace.py +0 -94
  706. reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_target.py +0 -44
  707. reconcile/test/saas_auto_promotions_manager/subscriber/conftest.py +0 -74
  708. reconcile/test/saas_auto_promotions_manager/subscriber/data_keys.py +0 -11
  709. reconcile/test/saas_auto_promotions_manager/subscriber/test_content_hash.py +0 -155
  710. reconcile/test/saas_auto_promotions_manager/subscriber/test_diff.py +0 -173
  711. reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_channels_config_hash.py +0 -226
  712. reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_channels_moving_ref.py +0 -224
  713. reconcile/test/saas_auto_promotions_manager/subscriber/test_single_channel_with_single_publisher.py +0 -350
  714. reconcile/test/saas_auto_promotions_manager/test_integration_test.py +0 -129
  715. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_multiple_publishers_for_single_channel.py +0 -70
  716. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_use_target_config_hash.py +0 -63
  717. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_with_auto_promote.py +0 -74
  718. reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_without_auto_promote.py +0 -65
  719. reconcile/test/test_aggregated_list.py +0 -237
  720. reconcile/test/test_amtool.py +0 -37
  721. reconcile/test/test_auto_promoter.py +0 -295
  722. reconcile/test/test_aws_ami_share.py +0 -68
  723. reconcile/test/test_aws_iam_keys.py +0 -70
  724. reconcile/test/test_aws_iam_password_reset.py +0 -35
  725. reconcile/test/test_aws_support_cases_sos.py +0 -23
  726. reconcile/test/test_checkpoint.py +0 -178
  727. reconcile/test/test_cli.py +0 -41
  728. reconcile/test/test_closedbox_endpoint_monitoring.py +0 -207
  729. reconcile/test/test_gabi_authorized_users.py +0 -72
  730. reconcile/test/test_github_org.py +0 -154
  731. reconcile/test/test_github_repo_invites.py +0 -123
  732. reconcile/test/test_gitlab_housekeeping.py +0 -88
  733. reconcile/test/test_gitlab_labeler.py +0 -129
  734. reconcile/test/test_gitlab_members.py +0 -283
  735. reconcile/test/test_instrumented_wrappers.py +0 -18
  736. reconcile/test/test_integrations_manager.py +0 -995
  737. reconcile/test/test_jenkins_worker_fleets.py +0 -55
  738. reconcile/test/test_jump_host.py +0 -117
  739. reconcile/test/test_ldap_users.py +0 -123
  740. reconcile/test/test_make.py +0 -28
  741. reconcile/test/test_ocm_additional_routers.py +0 -134
  742. reconcile/test/test_ocm_addons_upgrade_scheduler_org.py +0 -149
  743. reconcile/test/test_ocm_clusters.py +0 -598
  744. reconcile/test/test_ocm_clusters_manifest_updates.py +0 -89
  745. reconcile/test/test_ocm_oidc_idp.py +0 -315
  746. reconcile/test/test_ocm_update_recommended_version.py +0 -145
  747. reconcile/test/test_ocm_upgrade_scheduler.py +0 -614
  748. reconcile/test/test_ocm_upgrade_scheduler_org_updater.py +0 -129
  749. reconcile/test/test_openshift_base.py +0 -730
  750. reconcile/test/test_openshift_namespace_labels.py +0 -345
  751. reconcile/test/test_openshift_namespaces.py +0 -256
  752. reconcile/test/test_openshift_resource.py +0 -415
  753. reconcile/test/test_openshift_resources_base.py +0 -440
  754. reconcile/test/test_openshift_saas_deploy_change_tester.py +0 -310
  755. reconcile/test/test_openshift_tekton_resources.py +0 -253
  756. reconcile/test/test_openshift_upgrade_watcher.py +0 -146
  757. reconcile/test/test_prometheus_rules_tester.py +0 -151
  758. reconcile/test/test_prometheus_rules_tester_old.py +0 -77
  759. reconcile/test/test_quay_membership.py +0 -86
  760. reconcile/test/test_quay_mirror.py +0 -109
  761. reconcile/test/test_quay_mirror_org.py +0 -70
  762. reconcile/test/test_quay_repos.py +0 -59
  763. reconcile/test/test_queries.py +0 -53
  764. reconcile/test/test_repo_owners.py +0 -47
  765. reconcile/test/test_requests_sender.py +0 -139
  766. reconcile/test/test_saasherder.py +0 -1074
  767. reconcile/test/test_saasherder_allowed_secret_paths.py +0 -127
  768. reconcile/test/test_secret_reader.py +0 -153
  769. reconcile/test/test_slack_base.py +0 -185
  770. reconcile/test/test_slack_usergroups.py +0 -744
  771. reconcile/test/test_sql_query.py +0 -19
  772. reconcile/test/test_terraform_cloudflare_dns.py +0 -117
  773. reconcile/test/test_terraform_cloudflare_resources.py +0 -106
  774. reconcile/test/test_terraform_cloudflare_users.py +0 -749
  775. reconcile/test/test_terraform_resources.py +0 -257
  776. reconcile/test/test_terraform_tgw_attachments.py +0 -631
  777. reconcile/test/test_terraform_users.py +0 -57
  778. reconcile/test/test_terraform_vpc_peerings.py +0 -499
  779. reconcile/test/test_terraform_vpc_peerings_build_desired_state.py +0 -1061
  780. reconcile/test/test_unleash.py +0 -138
  781. reconcile/test/test_utils_aws_api.py +0 -240
  782. reconcile/test/test_utils_aws_helper.py +0 -80
  783. reconcile/test/test_utils_cluster_version_data.py +0 -177
  784. reconcile/test/test_utils_data_structures.py +0 -13
  785. reconcile/test/test_utils_disabled_integrations.py +0 -86
  786. reconcile/test/test_utils_expiration.py +0 -109
  787. reconcile/test/test_utils_external_resource_spec.py +0 -383
  788. reconcile/test/test_utils_external_resources.py +0 -247
  789. reconcile/test/test_utils_github_api.py +0 -73
  790. reconcile/test/test_utils_gitlab_api.py +0 -20
  791. reconcile/test/test_utils_gpg.py +0 -69
  792. reconcile/test/test_utils_gql.py +0 -81
  793. reconcile/test/test_utils_helm.py +0 -306
  794. reconcile/test/test_utils_helpers.py +0 -55
  795. reconcile/test/test_utils_imap_client.py +0 -65
  796. reconcile/test/test_utils_jjb_client.py +0 -52
  797. reconcile/test/test_utils_jsonpath.py +0 -286
  798. reconcile/test/test_utils_ldap_client.py +0 -51
  799. reconcile/test/test_utils_mr.py +0 -226
  800. reconcile/test/test_utils_mr_clusters_updates.py +0 -77
  801. reconcile/test/test_utils_oc.py +0 -984
  802. reconcile/test/test_utils_ocm.py +0 -110
  803. reconcile/test/test_utils_pagerduty_api.py +0 -251
  804. reconcile/test/test_utils_parse_dhms_duration.py +0 -34
  805. reconcile/test/test_utils_password_validator.py +0 -155
  806. reconcile/test/test_utils_quay_api.py +0 -86
  807. reconcile/test/test_utils_semver_helper.py +0 -19
  808. reconcile/test/test_utils_sharding.py +0 -56
  809. reconcile/test/test_utils_slack_api.py +0 -439
  810. reconcile/test/test_utils_smtp_client.py +0 -73
  811. reconcile/test/test_utils_state.py +0 -256
  812. reconcile/test/test_utils_terraform.py +0 -13
  813. reconcile/test/test_utils_terraform_client.py +0 -585
  814. reconcile/test/test_utils_terraform_config_client.py +0 -219
  815. reconcile/test/test_utils_terrascript_aws_client.py +0 -277
  816. reconcile/test/test_utils_terrascript_cloudflare_client.py +0 -597
  817. reconcile/test/test_utils_terrascript_cloudflare_resources.py +0 -26
  818. reconcile/test/test_vault_replication.py +0 -515
  819. reconcile/test/test_vault_utils.py +0 -47
  820. reconcile/test/test_version_bump.py +0 -18
  821. reconcile/test/test_vpc_peerings_validator.py +0 -103
  822. reconcile/test/test_wrong_region.py +0 -78
  823. reconcile/typed_queries/glitchtip_settings.py +0 -18
  824. reconcile/typed_queries/ocp_release_mirror.py +0 -11
  825. reconcile/unleash_watcher.py +0 -120
  826. reconcile/utils/git_secrets.py +0 -63
  827. reconcile/utils/mr/auto_promoter.py +0 -218
  828. reconcile/utils/sentry_client.py +0 -383
  829. release/test_version.py +0 -50
  830. release/version.py +0 -100
  831. tools/test/test_qontract_cli.py +0 -60
  832. tools/test/test_sre_checkpoints.py +0 -79
  833. /e2e_tests/__init__.py → /reconcile/aus/upgrades.py +0 -0
  834. /reconcile/{gql_definitions/ocp_release_mirror → aws_account_manager}/__init__.py +0 -0
  835. /reconcile/{test → aws_ami_cleanup}/__init__.py +0 -0
  836. /reconcile/{test/saas_auto_promotions_manager → aws_cloudwatch_log_retention}/__init__.py +0 -0
  837. /reconcile/{test/saas_auto_promotions_manager/merge_request_manager → aws_saml_idp}/__init__.py +0 -0
  838. /reconcile/{test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager → aws_saml_roles}/__init__.py +0 -0
  839. /reconcile/{test/saas_auto_promotions_manager/merge_request_manager/renderer → aws_version_sync}/__init__.py +0 -0
  840. /reconcile/{test/saas_auto_promotions_manager/subscriber → aws_version_sync/merge_request_manager}/__init__.py +0 -0
  841. /reconcile/{test/saas_auto_promotions_manager/utils → cluster_auth_rhidp}/__init__.py +0 -0
  842. /reconcile/{test/saas_auto_promotions_manager/utils/saas_files_inventory → dynatrace_token_provider}/__init__.py +0 -0
  843. {release → reconcile/endpoints_discovery}/__init__.py +0 -0
  844. {tools/test → reconcile/external_resources}/__init__.py +0 -0
@@ -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