qontract-reconcile 0.10.2.dev361__py3-none-any.whl → 0.10.2.dev430__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 (351) hide show
  1. {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/METADATA +13 -12
  2. {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/RECORD +351 -345
  3. reconcile/acs_rbac.py +2 -2
  4. reconcile/aus/advanced_upgrade_service.py +18 -12
  5. reconcile/aus/base.py +134 -32
  6. reconcile/aus/cluster_version_data.py +15 -5
  7. reconcile/aus/models.py +3 -1
  8. reconcile/aus/ocm_addons_upgrade_scheduler_org.py +1 -0
  9. reconcile/aus/ocm_upgrade_scheduler.py +8 -1
  10. reconcile/aus/ocm_upgrade_scheduler_org.py +20 -5
  11. reconcile/aus/version_gates/sts_version_gate_handler.py +54 -1
  12. reconcile/automated_actions/config/integration.py +16 -4
  13. reconcile/aws_account_manager/integration.py +8 -8
  14. reconcile/aws_account_manager/reconciler.py +3 -3
  15. reconcile/aws_ami_cleanup/integration.py +8 -12
  16. reconcile/aws_ami_share.py +69 -62
  17. reconcile/aws_cloudwatch_log_retention/integration.py +155 -126
  18. reconcile/aws_iam_keys.py +1 -0
  19. reconcile/aws_saml_idp/integration.py +12 -4
  20. reconcile/aws_saml_roles/integration.py +30 -23
  21. reconcile/aws_version_sync/integration.py +6 -12
  22. reconcile/change_owners/bundle.py +3 -3
  23. reconcile/change_owners/change_log_tracking.py +3 -2
  24. reconcile/change_owners/change_owners.py +1 -1
  25. reconcile/change_owners/diff.py +0 -2
  26. reconcile/checkpoint.py +11 -3
  27. reconcile/cli.py +93 -10
  28. reconcile/dashdotdb_dora.py +5 -12
  29. reconcile/dashdotdb_slo.py +1 -1
  30. reconcile/database_access_manager.py +123 -117
  31. reconcile/dynatrace_token_provider/integration.py +1 -1
  32. reconcile/endpoints_discovery/integration.py +4 -1
  33. reconcile/endpoints_discovery/merge_request.py +1 -1
  34. reconcile/endpoints_discovery/merge_request_manager.py +8 -8
  35. reconcile/external_resources/factories.py +4 -6
  36. reconcile/external_resources/integration.py +1 -1
  37. reconcile/external_resources/manager.py +8 -6
  38. reconcile/external_resources/meta.py +0 -1
  39. reconcile/external_resources/metrics.py +1 -1
  40. reconcile/external_resources/model.py +19 -15
  41. reconcile/external_resources/reconciler.py +7 -4
  42. reconcile/external_resources/secrets_sync.py +4 -7
  43. reconcile/external_resources/state.py +26 -16
  44. reconcile/fleet_labeler/integration.py +1 -1
  45. reconcile/gabi_authorized_users.py +5 -2
  46. reconcile/gcp_image_mirror.py +2 -2
  47. reconcile/github_org.py +1 -1
  48. reconcile/github_owners.py +4 -0
  49. reconcile/gitlab_housekeeping.py +13 -15
  50. reconcile/gitlab_members.py +6 -12
  51. reconcile/gitlab_owners.py +15 -11
  52. reconcile/gitlab_permissions.py +8 -12
  53. reconcile/glitchtip_project_alerts/integration.py +3 -1
  54. reconcile/gql_definitions/acs/acs_instances.py +5 -5
  55. reconcile/gql_definitions/acs/acs_policies.py +5 -5
  56. reconcile/gql_definitions/acs/acs_rbac.py +5 -5
  57. reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +5 -5
  58. reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +5 -5
  59. reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +5 -5
  60. reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
  61. reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
  62. reconcile/gql_definitions/automated_actions/instance.py +46 -7
  63. reconcile/gql_definitions/aws_account_manager/aws_accounts.py +5 -5
  64. reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +15 -5
  65. reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +27 -66
  66. reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +15 -5
  67. reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +15 -5
  68. reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
  69. reconcile/gql_definitions/aws_version_sync/clusters.py +5 -5
  70. reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
  71. reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
  72. reconcile/gql_definitions/change_owners/queries/self_service_roles.py +5 -5
  73. reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +5 -5
  74. reconcile/gql_definitions/common/alerting_services_settings.py +5 -5
  75. reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
  76. reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
  77. reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
  78. reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
  79. reconcile/gql_definitions/common/app_interface_roles.py +5 -5
  80. reconcile/gql_definitions/common/app_interface_state_settings.py +5 -5
  81. reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
  82. reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
  83. reconcile/gql_definitions/common/apps.py +5 -5
  84. reconcile/gql_definitions/common/aws_vpc_requests.py +15 -5
  85. reconcile/gql_definitions/common/aws_vpcs.py +5 -5
  86. reconcile/gql_definitions/common/clusters.py +5 -5
  87. reconcile/gql_definitions/common/clusters_minimal.py +5 -5
  88. reconcile/gql_definitions/common/clusters_with_dms.py +5 -5
  89. reconcile/gql_definitions/common/clusters_with_peering.py +5 -5
  90. reconcile/gql_definitions/common/github_orgs.py +5 -5
  91. reconcile/gql_definitions/common/jira_settings.py +5 -5
  92. reconcile/gql_definitions/common/jiralert_settings.py +5 -5
  93. reconcile/gql_definitions/common/ldap_settings.py +5 -5
  94. reconcile/gql_definitions/common/namespaces.py +5 -5
  95. reconcile/gql_definitions/common/namespaces_minimal.py +7 -5
  96. reconcile/gql_definitions/common/ocm_env_telemeter.py +5 -5
  97. reconcile/gql_definitions/common/ocm_environments.py +5 -5
  98. reconcile/gql_definitions/common/pagerduty_instances.py +5 -5
  99. reconcile/gql_definitions/common/pgp_reencryption_settings.py +5 -5
  100. reconcile/gql_definitions/common/pipeline_providers.py +5 -5
  101. reconcile/gql_definitions/common/quay_instances.py +5 -5
  102. reconcile/gql_definitions/common/quay_orgs.py +5 -5
  103. reconcile/gql_definitions/common/reserved_networks.py +5 -5
  104. reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
  105. reconcile/gql_definitions/common/saas_files.py +5 -5
  106. reconcile/gql_definitions/common/saas_target_namespaces.py +5 -5
  107. reconcile/gql_definitions/common/saasherder_settings.py +5 -5
  108. reconcile/gql_definitions/common/slack_workspaces.py +5 -5
  109. reconcile/gql_definitions/common/smtp_client_settings.py +5 -5
  110. reconcile/gql_definitions/common/state_aws_account.py +5 -5
  111. reconcile/gql_definitions/common/users.py +5 -5
  112. reconcile/gql_definitions/common/users_with_paths.py +5 -5
  113. reconcile/gql_definitions/cost_report/app_names.py +5 -5
  114. reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
  115. reconcile/gql_definitions/cost_report/settings.py +5 -5
  116. reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +5 -5
  117. reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +5 -5
  118. reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
  119. reconcile/gql_definitions/email_sender/apps.py +5 -5
  120. reconcile/gql_definitions/email_sender/emails.py +5 -5
  121. reconcile/gql_definitions/email_sender/users.py +5 -5
  122. reconcile/gql_definitions/endpoints_discovery/apps.py +5 -5
  123. reconcile/gql_definitions/external_resources/aws_accounts.py +5 -5
  124. reconcile/gql_definitions/external_resources/external_resources_modules.py +5 -5
  125. reconcile/gql_definitions/external_resources/external_resources_namespaces.py +33 -6
  126. reconcile/gql_definitions/external_resources/external_resources_settings.py +5 -5
  127. reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
  128. reconcile/gql_definitions/fleet_labeler/fleet_labels.py +5 -5
  129. reconcile/gql_definitions/fragments/aus_organization.py +5 -5
  130. reconcile/gql_definitions/fragments/aws_account_common.py +7 -5
  131. reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
  132. reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
  133. reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
  134. reconcile/gql_definitions/fragments/aws_organization.py +33 -0
  135. reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
  136. reconcile/gql_definitions/fragments/aws_vpc_request.py +7 -5
  137. reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
  138. reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
  139. reconcile/gql_definitions/fragments/disable.py +5 -5
  140. reconcile/gql_definitions/fragments/email_service.py +5 -5
  141. reconcile/gql_definitions/fragments/email_user.py +5 -5
  142. reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
  143. reconcile/gql_definitions/fragments/membership_source.py +5 -5
  144. reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
  145. reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
  146. reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
  147. reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
  148. reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
  149. reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
  150. reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
  151. reconcile/gql_definitions/fragments/resource_values.py +5 -5
  152. reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
  153. reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
  154. reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
  155. reconcile/gql_definitions/fragments/terraform_state.py +5 -5
  156. reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
  157. reconcile/gql_definitions/fragments/user.py +5 -5
  158. reconcile/gql_definitions/fragments/vault_secret.py +5 -5
  159. reconcile/gql_definitions/gcp/gcp_docker_repos.py +5 -5
  160. reconcile/gql_definitions/gcp/gcp_projects.py +5 -5
  161. reconcile/gql_definitions/gitlab_members/gitlab_instances.py +5 -5
  162. reconcile/gql_definitions/gitlab_members/permissions.py +5 -5
  163. reconcile/gql_definitions/glitchtip/glitchtip_instance.py +5 -5
  164. reconcile/gql_definitions/glitchtip/glitchtip_project.py +5 -5
  165. reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +5 -5
  166. reconcile/gql_definitions/integrations/integrations.py +5 -5
  167. reconcile/gql_definitions/introspection.json +724 -129
  168. reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +5 -5
  169. reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +5 -5
  170. reconcile/gql_definitions/jira/jira_servers.py +5 -5
  171. reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +9 -5
  172. reconcile/gql_definitions/jumphosts/jumphosts.py +5 -5
  173. reconcile/gql_definitions/ldap_groups/roles.py +5 -5
  174. reconcile/gql_definitions/ldap_groups/settings.py +5 -5
  175. reconcile/gql_definitions/maintenance/maintenances.py +5 -5
  176. reconcile/gql_definitions/membershipsources/roles.py +5 -5
  177. reconcile/gql_definitions/ocm_labels/clusters.py +5 -5
  178. reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
  179. reconcile/gql_definitions/openshift_cluster_bots/clusters.py +5 -5
  180. reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
  181. reconcile/gql_definitions/openshift_groups/managed_roles.py +5 -5
  182. reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +5 -5
  183. reconcile/gql_definitions/quay_membership/quay_membership.py +5 -5
  184. reconcile/gql_definitions/rhcs/certs.py +25 -79
  185. reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +43 -0
  186. reconcile/gql_definitions/rhidp/organizations.py +5 -5
  187. reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
  188. reconcile/gql_definitions/service_dependencies/service_dependencies.py +5 -5
  189. reconcile/gql_definitions/sharding/aws_accounts.py +5 -5
  190. reconcile/gql_definitions/sharding/ocm_organization.py +5 -5
  191. reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
  192. reconcile/gql_definitions/skupper_network/skupper_networks.py +5 -5
  193. reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
  194. reconcile/gql_definitions/slack_usergroups/permissions.py +5 -5
  195. reconcile/gql_definitions/slack_usergroups/users.py +5 -5
  196. reconcile/gql_definitions/slo_documents/slo_documents.py +5 -5
  197. reconcile/gql_definitions/status_board/status_board.py +5 -5
  198. reconcile/gql_definitions/statuspage/statuspages.py +5 -5
  199. reconcile/gql_definitions/templating/template_collection.py +5 -5
  200. reconcile/gql_definitions/templating/templates.py +5 -5
  201. reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +5 -5
  202. reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +5 -5
  203. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +5 -5
  204. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +5 -5
  205. reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +5 -5
  206. reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +5 -5
  207. reconcile/gql_definitions/terraform_init/aws_accounts.py +19 -5
  208. reconcile/gql_definitions/terraform_repo/terraform_repo.py +5 -5
  209. reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
  210. reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +30 -6
  211. reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +15 -5
  212. reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +5 -5
  213. reconcile/gql_definitions/vault_instances/vault_instances.py +5 -5
  214. reconcile/gql_definitions/vault_policies/vault_policies.py +5 -5
  215. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +5 -5
  216. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +5 -5
  217. reconcile/integrations_manager.py +3 -3
  218. reconcile/jenkins_worker_fleets.py +10 -8
  219. reconcile/jira_permissions_validator.py +237 -122
  220. reconcile/ldap_groups/integration.py +1 -1
  221. reconcile/ocm/types.py +35 -57
  222. reconcile/ocm_aws_infrastructure_access.py +1 -1
  223. reconcile/ocm_clusters.py +4 -4
  224. reconcile/ocm_labels/integration.py +3 -2
  225. reconcile/ocm_machine_pools.py +33 -27
  226. reconcile/openshift_base.py +113 -4
  227. reconcile/openshift_cluster_bots.py +1 -1
  228. reconcile/openshift_namespace_labels.py +1 -1
  229. reconcile/openshift_namespaces.py +97 -101
  230. reconcile/openshift_resources_base.py +6 -2
  231. reconcile/openshift_rhcs_certs.py +74 -37
  232. reconcile/openshift_rolebindings.py +7 -11
  233. reconcile/openshift_saas_deploy.py +4 -5
  234. reconcile/openshift_saas_deploy_change_tester.py +9 -7
  235. reconcile/openshift_saas_deploy_trigger_cleaner.py +3 -5
  236. reconcile/openshift_serviceaccount_tokens.py +2 -2
  237. reconcile/openshift_upgrade_watcher.py +4 -4
  238. reconcile/oum/labelset.py +5 -3
  239. reconcile/oum/models.py +1 -4
  240. reconcile/prometheus_rules_tester/integration.py +3 -3
  241. reconcile/quay_mirror.py +1 -1
  242. reconcile/queries.py +131 -0
  243. reconcile/rhidp/common.py +3 -5
  244. reconcile/rhidp/sso_client/base.py +16 -5
  245. reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
  246. reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
  247. reconcile/skupper_network/integration.py +2 -2
  248. reconcile/slack_usergroups.py +35 -14
  249. reconcile/sql_query.py +1 -0
  250. reconcile/status_board.py +6 -6
  251. reconcile/statuspage/atlassian.py +7 -7
  252. reconcile/statuspage/integrations/maintenances.py +4 -3
  253. reconcile/statuspage/page.py +4 -9
  254. reconcile/statuspage/status.py +5 -8
  255. reconcile/templating/lib/rendering.py +3 -3
  256. reconcile/templating/renderer.py +2 -2
  257. reconcile/terraform_aws_route53.py +7 -1
  258. reconcile/terraform_cloudflare_dns.py +3 -3
  259. reconcile/terraform_cloudflare_resources.py +5 -5
  260. reconcile/terraform_cloudflare_users.py +3 -2
  261. reconcile/terraform_init/integration.py +187 -23
  262. reconcile/terraform_repo.py +16 -12
  263. reconcile/terraform_resources.py +6 -6
  264. reconcile/terraform_tgw_attachments.py +27 -19
  265. reconcile/terraform_users.py +7 -0
  266. reconcile/terraform_vpc_peerings.py +14 -3
  267. reconcile/terraform_vpc_resources/integration.py +10 -1
  268. reconcile/typed_queries/aws_account_tags.py +41 -0
  269. reconcile/typed_queries/cost_report/app_names.py +1 -1
  270. reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
  271. reconcile/typed_queries/saas_files.py +11 -11
  272. reconcile/typed_queries/status_board.py +2 -2
  273. reconcile/unleash_feature_toggles/integration.py +4 -2
  274. reconcile/utils/acs/base.py +6 -3
  275. reconcile/utils/acs/policies.py +2 -2
  276. reconcile/utils/aws_api.py +51 -20
  277. reconcile/utils/aws_api_typed/api.py +38 -9
  278. reconcile/utils/aws_api_typed/cloudformation.py +149 -0
  279. reconcile/utils/aws_api_typed/logs.py +73 -0
  280. reconcile/utils/aws_api_typed/organization.py +4 -2
  281. reconcile/utils/binary.py +7 -12
  282. reconcile/utils/datetime_util.py +67 -0
  283. reconcile/utils/deadmanssnitch_api.py +1 -1
  284. reconcile/utils/differ.py +2 -3
  285. reconcile/utils/early_exit_cache.py +11 -12
  286. reconcile/utils/expiration.py +7 -3
  287. reconcile/utils/filtering.py +1 -1
  288. reconcile/utils/gitlab_api.py +7 -5
  289. reconcile/utils/glitchtip/client.py +6 -2
  290. reconcile/utils/glitchtip/models.py +25 -28
  291. reconcile/utils/gql.py +4 -7
  292. reconcile/utils/helpers.py +1 -1
  293. reconcile/utils/instrumented_wrappers.py +1 -1
  294. reconcile/utils/internal_groups/client.py +2 -2
  295. reconcile/utils/internal_groups/models.py +8 -17
  296. reconcile/utils/jinja2/utils.py +6 -101
  297. reconcile/utils/jira_client.py +82 -63
  298. reconcile/utils/jjb_client.py +7 -10
  299. reconcile/utils/jobcontroller/controller.py +2 -2
  300. reconcile/utils/jobcontroller/models.py +17 -1
  301. reconcile/utils/json.py +43 -1
  302. reconcile/utils/membershipsources/app_interface_resolver.py +4 -2
  303. reconcile/utils/membershipsources/models.py +16 -23
  304. reconcile/utils/membershipsources/resolver.py +4 -2
  305. reconcile/utils/merge_request_manager/merge_request_manager.py +4 -4
  306. reconcile/utils/merge_request_manager/parser.py +6 -6
  307. reconcile/utils/metrics.py +5 -5
  308. reconcile/utils/models.py +304 -82
  309. reconcile/utils/mr/app_interface_reporter.py +2 -2
  310. reconcile/utils/mr/notificator.py +3 -3
  311. reconcile/utils/mr/update_access_report_base.py +3 -4
  312. reconcile/utils/mr/user_maintenance.py +3 -2
  313. reconcile/utils/oc.py +246 -201
  314. reconcile/utils/oc_filters.py +3 -3
  315. reconcile/utils/ocm/addons.py +0 -1
  316. reconcile/utils/ocm/base.py +17 -20
  317. reconcile/utils/ocm/cluster_groups.py +1 -1
  318. reconcile/utils/ocm/identity_providers.py +2 -2
  319. reconcile/utils/ocm/labels.py +1 -1
  320. reconcile/utils/ocm/products.py +8 -8
  321. reconcile/utils/ocm/search_filters.py +3 -6
  322. reconcile/utils/ocm/service_log.py +4 -6
  323. reconcile/utils/ocm/sre_capability_labels.py +20 -13
  324. reconcile/utils/openshift_resource.py +8 -3
  325. reconcile/utils/pagerduty_api.py +10 -7
  326. reconcile/utils/promotion_state.py +6 -11
  327. reconcile/utils/raw_github_api.py +1 -1
  328. reconcile/utils/rhcsv2_certs.py +86 -23
  329. reconcile/utils/rosa/session.py +16 -0
  330. reconcile/utils/runtime/integration.py +2 -3
  331. reconcile/utils/runtime/runner.py +2 -2
  332. reconcile/utils/saasherder/interfaces.py +13 -20
  333. reconcile/utils/saasherder/models.py +23 -20
  334. reconcile/utils/saasherder/saasherder.py +50 -27
  335. reconcile/utils/slack_api.py +2 -2
  336. reconcile/utils/sloth.py +171 -2
  337. reconcile/utils/structs.py +1 -1
  338. reconcile/utils/terraform_client.py +5 -4
  339. reconcile/utils/terrascript_aws_client.py +134 -74
  340. reconcile/utils/unleash/server.py +2 -8
  341. reconcile/utils/vault.py +5 -12
  342. reconcile/utils/vcs.py +8 -8
  343. reconcile/vault_replication.py +107 -42
  344. tools/app_interface_reporter.py +4 -4
  345. tools/cli_commands/cost_report/cost_management_api.py +3 -3
  346. tools/cli_commands/cost_report/view.py +7 -6
  347. tools/cli_commands/erv2.py +1 -1
  348. tools/qontract_cli.py +28 -17
  349. tools/template_validation.py +3 -1
  350. {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/WHEEL +0 -0
  351. {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/entry_points.txt +0 -0
@@ -6,6 +6,7 @@ from reconcile.utils.ocm.base import OCMCluster, OCMVersionGate
6
6
  from reconcile.utils.ocm_base_client import OCMBaseClient
7
7
  from reconcile.utils.rosa.rosa_cli import RosaCliError
8
8
  from reconcile.utils.rosa.session import RosaSession
9
+ from reconcile.utils.semver_helper import get_version_prefix
9
10
 
10
11
  GATE_LABEL = "api.openshift.com/gate-sts"
11
12
 
@@ -63,6 +64,24 @@ class STSGateHandler(GateHandler):
63
64
  )
64
65
  return False
65
66
 
67
+ return self.upgrade_rosa_roles(
68
+ cluster=cluster,
69
+ version_raw_id_prefix=gate.version_raw_id_prefix,
70
+ dry_run=dry_run,
71
+ ocm_api=ocm_api,
72
+ ocm_org_id=ocm_org_id,
73
+ )
74
+
75
+ def upgrade_rosa_roles(
76
+ self,
77
+ cluster: OCMCluster,
78
+ version_raw_id_prefix: str,
79
+ dry_run: bool,
80
+ ocm_api: OCMBaseClient,
81
+ ocm_org_id: str,
82
+ ) -> bool:
83
+ if not cluster.aws:
84
+ return False
66
85
  rosa = RosaSession(
67
86
  aws_account_id=cluster.aws.aws_account_id,
68
87
  aws_region=cluster.region.id,
@@ -83,7 +102,7 @@ class STSGateHandler(GateHandler):
83
102
  )
84
103
  rosa.upgrade_account_roles(
85
104
  role_prefix=account_role_prefix,
86
- minor_version=gate.version_raw_id_prefix,
105
+ minor_version=version_raw_id_prefix,
87
106
  channel_group=cluster.version.channel_group,
88
107
  dry_run=dry_run,
89
108
  )
@@ -98,3 +117,37 @@ class STSGateHandler(GateHandler):
98
117
  e.write_logs_to_logger(logging.error)
99
118
  return False
100
119
  return True
120
+
121
+ def upgrade_rosa_roles_v2(
122
+ self,
123
+ cluster: OCMCluster,
124
+ upgrade_version: str,
125
+ dry_run: bool,
126
+ ocm_api: OCMBaseClient,
127
+ ocm_org_id: str,
128
+ ) -> bool:
129
+ if not cluster.aws:
130
+ return False
131
+ rosa = RosaSession(
132
+ aws_account_id=cluster.aws.aws_account_id,
133
+ aws_region=cluster.region.id,
134
+ aws_iam_role=self.aws_iam_role,
135
+ ocm_org_id=ocm_org_id,
136
+ ocm_api=ocm_api,
137
+ job_controller=self.job_controller,
138
+ image=self.rosa_job_image,
139
+ service_account=self.rosa_job_service_account,
140
+ )
141
+ policy_version = get_version_prefix(upgrade_version)
142
+ try:
143
+ rosa.upgrade_rosa_roles(
144
+ cluster_name=cluster.name,
145
+ upgrade_version=upgrade_version,
146
+ policy_version=policy_version,
147
+ dry_run=dry_run,
148
+ )
149
+ except RosaCliError as e:
150
+ logging.error(f"Failed to upgrade roles for cluster {cluster.name}: {e}")
151
+ e.write_logs_to_logger(logging.error)
152
+ return False
153
+ return True
@@ -7,7 +7,7 @@ from collections.abc import (
7
7
  from typing import Any
8
8
 
9
9
  import yaml
10
- from kubernetes.client import ( # type: ignore[attr-defined]
10
+ from kubernetes.client import (
11
11
  ApiClient,
12
12
  V1ConfigMap,
13
13
  V1ObjectMeta,
@@ -20,6 +20,7 @@ from reconcile.gql_definitions.automated_actions.instance import (
20
20
  AutomatedActionExternalResourceFlushElastiCacheV1,
21
21
  AutomatedActionExternalResourceRdsRebootV1,
22
22
  AutomatedActionExternalResourceRdsSnapshotV1,
23
+ AutomatedActionOpenshiftTriggerCronjobV1,
23
24
  AutomatedActionOpenshiftWorkloadDeleteV1,
24
25
  AutomatedActionOpenshiftWorkloadRestartArgumentV1,
25
26
  AutomatedActionOpenshiftWorkloadRestartV1,
@@ -82,7 +83,7 @@ class AutomatedActionsConfigIntegration(
82
83
  query_func = gql.get_api().query
83
84
  return {
84
85
  "automated_actions_instances": [
85
- c.dict() for c in self.get_automated_actions_instances(query_func)
86
+ c.model_dump() for c in self.get_automated_actions_instances(query_func)
86
87
  ]
87
88
  }
88
89
 
@@ -167,7 +168,7 @@ class AutomatedActionsConfigIntegration(
167
168
  case AutomatedActionActionListV1():
168
169
  # no special handling needed, just dump the values
169
170
  parameters.extend(
170
- arg.dict(exclude_none=True, exclude_defaults=True)
171
+ arg.model_dump(exclude_none=True, exclude_defaults=True)
171
172
  for arg in action.action_list_arguments or []
172
173
  )
173
174
  case AutomatedActionExternalResourceFlushElastiCacheV1():
@@ -205,6 +206,17 @@ class AutomatedActionsConfigIntegration(
205
206
  "account": f"^{rds_snapshot_er.provisioner.name}$",
206
207
  "identifier": rds_snapshot_arg.identifier,
207
208
  })
209
+ case AutomatedActionOpenshiftTriggerCronjobV1():
210
+ parameters.extend(
211
+ {
212
+ # all parameter values are regexes in the OPA policy
213
+ # therefore, cluster and namespace must be fixed to the current strings
214
+ "cluster": f"^{arg.namespace.cluster.name}$",
215
+ "namespace": f"^{arg.namespace.name}$",
216
+ "cronjob": arg.cronjob,
217
+ }
218
+ for arg in action.openshift_trigger_cronjob_arguments
219
+ )
208
220
  case AutomatedActionOpenshiftWorkloadDeleteV1():
209
221
  parameters.extend(
210
222
  {
@@ -257,7 +269,7 @@ class AutomatedActionsConfigIntegration(
257
269
  {
258
270
  "users": {user.username: sorted(user.roles) for user in users},
259
271
  "roles": {
260
- role: [policy.dict() for policy in policies]
272
+ role: [policy.model_dump() for policy in policies]
261
273
  for role, policies in roles.items()
262
274
  },
263
275
  },
@@ -1,5 +1,4 @@
1
1
  from collections.abc import Callable, Iterable
2
- from datetime import UTC, datetime
3
2
  from typing import Any
4
3
 
5
4
  import jinja2
@@ -26,6 +25,7 @@ from reconcile.typed_queries.gitlab_instances import get_gitlab_instances
26
25
  from reconcile.utils import gql, metrics
27
26
  from reconcile.utils.aws_api_typed.api import AWSApi, AWSStaticCredentials
28
27
  from reconcile.utils.aws_api_typed.iam import AWSAccessKey
28
+ from reconcile.utils.datetime_util import utc_now
29
29
  from reconcile.utils.defer import defer
30
30
  from reconcile.utils.disabled_integrations import integration_is_enabled
31
31
  from reconcile.utils.runtime.integration import (
@@ -42,14 +42,14 @@ QONTRACT_INTEGRATION_VERSION = make_semver(1, 0, 0)
42
42
 
43
43
 
44
44
  class AwsAccountMgmtIntegrationParams(PydanticRunParams):
45
- account_name: str | None
45
+ account_name: str | None = None
46
46
  flavor: str
47
47
  organization_account_role: str = "OrganizationAccountAccessRole"
48
48
  default_tags: dict[str, str] = {}
49
49
  initial_user_name: str = "terraform"
50
50
  initial_user_policy_arn: str = "arn:aws:iam::aws:policy/AdministratorAccess"
51
51
  initial_user_secret_vault_path: str = (
52
- "app-sre-v2/creds/terraform/{account_name}/config"
52
+ "app-sre-v2/creds/terraform/{account_name}/config" # noqa: RUF027
53
53
  )
54
54
  # To avoid the accidental deletion of the resource file, explicitly set the
55
55
  # qontract.cli option in the integration extraArgs!
@@ -76,9 +76,9 @@ class AwsAccountMgmtIntegration(
76
76
  query_func, account_name=self.params.account_name
77
77
  )
78
78
  return {
79
- "payer_accounts": [account.dict() for account in payer_accounts],
79
+ "payer_accounts": [account.model_dump() for account in payer_accounts],
80
80
  "non_organization_accounts": [
81
- account.dict() for account in non_organization_accounts
81
+ account.model_dump() for account in non_organization_accounts
82
82
  ],
83
83
  }
84
84
 
@@ -98,10 +98,10 @@ class AwsAccountMgmtIntegration(
98
98
  lstrip_blocks=True,
99
99
  keep_trailing_newline=True,
100
100
  ).render({
101
- "accountRequest": account_request.dict(by_alias=True),
101
+ "accountRequest": account_request.model_dump(by_alias=True),
102
102
  "uid": uid,
103
103
  "settings": settings,
104
- "timestamp": int(datetime.now(tz=UTC).timestamp()),
104
+ "timestamp": int(utc_now().timestamp()),
105
105
  })
106
106
  return tmpl
107
107
 
@@ -187,7 +187,7 @@ class AwsAccountMgmtIntegration(
187
187
  template=account_template,
188
188
  account_request=account_request,
189
189
  uid=uid,
190
- settings=self.params.dict(),
190
+ settings=self.params.model_dump(),
191
191
  ),
192
192
  account_request_file_path=f"data/{account_request.path.strip('/')}",
193
193
  )
@@ -35,7 +35,7 @@ class Quota(Protocol):
35
35
  quota_code: str
36
36
  value: float
37
37
 
38
- def dict(self) -> dict[str, Any]: ...
38
+ def model_dump(self) -> dict[str, Any]: ...
39
39
 
40
40
 
41
41
  class Contact(Protocol):
@@ -44,7 +44,7 @@ class Contact(Protocol):
44
44
  email: str
45
45
  phone_number: str
46
46
 
47
- def dict(self) -> dict[str, Any]: ...
47
+ def model_dump(self) -> dict[str, Any]: ...
48
48
 
49
49
 
50
50
  class AWSReconciler:
@@ -167,7 +167,7 @@ class AWSReconciler:
167
167
  self, aws_api: AWSApi, name: str, quotas: Iterable[Quota]
168
168
  ) -> list[str] | None:
169
169
  """Request service quota changes."""
170
- quotas_dict = [q.dict() for q in quotas]
170
+ quotas_dict = [q.model_dump() for q in quotas]
171
171
  with self.state.transaction(
172
172
  state_key(name, TASK_REQUEST_SERVICE_QUOTA)
173
173
  ) as _state:
@@ -26,6 +26,7 @@ from reconcile.typed_queries.app_interface_vault_settings import (
26
26
  )
27
27
  from reconcile.utils import gql
28
28
  from reconcile.utils.aws_api import AWSApi
29
+ from reconcile.utils.datetime_util import from_utc_iso_format, utc_now
29
30
  from reconcile.utils.defer import defer
30
31
  from reconcile.utils.parse_dhms_duration import dhms_to_seconds
31
32
  from reconcile.utils.secret_reader import create_secret_reader
@@ -39,15 +40,12 @@ QONTRACT_INTEGRATION = "aws_ami_cleanup"
39
40
  MANAGED_TAG = {"Key": "managed_by_integration", "Value": QONTRACT_INTEGRATION}
40
41
 
41
42
 
42
- class AWSAmi(BaseModel):
43
+ class AWSAmi(BaseModel, frozen=True):
43
44
  name: str
44
45
  image_id: str
45
46
  creation_date: datetime
46
47
  snapshot_ids: list[str]
47
48
 
48
- class Config:
49
- frozen = True
50
-
51
49
 
52
50
  def get_aws_amis_from_launch_templates(ec2_client: EC2Client) -> set[str]:
53
51
  amis = set()
@@ -77,7 +75,7 @@ def get_aws_amis(
77
75
  owner: str,
78
76
  regex: str,
79
77
  age_in_seconds: int,
80
- utc_now: datetime,
78
+ now: datetime,
81
79
  ) -> list[AWSAmi]:
82
80
  """Get amis that match regex older than given age"""
83
81
 
@@ -89,10 +87,8 @@ def get_aws_amis(
89
87
  if not re.search(pattern, image["Name"]):
90
88
  continue
91
89
 
92
- creation_date = datetime.strptime(
93
- image["CreationDate"], "%Y-%m-%dT%H:%M:%S.%fZ"
94
- )
95
- current_delta = utc_now - creation_date
90
+ creation_date = from_utc_iso_format(image["CreationDate"])
91
+ current_delta = now - creation_date
96
92
  delete_delta = timedelta(seconds=age_in_seconds)
97
93
 
98
94
  if current_delta < delete_delta:
@@ -135,7 +131,7 @@ def get_region(
135
131
 
136
132
  @defer
137
133
  def run(dry_run: bool, thread_pool_size: int, defer: Callable | None = None) -> None:
138
- utc_now = datetime.utcnow()
134
+ now = utc_now()
139
135
  gqlapi = gql.get_api()
140
136
  aws_accounts = aws_accounts_query(gqlapi.query).accounts
141
137
 
@@ -177,7 +173,7 @@ def run(dry_run: bool, thread_pool_size: int, defer: Callable | None = None) ->
177
173
  # Build AWSApi object. We will use all those accounts listed in ami_accounts since
178
174
  # we will also need to look for used AMIs.
179
175
  accounts_dicted = [
180
- account.dict(by_alias=True)
176
+ account.model_dump(by_alias=True)
181
177
  for account in aws_accounts or []
182
178
  if account.name in ami_accounts
183
179
  ]
@@ -222,7 +218,7 @@ def run(dry_run: bool, thread_pool_size: int, defer: Callable | None = None) ->
222
218
  owner=account.uid,
223
219
  regex=cleanup_config.regex,
224
220
  age_in_seconds=age_in_seconds,
225
- utc_now=utc_now,
221
+ now=now,
226
222
  )
227
223
 
228
224
  for ami in aws_amis:
@@ -1,17 +1,19 @@
1
1
  import logging
2
+ import re
2
3
  from collections.abc import (
3
- Callable,
4
4
  Iterable,
5
5
  Mapping,
6
6
  )
7
7
  from typing import Any
8
8
 
9
9
  from reconcile import queries
10
+ from reconcile.typed_queries.aws_account_tags import get_aws_account_tags
11
+ from reconcile.typed_queries.external_resources import get_settings
10
12
  from reconcile.utils.aws_api import AWSApi
11
- from reconcile.utils.defer import defer
12
13
 
13
14
  QONTRACT_INTEGRATION = "aws-ami-share"
14
- MANAGED_TAG = {"Key": "managed_by_integration", "Value": QONTRACT_INTEGRATION}
15
+
16
+ MANAGED_TAG = {"managed_by_integration": QONTRACT_INTEGRATION}
15
17
 
16
18
 
17
19
  def filter_accounts(accounts: Iterable[dict[str, Any]]) -> list[dict[str, Any]]:
@@ -37,65 +39,70 @@ def get_region(
37
39
  return region
38
40
 
39
41
 
40
- @defer
41
- def run(dry_run: bool, defer: Callable | None = None) -> None:
42
+ def share_ami(
43
+ dry_run: bool,
44
+ src_account: Mapping[str, Any],
45
+ share: Mapping[str, Any],
46
+ default_tags: dict[str, str],
47
+ aws_api: AWSApi,
48
+ ) -> None:
49
+ dst_account = share["account"]
50
+ regex = re.compile(share["regex"])
51
+ region = get_region(share, src_account, dst_account)
52
+ src_amis = aws_api.get_amis_details(src_account, src_account, regex, region)
53
+ dst_amis = aws_api.get_amis_details(dst_account, src_account, regex, region)
54
+
55
+ for ami_id, src_ami_tags in src_amis.items():
56
+ dst_ami_tags = dst_amis.get(ami_id)
57
+ if dst_ami_tags is None:
58
+ logging.info([
59
+ "share_ami",
60
+ src_account["name"],
61
+ dst_account["name"],
62
+ ami_id,
63
+ ])
64
+ if not dry_run:
65
+ aws_api.share_ami(src_account, dst_account["uid"], ami_id, region)
66
+ dst_account_tags = default_tags | get_aws_account_tags(
67
+ dst_account.get("organization", None)
68
+ )
69
+ desired_tags = src_ami_tags | dst_account_tags | MANAGED_TAG
70
+ current_tags = dst_ami_tags or {}
71
+
72
+ if desired_tags != current_tags:
73
+ logging.info([
74
+ "tag_shared_ami",
75
+ dst_account["name"],
76
+ ami_id,
77
+ desired_tags,
78
+ ])
79
+ if not dry_run:
80
+ aws_api.create_tags(dst_account, ami_id, desired_tags)
81
+
82
+
83
+ def run(dry_run: bool) -> None:
42
84
  accounts = queries.get_aws_accounts(sharing=True)
43
85
  sharing_accounts = filter_accounts(accounts)
44
86
  settings = queries.get_app_interface_settings()
45
- aws_api = AWSApi(1, sharing_accounts, settings=settings, init_users=False)
46
- if defer:
47
- defer(aws_api.cleanup)
48
-
49
- for src_account in sharing_accounts:
50
- sharing = src_account.get("sharing")
51
- if not sharing:
52
- continue
53
- for share in sharing:
54
- if share["provider"] != "ami":
55
- continue
56
- dst_account = share["account"]
57
- regex = share["regex"]
58
- region = get_region(share, src_account, dst_account)
59
- src_amis = aws_api.get_amis_details(src_account, src_account, regex, region)
60
- dst_amis = aws_api.get_amis_details(dst_account, src_account, regex, region)
61
-
62
- for src_ami in src_amis:
63
- src_ami_id = src_ami["image_id"]
64
- found_dst_amis = [d for d in dst_amis if d["image_id"] == src_ami_id]
65
- if not found_dst_amis:
66
- logging.info([
67
- "share_ami",
68
- src_account["name"],
69
- dst_account["name"],
70
- src_ami_id,
71
- ])
72
- if not dry_run:
73
- aws_api.share_ami(
74
- src_account, dst_account["uid"], src_ami_id, region
75
- )
76
- # we assume an unshared ami does not have tags
77
- found_dst_amis = [{"image_id": src_ami_id, "tags": []}]
78
-
79
- dst_ami = found_dst_amis[0]
80
- dst_ami_id = dst_ami["image_id"]
81
- dst_ami_tags = dst_ami["tags"]
82
- if MANAGED_TAG not in dst_ami_tags:
83
- logging.info([
84
- "tag_shared_ami",
85
- dst_account["name"],
86
- dst_ami_id,
87
- MANAGED_TAG,
88
- ])
89
- if not dry_run:
90
- aws_api.create_tag(dst_account, dst_ami_id, MANAGED_TAG)
91
- src_ami_tags = src_ami["tags"]
92
- for src_tag in src_ami_tags:
93
- if src_tag not in dst_ami_tags:
94
- logging.info([
95
- "tag_shared_ami",
96
- dst_account["name"],
97
- dst_ami_id,
98
- src_tag,
99
- ])
100
- if not dry_run:
101
- aws_api.create_tag(dst_account, dst_ami_id, src_tag)
87
+ try:
88
+ default_tags = get_settings().default_tags
89
+ except ValueError:
90
+ # no external resources settings found
91
+ default_tags = {}
92
+
93
+ with AWSApi(
94
+ 1,
95
+ sharing_accounts,
96
+ settings=settings,
97
+ init_users=False,
98
+ ) as aws_api:
99
+ for src_account in sharing_accounts:
100
+ for share in src_account.get("sharing") or []:
101
+ if share["provider"] == "ami":
102
+ share_ami(
103
+ dry_run=dry_run,
104
+ src_account=src_account,
105
+ share=share,
106
+ default_tags=default_tags,
107
+ aws_api=aws_api,
108
+ )