qontract-reconcile 0.10.2.dev361__py3-none-any.whl → 0.10.2.dev474__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 (371) hide show
  1. {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/METADATA +14 -13
  2. {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/RECORD +371 -364
  3. {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/WHEEL +1 -1
  4. reconcile/acs_rbac.py +2 -2
  5. reconcile/aus/advanced_upgrade_service.py +18 -12
  6. reconcile/aus/aus_sts_gate_handler.py +59 -0
  7. reconcile/aus/base.py +137 -34
  8. reconcile/aus/cluster_version_data.py +15 -5
  9. reconcile/aus/models.py +3 -1
  10. reconcile/aus/ocm_addons_upgrade_scheduler_org.py +1 -0
  11. reconcile/aus/ocm_upgrade_scheduler.py +8 -1
  12. reconcile/aus/ocm_upgrade_scheduler_org.py +20 -5
  13. reconcile/aus/version_gate_approver.py +1 -16
  14. reconcile/aus/version_gates/sts_version_gate_handler.py +5 -72
  15. reconcile/automated_actions/config/integration.py +16 -4
  16. reconcile/aws_account_manager/integration.py +21 -9
  17. reconcile/aws_account_manager/reconciler.py +3 -3
  18. reconcile/aws_account_manager/utils.py +1 -1
  19. reconcile/aws_ami_cleanup/integration.py +8 -12
  20. reconcile/aws_ami_share.py +69 -62
  21. reconcile/aws_cloudwatch_log_retention/integration.py +155 -126
  22. reconcile/aws_ecr_image_pull_secrets.py +1 -1
  23. reconcile/aws_iam_keys.py +1 -0
  24. reconcile/aws_saml_idp/integration.py +12 -4
  25. reconcile/aws_saml_roles/integration.py +30 -23
  26. reconcile/aws_version_sync/integration.py +6 -12
  27. reconcile/change_owners/README.md +1 -1
  28. reconcile/change_owners/bundle.py +3 -3
  29. reconcile/change_owners/change_log_tracking.py +3 -2
  30. reconcile/change_owners/change_owners.py +108 -42
  31. reconcile/change_owners/decision.py +1 -1
  32. reconcile/change_owners/diff.py +0 -2
  33. reconcile/checkpoint.py +11 -3
  34. reconcile/cli.py +94 -11
  35. reconcile/dashdotdb_dora.py +5 -12
  36. reconcile/dashdotdb_slo.py +1 -1
  37. reconcile/database_access_manager.py +123 -117
  38. reconcile/dynatrace_token_provider/integration.py +1 -1
  39. reconcile/endpoints_discovery/integration.py +4 -1
  40. reconcile/endpoints_discovery/merge_request.py +1 -1
  41. reconcile/endpoints_discovery/merge_request_manager.py +8 -8
  42. reconcile/external_resources/factories.py +4 -6
  43. reconcile/external_resources/integration.py +1 -1
  44. reconcile/external_resources/manager.py +8 -6
  45. reconcile/external_resources/meta.py +0 -1
  46. reconcile/external_resources/metrics.py +1 -1
  47. reconcile/external_resources/model.py +19 -15
  48. reconcile/external_resources/reconciler.py +7 -4
  49. reconcile/external_resources/secrets_sync.py +6 -10
  50. reconcile/external_resources/state.py +26 -16
  51. reconcile/fleet_labeler/integration.py +1 -1
  52. reconcile/gabi_authorized_users.py +5 -2
  53. reconcile/gcp_image_mirror.py +2 -2
  54. reconcile/github_org.py +1 -1
  55. reconcile/github_owners.py +4 -0
  56. reconcile/gitlab_housekeeping.py +13 -15
  57. reconcile/gitlab_members.py +6 -12
  58. reconcile/gitlab_owners.py +15 -11
  59. reconcile/gitlab_permissions.py +8 -12
  60. reconcile/glitchtip_project_alerts/integration.py +3 -1
  61. reconcile/gql_definitions/acs/acs_instances.py +5 -5
  62. reconcile/gql_definitions/acs/acs_policies.py +5 -5
  63. reconcile/gql_definitions/acs/acs_rbac.py +5 -5
  64. reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +5 -5
  65. reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +5 -5
  66. reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +5 -5
  67. reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
  68. reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
  69. reconcile/gql_definitions/automated_actions/instance.py +46 -7
  70. reconcile/gql_definitions/aws_account_manager/aws_accounts.py +14 -5
  71. reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +15 -5
  72. reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +27 -66
  73. reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +15 -5
  74. reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +15 -5
  75. reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
  76. reconcile/gql_definitions/aws_version_sync/clusters.py +5 -5
  77. reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
  78. reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
  79. reconcile/gql_definitions/change_owners/queries/self_service_roles.py +5 -5
  80. reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +5 -5
  81. reconcile/gql_definitions/common/alerting_services_settings.py +5 -5
  82. reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
  83. reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
  84. reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
  85. reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
  86. reconcile/gql_definitions/common/app_interface_roles.py +5 -5
  87. reconcile/gql_definitions/common/app_interface_state_settings.py +5 -5
  88. reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
  89. reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
  90. reconcile/gql_definitions/common/apps.py +5 -5
  91. reconcile/gql_definitions/common/aws_vpc_requests.py +18 -5
  92. reconcile/gql_definitions/common/aws_vpcs.py +5 -5
  93. reconcile/gql_definitions/common/clusters.py +7 -5
  94. reconcile/gql_definitions/common/clusters_minimal.py +5 -5
  95. reconcile/gql_definitions/common/clusters_with_dms.py +5 -5
  96. reconcile/gql_definitions/common/clusters_with_peering.py +5 -5
  97. reconcile/gql_definitions/common/github_orgs.py +5 -5
  98. reconcile/gql_definitions/common/jira_settings.py +5 -5
  99. reconcile/gql_definitions/common/jiralert_settings.py +5 -5
  100. reconcile/gql_definitions/common/ldap_settings.py +5 -5
  101. reconcile/gql_definitions/common/namespaces.py +5 -5
  102. reconcile/gql_definitions/common/namespaces_minimal.py +7 -5
  103. reconcile/gql_definitions/common/ocm_env_telemeter.py +5 -5
  104. reconcile/gql_definitions/common/ocm_environments.py +5 -5
  105. reconcile/gql_definitions/common/pagerduty_instances.py +5 -5
  106. reconcile/gql_definitions/common/pgp_reencryption_settings.py +5 -5
  107. reconcile/gql_definitions/common/pipeline_providers.py +5 -5
  108. reconcile/gql_definitions/common/quay_instances.py +5 -5
  109. reconcile/gql_definitions/common/quay_orgs.py +5 -5
  110. reconcile/gql_definitions/common/reserved_networks.py +5 -5
  111. reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
  112. reconcile/gql_definitions/common/saas_files.py +5 -5
  113. reconcile/gql_definitions/common/saas_target_namespaces.py +5 -5
  114. reconcile/gql_definitions/common/saasherder_settings.py +5 -5
  115. reconcile/gql_definitions/common/slack_workspaces.py +5 -5
  116. reconcile/gql_definitions/common/smtp_client_settings.py +5 -5
  117. reconcile/gql_definitions/common/state_aws_account.py +5 -5
  118. reconcile/gql_definitions/common/users.py +5 -5
  119. reconcile/gql_definitions/common/users_with_paths.py +5 -5
  120. reconcile/gql_definitions/cost_report/app_names.py +5 -5
  121. reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
  122. reconcile/gql_definitions/cost_report/settings.py +5 -5
  123. reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +5 -5
  124. reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +5 -5
  125. reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
  126. reconcile/gql_definitions/email_sender/apps.py +5 -5
  127. reconcile/gql_definitions/email_sender/emails.py +5 -5
  128. reconcile/gql_definitions/email_sender/users.py +5 -5
  129. reconcile/gql_definitions/endpoints_discovery/apps.py +5 -5
  130. reconcile/gql_definitions/external_resources/aws_accounts.py +5 -5
  131. reconcile/gql_definitions/external_resources/external_resources_modules.py +5 -5
  132. reconcile/gql_definitions/external_resources/external_resources_namespaces.py +38 -7
  133. reconcile/gql_definitions/external_resources/external_resources_settings.py +5 -5
  134. reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
  135. reconcile/gql_definitions/fleet_labeler/fleet_labels.py +5 -5
  136. reconcile/gql_definitions/fragments/aus_organization.py +5 -5
  137. reconcile/gql_definitions/fragments/aws_account_common.py +7 -5
  138. reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
  139. reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
  140. reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
  141. reconcile/gql_definitions/fragments/aws_organization.py +33 -0
  142. reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
  143. reconcile/gql_definitions/fragments/aws_vpc_request.py +12 -5
  144. reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
  145. reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
  146. reconcile/gql_definitions/fragments/disable.py +5 -5
  147. reconcile/gql_definitions/fragments/email_service.py +5 -5
  148. reconcile/gql_definitions/fragments/email_user.py +5 -5
  149. reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
  150. reconcile/gql_definitions/fragments/membership_source.py +5 -5
  151. reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
  152. reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
  153. reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
  154. reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
  155. reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
  156. reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
  157. reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
  158. reconcile/gql_definitions/fragments/resource_values.py +5 -5
  159. reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
  160. reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
  161. reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
  162. reconcile/gql_definitions/fragments/terraform_state.py +5 -5
  163. reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
  164. reconcile/gql_definitions/fragments/user.py +5 -5
  165. reconcile/gql_definitions/fragments/vault_secret.py +5 -5
  166. reconcile/gql_definitions/gcp/gcp_docker_repos.py +5 -5
  167. reconcile/gql_definitions/gcp/gcp_projects.py +5 -5
  168. reconcile/gql_definitions/gitlab_members/gitlab_instances.py +5 -5
  169. reconcile/gql_definitions/gitlab_members/permissions.py +5 -5
  170. reconcile/gql_definitions/glitchtip/glitchtip_instance.py +5 -5
  171. reconcile/gql_definitions/glitchtip/glitchtip_project.py +5 -5
  172. reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +5 -5
  173. reconcile/gql_definitions/integrations/integrations.py +5 -5
  174. reconcile/gql_definitions/introspection.json +775 -136
  175. reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +5 -5
  176. reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +5 -5
  177. reconcile/gql_definitions/jira/jira_servers.py +5 -5
  178. reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +9 -5
  179. reconcile/gql_definitions/jumphosts/jumphosts.py +5 -5
  180. reconcile/gql_definitions/ldap_groups/roles.py +5 -5
  181. reconcile/gql_definitions/ldap_groups/settings.py +5 -5
  182. reconcile/gql_definitions/maintenance/maintenances.py +5 -5
  183. reconcile/gql_definitions/membershipsources/roles.py +5 -5
  184. reconcile/gql_definitions/ocm_labels/clusters.py +5 -5
  185. reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
  186. reconcile/gql_definitions/openshift_cluster_bots/clusters.py +5 -5
  187. reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
  188. reconcile/gql_definitions/openshift_groups/managed_roles.py +5 -5
  189. reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +5 -5
  190. reconcile/gql_definitions/quay_membership/quay_membership.py +5 -5
  191. reconcile/gql_definitions/rhcs/certs.py +25 -79
  192. reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +43 -0
  193. reconcile/gql_definitions/rhidp/organizations.py +5 -5
  194. reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
  195. reconcile/gql_definitions/service_dependencies/service_dependencies.py +5 -5
  196. reconcile/gql_definitions/sharding/aws_accounts.py +5 -5
  197. reconcile/gql_definitions/sharding/ocm_organization.py +5 -5
  198. reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
  199. reconcile/gql_definitions/skupper_network/skupper_networks.py +5 -5
  200. reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
  201. reconcile/gql_definitions/slack_usergroups/permissions.py +5 -5
  202. reconcile/gql_definitions/slack_usergroups/users.py +5 -5
  203. reconcile/gql_definitions/slo_documents/slo_documents.py +5 -5
  204. reconcile/gql_definitions/status_board/status_board.py +5 -5
  205. reconcile/gql_definitions/statuspage/statuspages.py +5 -5
  206. reconcile/gql_definitions/templating/template_collection.py +5 -5
  207. reconcile/gql_definitions/templating/templates.py +5 -5
  208. reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +5 -5
  209. reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +5 -5
  210. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +5 -5
  211. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +5 -5
  212. reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +5 -5
  213. reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +5 -5
  214. reconcile/gql_definitions/terraform_init/aws_accounts.py +19 -5
  215. reconcile/gql_definitions/terraform_repo/terraform_repo.py +5 -5
  216. reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
  217. reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +37 -7
  218. reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +15 -5
  219. reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +5 -5
  220. reconcile/gql_definitions/vault_instances/vault_instances.py +5 -5
  221. reconcile/gql_definitions/vault_policies/vault_policies.py +5 -5
  222. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +8 -5
  223. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +6 -5
  224. reconcile/integrations_manager.py +3 -3
  225. reconcile/jenkins_worker_fleets.py +10 -8
  226. reconcile/jira_permissions_validator.py +237 -122
  227. reconcile/ldap_groups/integration.py +1 -1
  228. reconcile/ocm/types.py +35 -57
  229. reconcile/ocm_aws_infrastructure_access.py +1 -1
  230. reconcile/ocm_clusters.py +4 -4
  231. reconcile/ocm_labels/integration.py +3 -2
  232. reconcile/ocm_machine_pools.py +33 -27
  233. reconcile/openshift_base.py +113 -4
  234. reconcile/openshift_cluster_bots.py +1 -1
  235. reconcile/openshift_namespace_labels.py +1 -1
  236. reconcile/openshift_namespaces.py +96 -101
  237. reconcile/openshift_resources_base.py +6 -2
  238. reconcile/openshift_rhcs_certs.py +74 -37
  239. reconcile/openshift_rolebindings.py +7 -11
  240. reconcile/openshift_saas_deploy.py +4 -5
  241. reconcile/openshift_saas_deploy_change_tester.py +9 -7
  242. reconcile/openshift_saas_deploy_trigger_cleaner.py +3 -5
  243. reconcile/openshift_serviceaccount_tokens.py +2 -2
  244. reconcile/openshift_upgrade_watcher.py +4 -4
  245. reconcile/oum/labelset.py +5 -3
  246. reconcile/oum/models.py +1 -4
  247. reconcile/prometheus_rules_tester/integration.py +3 -3
  248. reconcile/quay_base.py +25 -6
  249. reconcile/quay_membership.py +55 -29
  250. reconcile/quay_mirror.py +1 -1
  251. reconcile/quay_mirror_org.py +6 -4
  252. reconcile/quay_permissions.py +81 -75
  253. reconcile/quay_repos.py +35 -37
  254. reconcile/queries.py +132 -1
  255. reconcile/rhidp/common.py +3 -5
  256. reconcile/rhidp/sso_client/base.py +16 -5
  257. reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
  258. reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
  259. reconcile/skupper_network/integration.py +2 -2
  260. reconcile/slack_usergroups.py +35 -14
  261. reconcile/sql_query.py +1 -0
  262. reconcile/status_board.py +6 -6
  263. reconcile/statuspage/atlassian.py +7 -7
  264. reconcile/statuspage/integrations/maintenances.py +4 -3
  265. reconcile/statuspage/page.py +4 -9
  266. reconcile/statuspage/status.py +5 -8
  267. reconcile/templates/rosa-classic-cluster-creation.sh.j2 +1 -1
  268. reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +1 -1
  269. reconcile/templating/lib/rendering.py +3 -3
  270. reconcile/templating/renderer.py +2 -2
  271. reconcile/templating/validator.py +4 -4
  272. reconcile/terraform_aws_route53.py +7 -1
  273. reconcile/terraform_cloudflare_dns.py +3 -3
  274. reconcile/terraform_cloudflare_resources.py +5 -5
  275. reconcile/terraform_cloudflare_users.py +3 -2
  276. reconcile/terraform_init/integration.py +187 -23
  277. reconcile/terraform_repo.py +16 -12
  278. reconcile/terraform_resources.py +6 -6
  279. reconcile/terraform_tgw_attachments.py +27 -19
  280. reconcile/terraform_users.py +7 -0
  281. reconcile/terraform_vpc_peerings.py +14 -3
  282. reconcile/terraform_vpc_resources/integration.py +20 -8
  283. reconcile/terraform_vpc_resources/merge_request.py +12 -2
  284. reconcile/terraform_vpc_resources/merge_request_manager.py +43 -19
  285. reconcile/typed_queries/aws_account_tags.py +41 -0
  286. reconcile/typed_queries/cost_report/app_names.py +1 -1
  287. reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
  288. reconcile/typed_queries/saas_files.py +20 -15
  289. reconcile/typed_queries/status_board.py +2 -2
  290. reconcile/unleash_feature_toggles/integration.py +4 -2
  291. reconcile/utils/acs/base.py +6 -3
  292. reconcile/utils/acs/policies.py +2 -2
  293. reconcile/utils/aws_api.py +51 -20
  294. reconcile/utils/aws_api_typed/api.py +38 -9
  295. reconcile/utils/aws_api_typed/cloudformation.py +149 -0
  296. reconcile/utils/aws_api_typed/logs.py +73 -0
  297. reconcile/utils/aws_api_typed/organization.py +4 -2
  298. reconcile/utils/binary.py +7 -12
  299. reconcile/utils/datetime_util.py +67 -0
  300. reconcile/utils/deadmanssnitch_api.py +1 -1
  301. reconcile/utils/differ.py +2 -3
  302. reconcile/utils/early_exit_cache.py +11 -12
  303. reconcile/utils/environ.py +5 -0
  304. reconcile/utils/expiration.py +7 -3
  305. reconcile/utils/external_resource_spec.py +2 -0
  306. reconcile/utils/filtering.py +1 -1
  307. reconcile/utils/gitlab_api.py +19 -5
  308. reconcile/utils/glitchtip/client.py +6 -2
  309. reconcile/utils/glitchtip/models.py +25 -28
  310. reconcile/utils/gql.py +4 -7
  311. reconcile/utils/helpers.py +1 -1
  312. reconcile/utils/instrumented_wrappers.py +1 -1
  313. reconcile/utils/internal_groups/client.py +2 -2
  314. reconcile/utils/internal_groups/models.py +8 -17
  315. reconcile/utils/jinja2/utils.py +6 -101
  316. reconcile/utils/jira_client.py +82 -63
  317. reconcile/utils/jjb_client.py +26 -13
  318. reconcile/utils/jobcontroller/controller.py +2 -2
  319. reconcile/utils/jobcontroller/models.py +17 -1
  320. reconcile/utils/json.py +43 -1
  321. reconcile/utils/membershipsources/app_interface_resolver.py +4 -2
  322. reconcile/utils/membershipsources/models.py +16 -23
  323. reconcile/utils/membershipsources/resolver.py +4 -2
  324. reconcile/utils/merge_request_manager/merge_request_manager.py +4 -4
  325. reconcile/utils/merge_request_manager/parser.py +6 -6
  326. reconcile/utils/metrics.py +5 -5
  327. reconcile/utils/models.py +304 -82
  328. reconcile/utils/mr/app_interface_reporter.py +2 -2
  329. reconcile/utils/mr/notificator.py +3 -3
  330. reconcile/utils/mr/update_access_report_base.py +3 -4
  331. reconcile/utils/mr/user_maintenance.py +3 -2
  332. reconcile/utils/oc.py +252 -201
  333. reconcile/utils/oc_filters.py +3 -3
  334. reconcile/utils/ocm/addons.py +0 -1
  335. reconcile/utils/ocm/base.py +17 -20
  336. reconcile/utils/ocm/cluster_groups.py +1 -1
  337. reconcile/utils/ocm/identity_providers.py +2 -2
  338. reconcile/utils/ocm/labels.py +1 -1
  339. reconcile/utils/ocm/products.py +8 -8
  340. reconcile/utils/ocm/search_filters.py +3 -6
  341. reconcile/utils/ocm/service_log.py +4 -6
  342. reconcile/utils/ocm/sre_capability_labels.py +20 -13
  343. reconcile/utils/openshift_resource.py +8 -3
  344. reconcile/utils/pagerduty_api.py +10 -7
  345. reconcile/utils/promotion_state.py +6 -11
  346. reconcile/utils/quay_api.py +74 -87
  347. reconcile/utils/raw_github_api.py +1 -1
  348. reconcile/utils/rhcsv2_certs.py +86 -23
  349. reconcile/utils/rosa/session.py +16 -0
  350. reconcile/utils/runtime/integration.py +2 -3
  351. reconcile/utils/runtime/runner.py +2 -2
  352. reconcile/utils/saasherder/interfaces.py +13 -20
  353. reconcile/utils/saasherder/models.py +23 -20
  354. reconcile/utils/saasherder/saasherder.py +50 -27
  355. reconcile/utils/slack_api.py +2 -2
  356. reconcile/utils/sloth.py +171 -2
  357. reconcile/utils/structs.py +1 -1
  358. reconcile/utils/terraform_client.py +5 -4
  359. reconcile/utils/terrascript_aws_client.py +274 -124
  360. reconcile/utils/unleash/server.py +2 -8
  361. reconcile/utils/vault.py +5 -12
  362. reconcile/utils/vcs.py +8 -8
  363. reconcile/vault_replication.py +107 -42
  364. reconcile/vpc_peerings_validator.py +13 -0
  365. tools/app_interface_reporter.py +4 -4
  366. tools/cli_commands/cost_report/cost_management_api.py +3 -3
  367. tools/cli_commands/cost_report/view.py +7 -6
  368. tools/cli_commands/erv2.py +1 -1
  369. tools/qontract_cli.py +28 -17
  370. tools/template_validation.py +3 -1
  371. {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/entry_points.txt +0 -0
@@ -10,7 +10,7 @@ from reconcile.gql_definitions.quay_membership.quay_membership import (
10
10
  PermissionQuayOrgTeamV1,
11
11
  UserV1,
12
12
  )
13
- from reconcile.quay_base import QuayApiStore, get_quay_api_store
13
+ from reconcile.quay_base import OrgKey, QuayApiStore
14
14
  from reconcile.status import ExitCodes
15
15
  from reconcile.utils import (
16
16
  expiration,
@@ -58,10 +58,11 @@ def fetch_current_state(quay_api_store: QuayApiStore) -> AggregatedList:
58
58
  state = AggregatedList()
59
59
 
60
60
  for org_key, org_data in quay_api_store.items():
61
- quay_api = org_data["api"]
62
61
  teams = org_data["teams"]
63
62
  if not teams:
64
63
  continue
64
+
65
+ quay_api = org_data["api"]
65
66
  for team in teams:
66
67
  try:
67
68
  members = quay_api.list_team_members(team)
@@ -76,8 +77,13 @@ def fetch_current_state(quay_api_store: QuayApiStore) -> AggregatedList:
76
77
  else:
77
78
  # Teams are only added to the state if they exist so that
78
79
  # there is a proper diff between the desired and current state.
80
+ # Use tuple format (instance, org_name) to match desired state format
79
81
  state.add(
80
- {"service": "quay-membership", "org": org_key, "team": team},
82
+ {
83
+ "service": "quay-membership",
84
+ "org": (org_key.instance, org_key.org_name),
85
+ "team": team,
86
+ },
81
87
  members,
82
88
  )
83
89
  return state
@@ -117,9 +123,16 @@ class RunnerAction:
117
123
  def action(params: dict, items: list) -> bool:
118
124
  org = params["org"]
119
125
  team = params["team"]
126
+ # Convert org tuple (instance, org_name) to OrgKey for lookup
127
+ org_key = (
128
+ OrgKey(org[0], org[1])
129
+ if isinstance(org, tuple)
130
+ else OrgKey("quay.io", org)
131
+ )
132
+ org_data = self.quay_api_store[org_key]
133
+ quay_api = org_data["api"]
120
134
 
121
135
  missing_users = False
122
- quay_api = self.quay_api_store[org]["api"]
123
136
  for member in items:
124
137
  logging.info([label, member, org, team])
125
138
  user_exists = quay_api.user_exists(member)
@@ -147,19 +160,26 @@ class RunnerAction:
147
160
  def action(params: dict, items: list) -> bool:
148
161
  org = params["org"]
149
162
  team = params["team"]
163
+ # Convert org tuple (instance, org_name) to OrgKey for lookup
164
+ org_key = (
165
+ OrgKey(org[0], org[1])
166
+ if isinstance(org, tuple)
167
+ else OrgKey("quay.io", org)
168
+ )
169
+ org_data = self.quay_api_store[org_key]
150
170
 
151
171
  # Ensure all quay org/teams are declared as dependencies in a
152
172
  # `/dependencies/quay-org-1.yml` datafile.
153
- if team not in self.quay_api_store[org]["teams"]:
173
+ if team not in org_data["teams"]:
154
174
  raise RunnerError(
155
175
  f"Quay team {team} is not defined as a "
156
- f"managedTeam in the {org} org."
176
+ f"managedTeam in the {org_key.org_name} org."
157
177
  )
158
178
 
159
179
  logging.info([label, org, team])
160
180
 
161
181
  if not self.dry_run:
162
- quay_api = self.quay_api_store[org]["api"]
182
+ quay_api = org_data["api"]
163
183
  quay_api.create_or_update_team(team)
164
184
 
165
185
  return True
@@ -172,12 +192,19 @@ class RunnerAction:
172
192
  def action(params: dict, items: list) -> bool:
173
193
  org = params["org"]
174
194
  team = params["team"]
195
+ # Convert org tuple (instance, org_name) to OrgKey for lookup
196
+ org_key = (
197
+ OrgKey(org[0], org[1])
198
+ if isinstance(org, tuple)
199
+ else OrgKey("quay.io", org)
200
+ )
201
+ org_data = self.quay_api_store[org_key]
175
202
 
203
+ quay_api = org_data["api"]
176
204
  if self.dry_run:
177
205
  for member in items:
178
206
  logging.info([label, member, org, team])
179
207
  else:
180
- quay_api = self.quay_api_store[org]["api"]
181
208
  for member in items:
182
209
  logging.info([label, member, org, team])
183
210
  quay_api.remove_user_from_team(member, team)
@@ -188,24 +215,23 @@ class RunnerAction:
188
215
 
189
216
 
190
217
  def run(dry_run: bool) -> None:
191
- quay_api_store = get_quay_api_store()
192
-
193
- current_state = fetch_current_state(quay_api_store)
194
- desired_state = fetch_desired_state()
195
-
196
- # calculate diff
197
- diff = current_state.diff(desired_state)
198
- logging.debug("State diff: %s", diff)
199
-
200
- # Run actions
201
- runner_action = RunnerAction(dry_run, quay_api_store)
202
- runner = AggregatedDiffRunner(diff)
203
-
204
- runner.register("insert", runner_action.create_team())
205
- runner.register("update-insert", runner_action.add_to_team())
206
- runner.register("update-delete", runner_action.del_from_team())
207
- runner.register("delete", runner_action.del_from_team())
208
-
209
- status = runner.run()
210
- if not status:
211
- sys.exit(ExitCodes.ERROR)
218
+ with QuayApiStore() as quay_api_store:
219
+ current_state = fetch_current_state(quay_api_store)
220
+ desired_state = fetch_desired_state()
221
+
222
+ # calculate diff
223
+ diff = current_state.diff(desired_state)
224
+ logging.debug("State diff: %s", diff)
225
+
226
+ # Run actions
227
+ runner_action = RunnerAction(dry_run, quay_api_store)
228
+ runner = AggregatedDiffRunner(diff)
229
+
230
+ runner.register("insert", runner_action.create_team())
231
+ runner.register("update-insert", runner_action.add_to_team())
232
+ runner.register("update-delete", runner_action.del_from_team())
233
+ runner.register("delete", runner_action.del_from_team())
234
+
235
+ status = runner.run()
236
+ if not status:
237
+ sys.exit(ExitCodes.ERROR)
reconcile/quay_mirror.py CHANGED
@@ -66,7 +66,7 @@ class QuayMirror:
66
66
  }
67
67
  """
68
68
 
69
- response_cache: dict[tuple[str, str], Response] = {}
69
+ response_cache: dict[tuple[str, str | None], Response] = {}
70
70
 
71
71
  def __init__(
72
72
  self,
@@ -17,7 +17,7 @@ from sretoolbox.container.image import (
17
17
  )
18
18
  from sretoolbox.container.skopeo import SkopeoCmdError
19
19
 
20
- from reconcile.quay_base import get_quay_api_store
20
+ from reconcile.quay_base import QuayApiStore
21
21
  from reconcile.quay_mirror import QuayMirror
22
22
  from reconcile.utils.quay_mirror import record_timestamp, sync_tag
23
23
 
@@ -45,7 +45,7 @@ class QuayMirrorOrg:
45
45
  ) -> None:
46
46
  self.dry_run = dry_run
47
47
  self.skopeo_cli = Skopeo(dry_run)
48
- self.quay_api_store = get_quay_api_store()
48
+ self.quay_api_store = QuayApiStore()
49
49
  self.compare_tags = compare_tags
50
50
  self.compare_tags_interval = compare_tags_interval
51
51
  self.orgs = orgs
@@ -71,6 +71,7 @@ class QuayMirrorOrg:
71
71
 
72
72
  def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
73
73
  self.session.close()
74
+ self.quay_api_store.cleanup()
74
75
 
75
76
  def run(self) -> None:
76
77
  sync_tasks = self.process_sync_tasks()
@@ -101,11 +102,9 @@ class QuayMirrorOrg:
101
102
  if self.orgs and org_key.org_name not in self.orgs:
102
103
  continue
103
104
 
104
- quay_api = org_info["api"]
105
105
  upstream_org_key = org_info["mirror"]
106
106
  assert upstream_org_key is not None
107
107
  upstream_org = self.quay_api_store[upstream_org_key]
108
- upstream_quay_api = upstream_org["api"]
109
108
 
110
109
  push_token = upstream_org["push_token"]
111
110
 
@@ -114,7 +113,10 @@ class QuayMirrorOrg:
114
113
  username = push_token["user"]
115
114
  token = push_token["token"]
116
115
 
116
+ quay_api = org_info["api"]
117
117
  org_repos = [item["name"] for item in quay_api.list_images()]
118
+
119
+ upstream_quay_api = upstream_org["api"]
118
120
  for repo in upstream_quay_api.list_images():
119
121
  if repo["name"] not in org_repos:
120
122
  continue
@@ -2,7 +2,10 @@ import logging
2
2
  import sys
3
3
  from typing import Any
4
4
 
5
- from reconcile.quay_base import OrgKey, get_quay_api_store
5
+ from reconcile.quay_base import (
6
+ OrgKey,
7
+ QuayApiStore,
8
+ )
6
9
  from reconcile.status import ExitCodes
7
10
  from reconcile.utils import gql
8
11
 
@@ -57,85 +60,88 @@ def run(dry_run: bool) -> None:
57
60
  return
58
61
 
59
62
  apps: list[dict[str, Any]] = result.get("apps") or []
60
- quay_api_store = get_quay_api_store()
61
63
  error = False
62
- for app in apps:
63
- quay_repo_configs = app.get("quayRepos")
64
- if not quay_repo_configs:
65
- continue
66
- for quay_repo_config in quay_repo_configs:
67
- instance_name = quay_repo_config["org"]["instance"]["name"]
68
- org_name = quay_repo_config["org"]["name"]
69
- org_key = OrgKey(instance_name, org_name)
70
-
71
- if not quay_repo_config["org"]["managedRepos"]:
72
- logging.error(
73
- f"[{app['name']}] Can not manage repo permissions in {org_name} "
74
- "since managedRepos is set to false."
75
- )
76
- error = True
77
- continue
78
-
79
- # processing quayRepos section
80
- logging.debug(["app", app["name"], instance_name, org_name])
81
64
 
82
- quay_api = quay_api_store[org_key]["api"]
83
- teams = quay_repo_config.get("teams")
84
- if not teams:
65
+ with QuayApiStore() as quay_api_store:
66
+ for app in apps:
67
+ quay_repo_configs = app.get("quayRepos")
68
+ if not quay_repo_configs:
85
69
  continue
86
- repos = quay_repo_config["items"]
87
- for repo in repos:
88
- repo_name = repo["name"]
89
-
90
- # processing repo section
91
- logging.debug(["repo", repo_name])
92
-
93
- for team in teams:
94
- permissions = team["permissions"]
95
- role = team["role"]
96
- for permission in permissions:
97
- if permission["service"] != "quay-membership":
98
- logging.warning(
99
- "wrong service kind, should be quay-membership"
70
+ for quay_repo_config in quay_repo_configs:
71
+ instance_name = quay_repo_config["org"]["instance"]["name"]
72
+ org_name = quay_repo_config["org"]["name"]
73
+ org_key = OrgKey(instance_name, org_name)
74
+
75
+ if not quay_repo_config["org"]["managedRepos"]:
76
+ logging.error(
77
+ f"[{app['name']}] Can not manage repo permissions in {org_name} "
78
+ "since managedRepos is set to false."
79
+ )
80
+ error = True
81
+ continue
82
+
83
+ # processing quayRepos section
84
+ logging.debug(["app", app["name"], instance_name, org_name])
85
+
86
+ org_data = quay_api_store[org_key]
87
+ teams = quay_repo_config.get("teams")
88
+ if not teams:
89
+ continue
90
+ repos = quay_repo_config["items"]
91
+ quay_api = org_data["api"]
92
+
93
+ for repo in repos:
94
+ repo_name = repo["name"]
95
+
96
+ # processing repo section
97
+ logging.debug(["repo", repo_name])
98
+
99
+ for team in teams:
100
+ permissions = team["permissions"]
101
+ role = team["role"]
102
+ for permission in permissions:
103
+ if permission["service"] != "quay-membership":
104
+ logging.warning(
105
+ "wrong service kind, should be quay-membership"
106
+ )
107
+ continue
108
+
109
+ perm_org_key = OrgKey(
110
+ permission["quayOrg"]["instance"]["name"],
111
+ permission["quayOrg"]["name"],
100
112
  )
101
- continue
102
-
103
- perm_org_key = OrgKey(
104
- permission["quayOrg"]["instance"]["name"],
105
- permission["quayOrg"]["name"],
106
- )
107
-
108
- if perm_org_key != org_key:
109
- logging.warning(f"wrong org, should be {org_key}")
110
- continue
111
113
 
112
- team_name = permission["team"]
113
-
114
- # processing team section
115
- logging.debug(["team", team_name])
116
- try:
117
- current_role = quay_api.get_repo_team_permissions(
118
- repo_name, team_name
119
- )
120
- if current_role != role:
121
- logging.info([
122
- "update_role",
123
- org_key,
124
- repo_name,
125
- team_name,
126
- role,
127
- ])
128
- if not dry_run:
129
- quay_api.set_repo_team_permissions(
130
- repo_name, team_name, role
131
- )
132
- except Exception:
133
- error = True
134
- logging.exception(
135
- "could not manage repo permissions: "
136
- f"repo name: {repo_name}, "
137
- f"team name: {team_name}"
138
- )
114
+ if perm_org_key != org_key:
115
+ logging.warning(f"wrong org, should be {org_key}")
116
+ continue
117
+
118
+ team_name = permission["team"]
119
+
120
+ # processing team section
121
+ logging.debug(["team", team_name])
122
+ try:
123
+ current_role = quay_api.get_repo_team_permissions(
124
+ repo_name, team_name
125
+ )
126
+ if current_role != role:
127
+ logging.info([
128
+ "update_role",
129
+ org_key,
130
+ repo_name,
131
+ team_name,
132
+ role,
133
+ ])
134
+ if not dry_run:
135
+ quay_api.set_repo_team_permissions(
136
+ repo_name, team_name, role
137
+ )
138
+ except Exception:
139
+ error = True
140
+ logging.exception(
141
+ "could not manage repo permissions: "
142
+ f"repo name: {repo_name}, "
143
+ f"team name: {team_name}"
144
+ )
139
145
 
140
146
  if error:
141
147
  sys.exit(ExitCodes.ERROR)
reconcile/quay_repos.py CHANGED
@@ -3,18 +3,14 @@ from __future__ import annotations
3
3
  import logging
4
4
  import sys
5
5
  from collections import namedtuple
6
- from typing import TYPE_CHECKING
7
6
 
8
7
  from reconcile.quay_base import (
9
8
  OrgKey,
10
- get_quay_api_store,
9
+ QuayApiStore,
11
10
  )
12
11
  from reconcile.status import ExitCodes
13
12
  from reconcile.utils import gql
14
13
 
15
- if TYPE_CHECKING:
16
- from reconcile.quay_base import QuayApiStore
17
-
18
14
  QUAY_REPOS_QUERY = """
19
15
  {
20
16
  apps: apps_v1 {
@@ -51,7 +47,6 @@ def fetch_current_state(quay_api_store: QuayApiStore) -> list[RepoInfo]:
51
47
  continue
52
48
 
53
49
  quay_api = org_info["api"]
54
-
55
50
  for repo in quay_api.list_images():
56
51
  name = repo["name"]
57
52
  public = repo["is_public"]
@@ -150,7 +145,8 @@ def act_delete(
150
145
  current_repo.name,
151
146
  ])
152
147
  if not dry_run:
153
- api = quay_api_store[current_repo.org_key]["api"]
148
+ org_data = quay_api_store[current_repo.org_key]
149
+ api = org_data["api"]
154
150
  api.repo_delete(current_repo.name)
155
151
 
156
152
 
@@ -164,7 +160,8 @@ def act_create(
164
160
  desired_repo.name,
165
161
  ])
166
162
  if not dry_run:
167
- api = quay_api_store[desired_repo.org_key]["api"]
163
+ org_data = quay_api_store[desired_repo.org_key]
164
+ api = org_data["api"]
168
165
  api.repo_create(
169
166
  desired_repo.name, desired_repo.description, desired_repo.public
170
167
  )
@@ -180,7 +177,8 @@ def act_description(
180
177
  desired_repo.description,
181
178
  ])
182
179
  if not dry_run:
183
- api = quay_api_store[desired_repo.org_key]["api"]
180
+ org_data = quay_api_store[desired_repo.org_key]
181
+ api = org_data["api"]
184
182
  api.repo_update_description(desired_repo.name, desired_repo.description)
185
183
 
186
184
 
@@ -194,7 +192,8 @@ def act_public(
194
192
  desired_repo.name,
195
193
  ])
196
194
  if not dry_run:
197
- api = quay_api_store[desired_repo.org_key]["api"]
195
+ org_data = quay_api_store[desired_repo.org_key]
196
+ api = org_data["api"]
198
197
  if desired_repo.public:
199
198
  api.repo_make_public(desired_repo.name)
200
199
  else:
@@ -223,32 +222,31 @@ def act(
223
222
 
224
223
 
225
224
  def run(dry_run: bool) -> None:
226
- quay_api_store = get_quay_api_store()
227
-
228
- # consistency checks
229
- for org_key, org_info in quay_api_store.items():
230
- if org_info.get("mirror"):
231
- # ensure there are no circular mirror dependencies
232
- mirror_org_key = org_info["mirror"]
233
- assert mirror_org_key is not None
234
- mirror_org = quay_api_store[mirror_org_key]
235
- if mirror_org.get("mirror"):
236
- logging.error(
237
- f"{mirror_org_key.instance}/"
238
- + f"{mirror_org_key.org_name} "
239
- + "can't have mirrors and be a mirror"
240
- )
241
- sys.exit(ExitCodes.ERROR)
225
+ with QuayApiStore() as quay_api_store:
226
+ # consistency checks
227
+ for org_key, org_info in quay_api_store.items():
228
+ if org_info.get("mirror"):
229
+ # ensure there are no circular mirror dependencies
230
+ mirror_org_key = org_info["mirror"]
231
+ assert mirror_org_key is not None
232
+ mirror_org = quay_api_store[mirror_org_key]
233
+ if mirror_org.get("mirror"):
234
+ logging.error(
235
+ f"{mirror_org_key.instance}/"
236
+ + f"{mirror_org_key.org_name} "
237
+ + "can't have mirrors and be a mirror"
238
+ )
239
+ sys.exit(ExitCodes.ERROR)
242
240
 
243
- # ensure no org defines `managedRepos` and `mirror` at the same
244
- if org_info.get("managedRepos"):
245
- logging.error(
246
- f"{org_key.instance}/{org_key.org_name} "
247
- + "has defined mirror and managedRepos"
248
- )
249
- sys.exit(ExitCodes.ERROR)
241
+ # ensure no org defines `managedRepos` and `mirror` at the same
242
+ if org_info.get("managedRepos"):
243
+ logging.error(
244
+ f"{org_key.instance}/{org_key.org_name} "
245
+ + "has defined mirror and managedRepos"
246
+ )
247
+ sys.exit(ExitCodes.ERROR)
250
248
 
251
- # run integration
252
- current_state = fetch_current_state(quay_api_store)
253
- desired_state = fetch_desired_state(quay_api_store)
254
- act(dry_run, quay_api_store, current_state, desired_state)
249
+ # run integration
250
+ current_state = fetch_current_state(quay_api_store)
251
+ desired_state = fetch_desired_state(quay_api_store)
252
+ act(dry_run, quay_api_store, current_state, desired_state)