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
@@ -0,0 +1,278 @@
1
+ import datetime
2
+ from functools import cache
3
+ from typing import Any, Self
4
+
5
+ import jinja2
6
+ from jinja2.sandbox import SandboxedEnvironment
7
+ from pydantic import BaseModel
8
+ from sretoolbox.utils import retry
9
+
10
+ from reconcile import queries
11
+ from reconcile.checkpoint import url_makes_sense
12
+ from reconcile.github_users import init_github
13
+ from reconcile.utils import gql
14
+ from reconcile.utils.aws_api import AWSApi
15
+ from reconcile.utils.helpers import flatten
16
+ from reconcile.utils.jinja2.extensions import B64EncodeExtension, RaiseErrorExtension
17
+ from reconcile.utils.jinja2.filters import (
18
+ eval_filter,
19
+ extract_jsonpath,
20
+ hash_list,
21
+ json_pointers,
22
+ json_to_dict,
23
+ matches_jsonpath,
24
+ str_format,
25
+ urlescape,
26
+ urlunescape,
27
+ yaml_to_dict,
28
+ )
29
+ from reconcile.utils.secret_reader import SecretNotFound, SecretReader, SecretReaderBase
30
+ from reconcile.utils.vault import SecretFieldNotFound
31
+
32
+
33
+ class Jinja2TemplateError(Exception):
34
+ def __init__(self, msg: Any):
35
+ super().__init__("error processing jinja2 template: " + str(msg))
36
+
37
+
38
+ class TemplateRenderOptions(BaseModel):
39
+ trim_blocks: bool
40
+ lstrip_blocks: bool
41
+ keep_trailing_newline: bool
42
+
43
+ class Config:
44
+ frozen = True
45
+
46
+ @classmethod
47
+ def create(
48
+ cls,
49
+ trim_blocks: bool | None = None,
50
+ lstrip_blocks: bool | None = None,
51
+ keep_trailing_newline: bool | None = None,
52
+ ) -> Self:
53
+ return cls(
54
+ trim_blocks=trim_blocks or False,
55
+ lstrip_blocks=lstrip_blocks or False,
56
+ keep_trailing_newline=keep_trailing_newline or False,
57
+ )
58
+
59
+
60
+ @cache
61
+ def compile_jinja2_template(
62
+ body: str,
63
+ extra_curly: bool = False,
64
+ template_render_options: TemplateRenderOptions | None = None,
65
+ ) -> Any:
66
+ if not template_render_options:
67
+ template_render_options = TemplateRenderOptions.create()
68
+ env: dict[str, Any] = template_render_options.dict()
69
+ if extra_curly:
70
+ env.update({
71
+ "block_start_string": "{{%",
72
+ "block_end_string": "%}}",
73
+ "variable_start_string": "{{{",
74
+ "variable_end_string": "}}}",
75
+ "comment_start_string": "{{#",
76
+ "comment_end_string": "#}}",
77
+ })
78
+
79
+ jinja_env = SandboxedEnvironment(
80
+ extensions=[B64EncodeExtension, RaiseErrorExtension],
81
+ undefined=jinja2.StrictUndefined,
82
+ **env,
83
+ )
84
+ jinja_env.filters.update({
85
+ "json_to_dict": json_to_dict,
86
+ "yaml_to_dict": yaml_to_dict,
87
+ "urlescape": urlescape,
88
+ "urlunescape": urlunescape,
89
+ "eval": eval_filter,
90
+ "extract_jsonpath": extract_jsonpath,
91
+ "matches_jsonpath": matches_jsonpath,
92
+ "json_pointers": json_pointers,
93
+ "str_format": str_format,
94
+ })
95
+
96
+ return jinja_env.from_string(body)
97
+
98
+
99
+ def lookup_github_file_content(
100
+ repo: str,
101
+ path: str,
102
+ ref: str,
103
+ tvars: dict[str, Any] | None = None,
104
+ settings: dict[str, Any] | None = None,
105
+ secret_reader: SecretReaderBase | None = None,
106
+ ) -> str:
107
+ if tvars is not None:
108
+ repo = process_jinja2_template(
109
+ body=repo, vars=tvars, settings=settings, secret_reader=secret_reader
110
+ )
111
+ path = process_jinja2_template(
112
+ body=path, vars=tvars, settings=settings, secret_reader=secret_reader
113
+ )
114
+ ref = process_jinja2_template(
115
+ body=ref, vars=tvars, settings=settings, secret_reader=secret_reader
116
+ )
117
+
118
+ gh = init_github()
119
+ c = gh.get_repo(repo).get_contents(path, ref).decoded_content
120
+ return c.decode("utf-8")
121
+
122
+
123
+ def lookup_graphql_query_results(query: str, **kwargs: dict[str, Any]) -> list[Any]:
124
+ gqlapi = gql.get_api()
125
+ resource = gqlapi.get_resource(query)["content"]
126
+ rendered_resource = jinja2.Template(resource).render(**kwargs)
127
+ results = next(iter(gqlapi.query(rendered_resource).values()))
128
+ return results
129
+
130
+
131
+ def lookup_s3_object(
132
+ account_name: str,
133
+ bucket_name: str,
134
+ path: str,
135
+ region_name: str | None = None,
136
+ ) -> str:
137
+ settings = queries.get_app_interface_settings()
138
+ accounts = queries.get_aws_accounts(name=account_name)
139
+ if not accounts:
140
+ raise Exception(f"aws account not found: {account_name}")
141
+
142
+ with AWSApi(1, accounts, settings=settings, init_users=False) as aws_api:
143
+ return aws_api.get_s3_object_content(
144
+ account_name,
145
+ bucket_name,
146
+ path,
147
+ region_name=region_name,
148
+ )
149
+
150
+
151
+ def list_s3_objects(
152
+ account_name: str,
153
+ bucket_name: str,
154
+ path: str,
155
+ region_name: str | None = None,
156
+ ) -> list[str]:
157
+ settings = queries.get_app_interface_settings()
158
+ accounts = queries.get_aws_accounts(name=account_name)
159
+ if not accounts:
160
+ raise Exception(f"aws account not found: {account_name}")
161
+
162
+ with AWSApi(1, accounts, settings=settings, init_users=False) as aws_api:
163
+ return aws_api.list_s3_objects(
164
+ account_name,
165
+ bucket_name,
166
+ path,
167
+ region_name=region_name,
168
+ )
169
+
170
+
171
+ @retry()
172
+ def lookup_secret(
173
+ path: str,
174
+ key: str,
175
+ version: str | None = None,
176
+ tvars: dict[str, Any] | None = None,
177
+ allow_not_found: bool = False,
178
+ settings: dict[str, Any] | None = None,
179
+ secret_reader: SecretReaderBase | None = None,
180
+ ) -> str | None:
181
+ if tvars is not None:
182
+ path = process_jinja2_template(
183
+ body=path, vars=tvars, settings=settings, secret_reader=secret_reader
184
+ )
185
+ key = process_jinja2_template(
186
+ body=key, vars=tvars, settings=settings, secret_reader=secret_reader
187
+ )
188
+ if version and not isinstance(version, int):
189
+ version = process_jinja2_template(
190
+ body=version, vars=tvars, settings=settings, secret_reader=secret_reader
191
+ )
192
+ secret = {"path": path, "field": key, "version": version}
193
+ try:
194
+ if not secret_reader:
195
+ secret_reader = SecretReader(settings)
196
+ return secret_reader.read(secret)
197
+ except (SecretNotFound, SecretFieldNotFound) as e:
198
+ if allow_not_found:
199
+ return None
200
+ raise FetchSecretError(e) from None
201
+ except Exception as e:
202
+ raise FetchSecretError(e) from e
203
+
204
+
205
+ def process_jinja2_template(
206
+ body: str,
207
+ vars: dict[str, Any] | None = None,
208
+ extra_curly: bool = False,
209
+ settings: dict[str, Any] | None = None,
210
+ secret_reader: SecretReaderBase | None = None,
211
+ template_render_options: TemplateRenderOptions | None = None,
212
+ ) -> Any:
213
+ if vars is None:
214
+ vars = {}
215
+ vars.update({
216
+ "vault": lambda p, k, v=None, allow_not_found=False: lookup_secret(
217
+ path=p,
218
+ key=k,
219
+ version=v,
220
+ tvars=vars,
221
+ allow_not_found=allow_not_found,
222
+ settings=settings,
223
+ secret_reader=secret_reader,
224
+ ),
225
+ "github": lambda u, p, r, v=None: lookup_github_file_content(
226
+ repo=u,
227
+ path=p,
228
+ ref=r,
229
+ tvars=vars,
230
+ settings=settings,
231
+ secret_reader=secret_reader,
232
+ ),
233
+ "urlescape": lambda u, s="/", e=None: urlescape(string=u, safe=s, encoding=e),
234
+ "urlunescape": lambda u, e=None: urlunescape(string=u, encoding=e),
235
+ "hash_list": hash_list,
236
+ "query": lookup_graphql_query_results,
237
+ "url": url_makes_sense,
238
+ "s3": lookup_s3_object,
239
+ "s3_ls": list_s3_objects,
240
+ "flatten_dict": flatten,
241
+ "yesterday": lambda: (datetime.datetime.now() - datetime.timedelta(1)).strftime(
242
+ "%Y-%m-%d"
243
+ ),
244
+ })
245
+ if "_template_mocks" in vars:
246
+ for k, v in vars["_template_mocks"].items():
247
+ vars[k] = lambda *args, **kwargs: v # noqa: B023
248
+ try:
249
+ template = compile_jinja2_template(body, extra_curly, template_render_options)
250
+ r = template.render(vars)
251
+ except Exception as e:
252
+ raise Jinja2TemplateError(e) from None
253
+ return r
254
+
255
+
256
+ def process_extracurlyjinja2_template(
257
+ body: str,
258
+ vars: dict[str, Any] | None = None,
259
+ extra_curly: bool = True, # ignored. Just to be compatible with process_jinja2_template
260
+ settings: dict[str, Any] | None = None,
261
+ secret_reader: SecretReaderBase | None = None,
262
+ template_render_options: TemplateRenderOptions | None = None,
263
+ ) -> Any:
264
+ if vars is None:
265
+ vars = {}
266
+ return process_jinja2_template(
267
+ body,
268
+ vars=vars,
269
+ extra_curly=True,
270
+ settings=settings,
271
+ secret_reader=secret_reader,
272
+ template_render_options=template_render_options,
273
+ )
274
+
275
+
276
+ class FetchSecretError(Exception):
277
+ def __init__(self, msg: Any):
278
+ super().__init__("error fetching secret: " + str(msg))
@@ -1,3 +1,6 @@
1
+ from __future__ import annotations
2
+
3
+ import functools
1
4
  import logging
2
5
  from collections.abc import (
3
6
  Iterable,
@@ -5,7 +8,7 @@ from collections.abc import (
5
8
  )
6
9
  from typing import (
7
10
  Any,
8
- Optional,
11
+ Protocol,
9
12
  )
10
13
 
11
14
  from jira import (
@@ -13,38 +16,131 @@ from jira import (
13
16
  Issue,
14
17
  )
15
18
  from jira.client import ResultList
19
+ from pydantic import BaseModel
16
20
 
17
21
  from reconcile.utils.secret_reader import SecretReader
18
22
 
19
23
 
24
+ class JiraWatcherSettings(Protocol):
25
+ read_timeout: int
26
+ connect_timeout: int
27
+
28
+
29
+ class SecurityLevel(BaseModel):
30
+ """Jira security level."""
31
+
32
+ id: str
33
+ name: str
34
+
35
+
36
+ class Priority(BaseModel):
37
+ """Jira priority."""
38
+
39
+ id: str
40
+ name: str
41
+
42
+
43
+ class IssueType(BaseModel):
44
+ """Jira issue type."""
45
+
46
+ id: str
47
+ name: str
48
+ statuses: list[str]
49
+
50
+
20
51
  class JiraClient:
21
52
  """Wrapper around Jira client."""
22
53
 
54
+ DEFAULT_CONNECT_TIMEOUT = 60
55
+ DEFAULT_READ_TIMEOUT = 60
56
+
23
57
  def __init__(
24
- self, jira_board: Mapping[str, Any], settings: Optional[Mapping] = None
58
+ self,
59
+ jira_board: Mapping[str, Any] | None = None,
60
+ settings: Mapping | None = None,
61
+ jira_api: JIRA | None = None,
62
+ project: str | None = None,
63
+ server: str | None = None,
25
64
  ):
26
- self.secret_reader = SecretReader(settings=settings)
65
+ """
66
+ Note: jira_board and settings is to be deprecated. Use JiraClient.create() instead.
67
+ """
68
+ if jira_api and jira_board:
69
+ raise RuntimeError(
70
+ "jira_board parameter is deprecated. Use JiraClient.create() instead."
71
+ )
72
+ if not (jira_api and project):
73
+ # kept for backwards-compatibility
74
+ if not jira_board:
75
+ raise RuntimeError(
76
+ "JiraClient needs jira_api and project or jira_board."
77
+ )
78
+ self._deprecated_init(jira_board=jira_board, settings=settings)
79
+ return
80
+
81
+ self.server = server
82
+ self.project = project
83
+ self.jira = jira_api
84
+
85
+ # some caches
86
+ self.priorities = functools.lru_cache(maxsize=None)(self._priorities)
87
+ self.public_projects = functools.lru_cache(maxsize=None)(self._public_projects)
88
+ self.my_permissions = functools.lru_cache(maxsize=None)(self._my_permissions)
89
+
90
+ def _deprecated_init(
91
+ self, jira_board: Mapping[str, Any], settings: Mapping | None
92
+ ) -> None:
93
+ secret_reader = SecretReader(settings=settings)
27
94
  self.project = jira_board["name"]
28
95
  jira_server = jira_board["server"]
29
96
  self.server = jira_server["serverUrl"]
30
97
  token = jira_server["token"]
31
- token_auth = self.secret_reader.read(token)
98
+ token_auth = secret_reader.read(token)
32
99
  read_timeout = 60
33
100
  connect_timeout = 60
34
101
  if settings and settings["jiraWatcher"]:
35
102
  read_timeout = settings["jiraWatcher"]["readTimeout"]
36
103
  connect_timeout = settings["jiraWatcher"]["connectTimeout"]
104
+ if not self.server:
105
+ raise RuntimeError("JiraClient.server is not set.")
37
106
 
38
107
  self.jira = JIRA(
39
- self.server, token_auth=token_auth, timeout=(read_timeout, connect_timeout)
108
+ self.server,
109
+ token_auth=token_auth,
110
+ timeout=(read_timeout, connect_timeout),
111
+ logging=False,
40
112
  )
41
113
 
42
- def get_issues(self, fields: Optional[Mapping] = None) -> list[Issue]:
114
+ @staticmethod
115
+ def create(
116
+ project_name: str,
117
+ token: str,
118
+ server_url: str,
119
+ jira_watcher_settings: JiraWatcherSettings | None = None,
120
+ ) -> JiraClient:
121
+ read_timeout = JiraClient.DEFAULT_READ_TIMEOUT
122
+ connect_timeout = JiraClient.DEFAULT_CONNECT_TIMEOUT
123
+ if jira_watcher_settings:
124
+ read_timeout = jira_watcher_settings.read_timeout
125
+ connect_timeout = jira_watcher_settings.connect_timeout
126
+ jira_api = JIRA(
127
+ server=server_url,
128
+ token_auth=token,
129
+ timeout=(read_timeout, connect_timeout),
130
+ logging=False,
131
+ )
132
+ return JiraClient(
133
+ jira_api=jira_api,
134
+ project=project_name,
135
+ server=server_url,
136
+ )
137
+
138
+ def get_issues(self, fields: Mapping | None = None) -> list[Issue]:
43
139
  block_size = 100
44
140
  block_num = 0
45
141
 
46
142
  all_issues: list[Issue] = []
47
- jql = "project={}".format(self.project)
143
+ jql = f"project={self.project}"
48
144
  kwargs: dict[str, Any] = {}
49
145
  if fields:
50
146
  kwargs["fields"] = ",".join(fields)
@@ -72,7 +168,7 @@ class JiraClient:
72
168
  self,
73
169
  summary: str,
74
170
  body: str,
75
- labels: Optional[Iterable[str]] = None,
171
+ labels: Iterable[str] | None = None,
76
172
  links: Iterable[str] = (),
77
173
  ) -> Issue:
78
174
  """Create an issue in our project with the given labels."""
@@ -88,3 +184,64 @@ class JiraClient:
88
184
  type="is caused by", inwardIssue=issue.key, outwardIssue=ln
89
185
  )
90
186
  return issue
187
+
188
+ def _my_permissions(self, project: str) -> dict[str, Any]:
189
+ return self.jira.my_permissions(projectKey=project)["permissions"]
190
+
191
+ def can_i(self, permission: str) -> bool:
192
+ return bool(
193
+ self.my_permissions(project=self.project)[permission]["havePermission"]
194
+ )
195
+
196
+ def can_create_issues(self) -> bool:
197
+ return self.can_i("CREATE_ISSUES")
198
+
199
+ def can_transition_issues(self) -> bool:
200
+ return self.can_i("TRANSITION_ISSUES")
201
+
202
+ def project_issue_types(self) -> list[IssueType]:
203
+ return [
204
+ IssueType(id=t.id, name=t.name, statuses=[s.name for s in t.statuses])
205
+ for t in self.jira.issue_types_for_project(self.project)
206
+ ]
207
+
208
+ def security_levels(self) -> list[SecurityLevel]:
209
+ """Return a list of all available security levels for the project.
210
+
211
+ This API endpoint needs admin/owner project permissions.
212
+ """
213
+ scheme = self.jira.project_issue_security_level_scheme(self.project)
214
+ return [SecurityLevel(id=level.id, name=level.name) for level in scheme.levels]
215
+
216
+ def _priorities(self) -> list[Priority]:
217
+ """Return a list of all available Jira priorities."""
218
+ return [Priority(id=p.id, name=p.name) for p in self.jira.priorities()]
219
+
220
+ def project_priority_scheme(self) -> list[str]:
221
+ """Return a list of all priority IDs for the project."""
222
+ scheme = self.jira.project_priority_scheme(self.project)
223
+ return scheme.optionIds
224
+
225
+ def _public_projects(self) -> list[str]:
226
+ """Return a list of all public available projects."""
227
+ if not self.server:
228
+ raise RuntimeError("JiraClient.server is not set.")
229
+
230
+ # use anonymous access to get public projects
231
+ jira_api_anon = JIRA(
232
+ server=self.server,
233
+ timeout=(
234
+ JiraClient.DEFAULT_READ_TIMEOUT,
235
+ JiraClient.DEFAULT_CONNECT_TIMEOUT,
236
+ ),
237
+ logging=False,
238
+ )
239
+ return [project.key for project in jira_api_anon.projects()]
240
+
241
+ def components(self) -> list[str]:
242
+ """Return a list of all components for the project."""
243
+ return [c.name for c in self.jira.project_components(self.project)]
244
+
245
+ @property
246
+ def is_archived(self) -> bool:
247
+ return self.jira.project(self.project).archived
@@ -14,10 +14,7 @@ from subprocess import (
14
14
  STDOUT,
15
15
  CalledProcessError,
16
16
  )
17
- from typing import (
18
- Any,
19
- Optional,
20
- )
17
+ from typing import Any
21
18
 
22
19
  import yaml
23
20
  from jenkins_jobs.builder import JenkinsManager
@@ -63,8 +60,8 @@ class JJB: # pylint: disable=too-many-public-methods
63
60
  ini = self.secret_reader.read(token)
64
61
  ini = ini.replace('"', "")
65
62
  ini = ini.replace("false", "False")
66
- ini_file_path = "{}/{}.ini".format(wd, name)
67
- with open(ini_file_path, "w") as f:
63
+ ini_file_path = f"{wd}/{name}.ini"
64
+ with open(ini_file_path, "w", encoding="locale") as f:
68
65
  f.write(ini)
69
66
  f.write("\n")
70
67
  working_dirs[name] = wd
@@ -75,14 +72,18 @@ class JJB: # pylint: disable=too-many-public-methods
75
72
  for c in configs:
76
73
  instance_name = c["instance"]["name"]
77
74
  config = c["config"]
78
- config_file_path = "{}/config.yaml".format(working_dirs[instance_name])
75
+ config_file_path = f"{working_dirs[instance_name]}/config.yaml"
79
76
  if config:
80
- with open(config_file_path, "a") as f:
81
- yaml.dump(yaml.load(config, Loader=yaml.FullLoader), f)
77
+ content = yaml.load(config, Loader=yaml.FullLoader)
78
+ if c["type"] == "jobs":
79
+ for item in content:
80
+ item["project"]["app_name"] = c["app"]["name"]
81
+ with open(config_file_path, "a", encoding="locale") as f:
82
+ yaml.dump(content, f)
82
83
  f.write("\n")
83
84
  else:
84
85
  config = c["config_path"]["content"]
85
- with open(config_file_path, "a") as f:
86
+ with open(config_file_path, "a", encoding="locale") as f:
86
87
  f.write(config)
87
88
  f.write("\n")
88
89
 
@@ -95,8 +96,8 @@ class JJB: # pylint: disable=too-many-public-methods
95
96
  config files in the working directories with
96
97
  the supplied configs"""
97
98
  for name, wd in self.working_dirs.items():
98
- config_path = "{}/config.yaml".format(wd)
99
- with open(config_path, "w") as f:
99
+ config_path = f"{wd}/config.yaml"
100
+ with open(config_path, "w", encoding="locale") as f:
100
101
  f.write(configs[name])
101
102
 
102
103
  def sort(self, configs):
@@ -131,8 +132,8 @@ class JJB: # pylint: disable=too-many-public-methods
131
132
  working directories"""
132
133
  configs = {}
133
134
  for name, wd in self.working_dirs.items():
134
- config_path = "{}/config.yaml".format(wd)
135
- with open(config_path, "r") as f:
135
+ config_path = f"{wd}/config.yaml"
136
+ with open(config_path, encoding="locale") as f:
136
137
  configs[name] = f.read()
137
138
 
138
139
  return configs
@@ -145,8 +146,8 @@ class JJB: # pylint: disable=too-many-public-methods
145
146
  :param fetch_state: subdirectory to use ('desired' or 'current')
146
147
  """
147
148
  for name, wd in self.working_dirs.items():
148
- ini_path = "{}/{}.ini".format(wd, name)
149
- config_path = "{}/config.yaml".format(wd)
149
+ ini_path = f"{wd}/{name}.ini"
150
+ config_path = f"{wd}/config.yaml"
150
151
 
151
152
  output_dir = path.join(io_dir, "jjb", fetch_state, name)
152
153
  args = [
@@ -192,7 +193,7 @@ class JJB: # pylint: disable=too-many-public-methods
192
193
  logging.info([action, item_type, instance, item])
193
194
 
194
195
  if action == "update":
195
- with open(ft) as c, open(f) as d:
196
+ with open(ft, encoding="locale") as c, open(f, encoding="locale") as d:
196
197
  clines = c.readlines()
197
198
  dlines = d.readlines()
198
199
 
@@ -223,8 +224,8 @@ class JJB: # pylint: disable=too-many-public-methods
223
224
 
224
225
  def update(self) -> None:
225
226
  for name, wd in self.working_dirs.items():
226
- ini_path = "{}/{}.ini".format(wd, name)
227
- config_path = "{}/config.yaml".format(wd)
227
+ ini_path = f"{wd}/{name}.ini"
228
+ config_path = f"{wd}/config.yaml"
228
229
 
229
230
  os.environ["PYTHONHTTPSVERIFY"] = self.python_https_verify
230
231
  cmd = ["jenkins-jobs", "--conf", ini_path, "update", config_path]
@@ -243,7 +244,7 @@ class JJB: # pylint: disable=too-many-public-methods
243
244
 
244
245
  @staticmethod
245
246
  def get_jjb(args):
246
- from jenkins_jobs.cli.entry import JenkinsJobs
247
+ from jenkins_jobs.cli.entry import JenkinsJobs # noqa: PLC0415
247
248
 
248
249
  return JenkinsJobs(args)
249
250
 
@@ -264,8 +265,8 @@ class JJB: # pylint: disable=too-many-public-methods
264
265
 
265
266
  @retry(exceptions=(JenkinsJobsException))
266
267
  def get_jobs(self, wd, name):
267
- ini_path = "{}/{}.ini".format(wd, name)
268
- config_path = "{}/config.yaml".format(wd)
268
+ ini_path = f"{wd}/{name}.ini"
269
+ config_path = f"{wd}/config.yaml"
269
270
 
270
271
  args = ["--conf", ini_path, "test", config_path]
271
272
  jjb = self.get_jjb(args)
@@ -287,13 +288,15 @@ class JJB: # pylint: disable=too-many-public-methods
287
288
  project_url_raw = job["properties"][0]["github"]["url"]
288
289
  if "https://github.com" in project_url_raw:
289
290
  continue
291
+ if str(job.get("disabled")).lower() == "true":
292
+ continue
290
293
  job_url = "{}/project/{}".format(
291
294
  self.instance_urls[name], job["name"]
292
295
  )
293
296
  project_url = project_url_raw.strip("/").replace(".git", "")
294
- gitlab_triggers = job["triggers"][0]["gitlab"]
295
- mr_trigger = gitlab_triggers["trigger-merge-request"]
296
- trigger = "mr" if mr_trigger else "push"
297
+ trigger = self.get_gitlab_webhook_trigger(job)
298
+ if not trigger:
299
+ continue
297
300
  hook = {
298
301
  "job_url": job_url,
299
302
  "trigger": trigger,
@@ -314,7 +317,7 @@ class JJB: # pylint: disable=too-many-public-methods
314
317
  try:
315
318
  repos.add(self.get_repo_url(job))
316
319
  except KeyError:
317
- logging.debug("missing github url: {}".format(job_name))
320
+ logging.debug(f"missing github url: {job_name}")
318
321
  return repos
319
322
 
320
323
  def get_admins(self):
@@ -340,9 +343,7 @@ class JJB: # pylint: disable=too-many-public-methods
340
343
  def get_ref(job: dict) -> str:
341
344
  return job["scm"][0]["git"]["branches"][0]
342
345
 
343
- def get_all_jobs(
344
- self, job_types=None, instance_name=None, include_test=False
345
- ) -> dict[str, list[dict]]:
346
+ def get_all_jobs(self, job_types=None, instance_name=None) -> dict[str, list[dict]]:
346
347
  if job_types is None:
347
348
  job_types = []
348
349
  all_jobs: dict[str, list[dict]] = {}
@@ -356,11 +357,6 @@ class JJB: # pylint: disable=too-many-public-methods
356
357
  job_name = job["name"]
357
358
  if not any(job_type in job_name for job_type in job_types):
358
359
  continue
359
- if not include_test and "test" in job_name:
360
- continue
361
- # temporarily ignore openshift-saas-deploy jobs
362
- if job_name.startswith("openshift-saas-deploy"):
363
- continue
364
360
  all_jobs[name].append(job)
365
361
 
366
362
  return all_jobs
@@ -393,10 +389,26 @@ class JJB: # pylint: disable=too-many-public-methods
393
389
  raise ValueError(f"job with {job_type=} and {repo_url=} not found")
394
390
 
395
391
  @staticmethod
396
- def get_trigger_phrases_regex(job: dict) -> Optional[str]:
392
+ def get_trigger_phrases_regex(job: dict) -> str | None:
397
393
  for trigger in job["triggers"]:
398
394
  if "gitlab" in trigger:
399
395
  return trigger["gitlab"].get("note-regex")
400
396
  if "github-pull-request" in trigger:
401
397
  return trigger["github-pull-request"].get("trigger-phrase")
402
398
  return None
399
+
400
+ @staticmethod
401
+ def get_gitlab_webhook_trigger(job: dict) -> list[str]:
402
+ gitlab_triggers = job["triggers"][0]["gitlab"]
403
+ # pr-check job should be triggered by merge request events
404
+ # and certain comments: [test]|/retest|/lgtm|/lgtm cancel|/hold|/hold cancel
405
+ if gitlab_triggers.get("trigger-merge-request"):
406
+ return ["mr", "note"]
407
+ # build main/master job should be triggered by push events
408
+ elif gitlab_triggers.get("trigger-push"):
409
+ return ["push"]
410
+ # On-demand test job should be triggered by special comment
411
+ elif gitlab_triggers.get("trigger-note"):
412
+ return ["note"]
413
+ else:
414
+ return []
File without changes