qontract-reconcile 0.10.2.dev334__py3-none-any.whl → 0.10.2.dev439__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.

Potentially problematic release.


This version of qontract-reconcile might be problematic. Click here for more details.

Files changed (370) hide show
  1. {qontract_reconcile-0.10.2.dev334.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/METADATA +13 -12
  2. {qontract_reconcile-0.10.2.dev334.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/RECORD +366 -361
  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_ecr_image_pull_secrets.py +3 -3
  19. reconcile/aws_iam_keys.py +1 -0
  20. reconcile/aws_saml_idp/integration.py +12 -4
  21. reconcile/aws_saml_roles/integration.py +32 -25
  22. reconcile/aws_version_sync/integration.py +6 -12
  23. reconcile/change_owners/bundle.py +3 -3
  24. reconcile/change_owners/change_log_tracking.py +3 -2
  25. reconcile/change_owners/change_owners.py +1 -1
  26. reconcile/change_owners/diff.py +2 -4
  27. reconcile/checkpoint.py +11 -3
  28. reconcile/cli.py +111 -18
  29. reconcile/dashdotdb_dora.py +5 -12
  30. reconcile/dashdotdb_slo.py +1 -1
  31. reconcile/database_access_manager.py +123 -117
  32. reconcile/dynatrace_token_provider/integration.py +1 -1
  33. reconcile/endpoints_discovery/integration.py +4 -1
  34. reconcile/endpoints_discovery/merge_request.py +1 -1
  35. reconcile/endpoints_discovery/merge_request_manager.py +9 -11
  36. reconcile/external_resources/factories.py +5 -12
  37. reconcile/external_resources/integration.py +1 -1
  38. reconcile/external_resources/manager.py +8 -5
  39. reconcile/external_resources/meta.py +0 -1
  40. reconcile/external_resources/metrics.py +1 -1
  41. reconcile/external_resources/model.py +20 -20
  42. reconcile/external_resources/reconciler.py +7 -4
  43. reconcile/external_resources/secrets_sync.py +8 -11
  44. reconcile/external_resources/state.py +26 -16
  45. reconcile/fleet_labeler/integration.py +1 -1
  46. reconcile/gabi_authorized_users.py +8 -5
  47. reconcile/gcp_image_mirror.py +2 -2
  48. reconcile/github_org.py +1 -1
  49. reconcile/github_owners.py +4 -0
  50. reconcile/gitlab_housekeeping.py +13 -15
  51. reconcile/gitlab_members.py +6 -12
  52. reconcile/gitlab_mr_sqs_consumer.py +2 -2
  53. reconcile/gitlab_owners.py +15 -11
  54. reconcile/gitlab_permissions.py +8 -12
  55. reconcile/glitchtip_project_alerts/integration.py +3 -1
  56. reconcile/gql_definitions/acs/acs_instances.py +10 -10
  57. reconcile/gql_definitions/acs/acs_policies.py +5 -5
  58. reconcile/gql_definitions/acs/acs_rbac.py +6 -6
  59. reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +32 -32
  60. reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +26 -26
  61. reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +6 -7
  62. reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
  63. reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
  64. reconcile/gql_definitions/automated_actions/instance.py +51 -12
  65. reconcile/gql_definitions/aws_account_manager/aws_accounts.py +11 -11
  66. reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +20 -10
  67. reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +28 -68
  68. reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +20 -10
  69. reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +20 -10
  70. reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
  71. reconcile/gql_definitions/aws_version_sync/clusters.py +10 -10
  72. reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
  73. reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
  74. reconcile/gql_definitions/change_owners/queries/self_service_roles.py +9 -9
  75. reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +18 -18
  76. reconcile/gql_definitions/common/alerting_services_settings.py +9 -9
  77. reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
  78. reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
  79. reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
  80. reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
  81. reconcile/gql_definitions/common/app_interface_roles.py +120 -0
  82. reconcile/gql_definitions/common/app_interface_state_settings.py +10 -10
  83. reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
  84. reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
  85. reconcile/gql_definitions/common/apps.py +5 -5
  86. reconcile/gql_definitions/common/aws_vpc_requests.py +22 -9
  87. reconcile/gql_definitions/common/aws_vpcs.py +11 -11
  88. reconcile/gql_definitions/common/clusters.py +37 -35
  89. reconcile/gql_definitions/common/clusters_minimal.py +14 -14
  90. reconcile/gql_definitions/common/clusters_with_dms.py +6 -6
  91. reconcile/gql_definitions/common/clusters_with_peering.py +29 -30
  92. reconcile/gql_definitions/common/github_orgs.py +10 -10
  93. reconcile/gql_definitions/common/jira_settings.py +10 -10
  94. reconcile/gql_definitions/common/jiralert_settings.py +5 -5
  95. reconcile/gql_definitions/common/ldap_settings.py +5 -5
  96. reconcile/gql_definitions/common/namespaces.py +42 -44
  97. reconcile/gql_definitions/common/namespaces_minimal.py +15 -13
  98. reconcile/gql_definitions/common/ocm_env_telemeter.py +12 -12
  99. reconcile/gql_definitions/common/ocm_environments.py +19 -19
  100. reconcile/gql_definitions/common/pagerduty_instances.py +9 -9
  101. reconcile/gql_definitions/common/pgp_reencryption_settings.py +6 -6
  102. reconcile/gql_definitions/common/pipeline_providers.py +29 -29
  103. reconcile/gql_definitions/common/quay_instances.py +5 -5
  104. reconcile/gql_definitions/common/quay_orgs.py +5 -5
  105. reconcile/gql_definitions/common/reserved_networks.py +5 -5
  106. reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
  107. reconcile/gql_definitions/common/saas_files.py +44 -44
  108. reconcile/gql_definitions/common/saas_target_namespaces.py +10 -10
  109. reconcile/gql_definitions/common/saasherder_settings.py +5 -5
  110. reconcile/gql_definitions/common/slack_workspaces.py +5 -5
  111. reconcile/gql_definitions/common/smtp_client_settings.py +19 -19
  112. reconcile/gql_definitions/common/state_aws_account.py +7 -8
  113. reconcile/gql_definitions/common/users.py +5 -5
  114. reconcile/gql_definitions/common/users_with_paths.py +5 -5
  115. reconcile/gql_definitions/cost_report/app_names.py +5 -5
  116. reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
  117. reconcile/gql_definitions/cost_report/settings.py +9 -9
  118. reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +43 -43
  119. reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +10 -10
  120. reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
  121. reconcile/gql_definitions/email_sender/apps.py +5 -5
  122. reconcile/gql_definitions/email_sender/emails.py +8 -8
  123. reconcile/gql_definitions/email_sender/users.py +6 -6
  124. reconcile/gql_definitions/endpoints_discovery/apps.py +10 -10
  125. reconcile/gql_definitions/external_resources/aws_accounts.py +9 -9
  126. reconcile/gql_definitions/external_resources/external_resources_modules.py +23 -23
  127. reconcile/gql_definitions/external_resources/external_resources_namespaces.py +494 -410
  128. reconcile/gql_definitions/external_resources/external_resources_settings.py +28 -26
  129. reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
  130. reconcile/gql_definitions/fleet_labeler/fleet_labels.py +40 -40
  131. reconcile/gql_definitions/fragments/aus_organization.py +5 -5
  132. reconcile/gql_definitions/fragments/aws_account_common.py +7 -5
  133. reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
  134. reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
  135. reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
  136. reconcile/gql_definitions/fragments/{aws_vpc_request_subnet.py → aws_organization.py} +12 -8
  137. reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
  138. reconcile/gql_definitions/fragments/aws_vpc_request.py +12 -5
  139. reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
  140. reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
  141. reconcile/gql_definitions/fragments/disable.py +5 -5
  142. reconcile/gql_definitions/fragments/email_service.py +5 -5
  143. reconcile/gql_definitions/fragments/email_user.py +5 -5
  144. reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
  145. reconcile/gql_definitions/fragments/membership_source.py +5 -5
  146. reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
  147. reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
  148. reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
  149. reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
  150. reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
  151. reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
  152. reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
  153. reconcile/gql_definitions/fragments/resource_values.py +5 -5
  154. reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
  155. reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
  156. reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
  157. reconcile/gql_definitions/fragments/terraform_state.py +5 -5
  158. reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
  159. reconcile/gql_definitions/fragments/user.py +5 -5
  160. reconcile/gql_definitions/fragments/vault_secret.py +5 -5
  161. reconcile/gql_definitions/gcp/gcp_docker_repos.py +9 -9
  162. reconcile/gql_definitions/gcp/gcp_projects.py +9 -9
  163. reconcile/gql_definitions/gitlab_members/gitlab_instances.py +9 -9
  164. reconcile/gql_definitions/gitlab_members/permissions.py +9 -9
  165. reconcile/gql_definitions/glitchtip/glitchtip_instance.py +9 -9
  166. reconcile/gql_definitions/glitchtip/glitchtip_project.py +11 -11
  167. reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +9 -9
  168. reconcile/gql_definitions/integrations/integrations.py +48 -51
  169. reconcile/gql_definitions/introspection.json +3207 -1683
  170. reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +11 -11
  171. reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +10 -10
  172. reconcile/gql_definitions/jira/jira_servers.py +5 -5
  173. reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +14 -10
  174. reconcile/gql_definitions/jumphosts/jumphosts.py +13 -13
  175. reconcile/gql_definitions/ldap_groups/roles.py +5 -5
  176. reconcile/gql_definitions/ldap_groups/settings.py +9 -9
  177. reconcile/gql_definitions/maintenance/maintenances.py +5 -5
  178. reconcile/gql_definitions/membershipsources/roles.py +5 -5
  179. reconcile/gql_definitions/ocm_labels/clusters.py +18 -19
  180. reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
  181. reconcile/gql_definitions/openshift_cluster_bots/clusters.py +22 -22
  182. reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
  183. reconcile/gql_definitions/openshift_groups/managed_roles.py +6 -6
  184. reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +10 -10
  185. reconcile/gql_definitions/quay_membership/quay_membership.py +6 -6
  186. reconcile/gql_definitions/rhcs/certs.py +33 -87
  187. reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +43 -0
  188. reconcile/gql_definitions/rhidp/organizations.py +18 -18
  189. reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
  190. reconcile/gql_definitions/service_dependencies/service_dependencies.py +8 -8
  191. reconcile/gql_definitions/sharding/aws_accounts.py +10 -10
  192. reconcile/gql_definitions/sharding/ocm_organization.py +8 -8
  193. reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
  194. reconcile/gql_definitions/skupper_network/skupper_networks.py +10 -10
  195. reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
  196. reconcile/gql_definitions/slack_usergroups/permissions.py +9 -9
  197. reconcile/gql_definitions/slack_usergroups/users.py +5 -5
  198. reconcile/gql_definitions/slo_documents/slo_documents.py +5 -5
  199. reconcile/gql_definitions/status_board/status_board.py +6 -7
  200. reconcile/gql_definitions/statuspage/statuspages.py +9 -9
  201. reconcile/gql_definitions/templating/template_collection.py +5 -5
  202. reconcile/gql_definitions/templating/templates.py +5 -5
  203. reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +6 -6
  204. reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +11 -11
  205. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +11 -11
  206. reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +20 -25
  207. reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +6 -6
  208. reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +12 -12
  209. reconcile/gql_definitions/terraform_init/aws_accounts.py +23 -9
  210. reconcile/gql_definitions/terraform_repo/terraform_repo.py +9 -9
  211. reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
  212. reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +440 -407
  213. reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +23 -17
  214. reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +9 -9
  215. reconcile/gql_definitions/vault_instances/vault_instances.py +61 -61
  216. reconcile/gql_definitions/vault_policies/vault_policies.py +11 -11
  217. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +8 -8
  218. reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +5 -5
  219. reconcile/integrations_manager.py +3 -3
  220. reconcile/jenkins_worker_fleets.py +10 -8
  221. reconcile/jira_permissions_validator.py +237 -122
  222. reconcile/ldap_groups/integration.py +1 -1
  223. reconcile/ocm/types.py +35 -56
  224. reconcile/ocm_aws_infrastructure_access.py +1 -1
  225. reconcile/ocm_clusters.py +4 -4
  226. reconcile/ocm_labels/integration.py +3 -2
  227. reconcile/ocm_machine_pools.py +33 -27
  228. reconcile/openshift_base.py +113 -5
  229. reconcile/openshift_cluster_bots.py +3 -2
  230. reconcile/openshift_namespace_labels.py +1 -1
  231. reconcile/openshift_namespaces.py +97 -101
  232. reconcile/openshift_resources_base.py +6 -2
  233. reconcile/openshift_rhcs_certs.py +74 -37
  234. reconcile/openshift_rolebindings.py +230 -130
  235. reconcile/openshift_saas_deploy.py +6 -7
  236. reconcile/openshift_saas_deploy_change_tester.py +9 -7
  237. reconcile/openshift_saas_deploy_trigger_cleaner.py +3 -5
  238. reconcile/openshift_serviceaccount_tokens.py +2 -2
  239. reconcile/openshift_upgrade_watcher.py +4 -4
  240. reconcile/openshift_users.py +5 -3
  241. reconcile/oum/labelset.py +5 -3
  242. reconcile/oum/models.py +1 -4
  243. reconcile/prometheus_rules_tester/integration.py +3 -3
  244. reconcile/quay_mirror.py +1 -1
  245. reconcile/queries.py +131 -0
  246. reconcile/rhidp/common.py +3 -5
  247. reconcile/rhidp/sso_client/base.py +16 -5
  248. reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
  249. reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
  250. reconcile/skupper_network/integration.py +2 -2
  251. reconcile/slack_usergroups.py +35 -14
  252. reconcile/sql_query.py +1 -0
  253. reconcile/status_board.py +6 -6
  254. reconcile/statuspage/atlassian.py +7 -7
  255. reconcile/statuspage/integrations/maintenances.py +4 -3
  256. reconcile/statuspage/page.py +4 -9
  257. reconcile/statuspage/status.py +5 -8
  258. reconcile/templates/rosa-classic-cluster-creation.sh.j2 +5 -1
  259. reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +4 -1
  260. reconcile/templating/lib/merge_request_manager.py +2 -2
  261. reconcile/templating/lib/rendering.py +3 -3
  262. reconcile/templating/renderer.py +12 -13
  263. reconcile/terraform_aws_route53.py +7 -1
  264. reconcile/terraform_cloudflare_dns.py +3 -3
  265. reconcile/terraform_cloudflare_resources.py +5 -5
  266. reconcile/terraform_cloudflare_users.py +3 -2
  267. reconcile/terraform_init/integration.py +187 -23
  268. reconcile/terraform_repo.py +16 -12
  269. reconcile/terraform_resources.py +17 -7
  270. reconcile/terraform_tgw_attachments.py +27 -19
  271. reconcile/terraform_users.py +7 -0
  272. reconcile/terraform_vpc_peerings.py +14 -3
  273. reconcile/terraform_vpc_resources/integration.py +20 -8
  274. reconcile/typed_queries/app_interface_roles.py +10 -0
  275. reconcile/typed_queries/aws_account_tags.py +41 -0
  276. reconcile/typed_queries/cost_report/app_names.py +1 -1
  277. reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
  278. reconcile/typed_queries/saas_files.py +13 -13
  279. reconcile/typed_queries/status_board.py +2 -2
  280. reconcile/unleash_feature_toggles/integration.py +4 -2
  281. reconcile/utils/acs/base.py +6 -3
  282. reconcile/utils/acs/policies.py +2 -2
  283. reconcile/utils/aggregated_list.py +4 -3
  284. reconcile/utils/aws_api.py +51 -20
  285. reconcile/utils/aws_api_typed/api.py +38 -9
  286. reconcile/utils/aws_api_typed/cloudformation.py +149 -0
  287. reconcile/utils/aws_api_typed/logs.py +73 -0
  288. reconcile/utils/aws_api_typed/organization.py +4 -2
  289. reconcile/utils/binary.py +7 -12
  290. reconcile/utils/datetime_util.py +67 -0
  291. reconcile/utils/deadmanssnitch_api.py +1 -1
  292. reconcile/utils/differ.py +2 -3
  293. reconcile/utils/early_exit_cache.py +11 -12
  294. reconcile/utils/expiration.py +7 -3
  295. reconcile/utils/external_resource_spec.py +24 -1
  296. reconcile/utils/filtering.py +1 -1
  297. reconcile/utils/gitlab_api.py +7 -5
  298. reconcile/utils/glitchtip/client.py +6 -2
  299. reconcile/utils/glitchtip/models.py +25 -28
  300. reconcile/utils/gql.py +4 -7
  301. reconcile/utils/helm.py +2 -1
  302. reconcile/utils/helpers.py +1 -1
  303. reconcile/utils/instrumented_wrappers.py +1 -1
  304. reconcile/utils/internal_groups/client.py +2 -2
  305. reconcile/utils/internal_groups/models.py +8 -17
  306. reconcile/utils/jinja2/utils.py +6 -8
  307. reconcile/utils/jira_client.py +82 -63
  308. reconcile/utils/jjb_client.py +28 -15
  309. reconcile/utils/jobcontroller/controller.py +2 -2
  310. reconcile/utils/jobcontroller/models.py +17 -1
  311. reconcile/utils/json.py +74 -0
  312. reconcile/utils/membershipsources/app_interface_resolver.py +4 -2
  313. reconcile/utils/membershipsources/models.py +16 -23
  314. reconcile/utils/membershipsources/resolver.py +4 -2
  315. reconcile/utils/merge_request_manager/merge_request_manager.py +4 -4
  316. reconcile/utils/merge_request_manager/parser.py +6 -6
  317. reconcile/utils/metrics.py +5 -5
  318. reconcile/utils/models.py +304 -82
  319. reconcile/utils/mr/app_interface_reporter.py +2 -2
  320. reconcile/utils/mr/base.py +2 -2
  321. reconcile/utils/mr/notificator.py +3 -3
  322. reconcile/utils/mr/update_access_report_base.py +3 -4
  323. reconcile/utils/mr/user_maintenance.py +3 -2
  324. reconcile/utils/oc.py +249 -203
  325. reconcile/utils/oc_filters.py +3 -3
  326. reconcile/utils/ocm/addons.py +0 -1
  327. reconcile/utils/ocm/base.py +18 -21
  328. reconcile/utils/ocm/cluster_groups.py +1 -1
  329. reconcile/utils/ocm/identity_providers.py +2 -2
  330. reconcile/utils/ocm/labels.py +1 -1
  331. reconcile/utils/ocm/products.py +9 -3
  332. reconcile/utils/ocm/search_filters.py +3 -6
  333. reconcile/utils/ocm/service_log.py +4 -6
  334. reconcile/utils/ocm/sre_capability_labels.py +20 -13
  335. reconcile/utils/openshift_resource.py +10 -5
  336. reconcile/utils/output.py +3 -2
  337. reconcile/utils/pagerduty_api.py +10 -7
  338. reconcile/utils/promotion_state.py +6 -11
  339. reconcile/utils/raw_github_api.py +1 -1
  340. reconcile/utils/rhcsv2_certs.py +138 -35
  341. reconcile/utils/rosa/session.py +16 -0
  342. reconcile/utils/runtime/integration.py +2 -3
  343. reconcile/utils/runtime/runner.py +2 -2
  344. reconcile/utils/saasherder/interfaces.py +13 -20
  345. reconcile/utils/saasherder/models.py +25 -21
  346. reconcile/utils/saasherder/saasherder.py +55 -31
  347. reconcile/utils/slack_api.py +26 -4
  348. reconcile/utils/sloth.py +224 -0
  349. reconcile/utils/sqs_gateway.py +2 -1
  350. reconcile/utils/state.py +2 -1
  351. reconcile/utils/structs.py +1 -1
  352. reconcile/utils/terraform_client.py +5 -4
  353. reconcile/utils/terrascript_aws_client.py +192 -114
  354. reconcile/utils/unleash/server.py +2 -8
  355. reconcile/utils/vault.py +5 -12
  356. reconcile/utils/vcs.py +8 -8
  357. reconcile/vault_replication.py +107 -42
  358. tools/app_interface_reporter.py +4 -4
  359. tools/cli_commands/cost_report/cost_management_api.py +3 -3
  360. tools/cli_commands/cost_report/view.py +7 -6
  361. tools/cli_commands/erv2.py +1 -1
  362. tools/cli_commands/systems_and_tools.py +5 -1
  363. tools/qontract_cli.py +31 -18
  364. tools/template_validation.py +3 -1
  365. reconcile/gql_definitions/cna/__init__.py +0 -0
  366. reconcile/gql_definitions/cna/queries/__init__.py +0 -0
  367. reconcile/gql_definitions/ocm_oidc_idp/__init__.py +0 -0
  368. reconcile/gql_definitions/ocm_subscription_labels/__init__.py +0 -0
  369. {qontract_reconcile-0.10.2.dev334.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/WHEEL +0 -0
  370. {qontract_reconcile-0.10.2.dev334.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/entry_points.txt +0 -0
@@ -19,19 +19,19 @@ class Namespace(Protocol):
19
19
  NS = TypeVar("NS", bound=Namespace)
20
20
 
21
21
 
22
- def filter_namespaces_by_cluster(
22
+ def filter_namespaces_by_cluster[NS: Namespace](
23
23
  namespaces: Iterable[NS], cluster_names: Iterable[str]
24
24
  ) -> list[NS]:
25
25
  return [n for n in namespaces if n.cluster.name in cluster_names]
26
26
 
27
27
 
28
- def filter_namespaces_by_name(
28
+ def filter_namespaces_by_name[NS: Namespace](
29
29
  namespaces: Iterable[NS], namespace_names: Iterable[str]
30
30
  ) -> list[NS]:
31
31
  return [n for n in namespaces if n.name in namespace_names]
32
32
 
33
33
 
34
- def filter_namespaces_by_cluster_and_namespace(
34
+ def filter_namespaces_by_cluster_and_namespace[NS: Namespace](
35
35
  namespaces: Iterable[NS],
36
36
  cluster_names: Iterable[str] | None,
37
37
  namespace_names: Iterable[str] | None,
@@ -188,7 +188,6 @@ class AddonServiceV2(AddonService):
188
188
  next_run=policy.get("next_run"),
189
189
  version=policy["version"],
190
190
  state=policy.get("state"),
191
- addon_service=self,
192
191
  )
193
192
  )
194
193
 
@@ -141,16 +141,16 @@ class OCMClusterAWSOperatorRole(BaseModel):
141
141
 
142
142
 
143
143
  class OCMAWSSTS(OCMClusterFlag):
144
- role_arn: str | None
145
- support_role_arn: str | None
146
- oidc_endpoint_url: str | None
147
- operator_iam_roles: list[OCMClusterAWSOperatorRole] | None
148
- instance_iam_roles: dict[str, str] | None
149
- operator_role_prefix: str | None
144
+ role_arn: str | None = None
145
+ support_role_arn: str | None = None
146
+ oidc_endpoint_url: str | None = None
147
+ operator_iam_roles: list[OCMClusterAWSOperatorRole] | None = None
148
+ instance_iam_roles: dict[str, str] | None = None
149
+ operator_role_prefix: str | None = None
150
150
 
151
151
 
152
152
  class OCMClusterAWSSettings(BaseModel):
153
- sts: OCMAWSSTS | None
153
+ sts: OCMAWSSTS | None = None
154
154
 
155
155
  @property
156
156
  def sts_enabled(self) -> bool:
@@ -264,21 +264,21 @@ class OCMCluster(BaseModel):
264
264
  product: OCMModelLink
265
265
  identity_providers: OCMCollectionLink
266
266
 
267
- aws: OCMClusterAWSSettings | None
267
+ aws: OCMClusterAWSSettings | None = None
268
268
 
269
269
  version: OCMClusterVersion
270
270
 
271
271
  hypershift: OCMClusterFlag
272
272
 
273
- console: OCMClusterConsole | None
273
+ console: OCMClusterConsole | None = None
274
274
 
275
- api: OCMClusterAPI | None
275
+ api: OCMClusterAPI | None = None
276
276
 
277
- dns: OCMClusterDns | None
277
+ dns: OCMClusterDns | None = None
278
278
 
279
- external_configuration: OCMExternalConfiguration | None
279
+ external_configuration: OCMExternalConfiguration | None = None
280
280
 
281
- external_auth_config: OCMExternalAuthConfig | None
281
+ external_auth_config: OCMExternalAuthConfig | None = None
282
282
 
283
283
  def minor_version(self) -> str:
284
284
  version_info = parse_semver(self.version.raw_id)
@@ -570,15 +570,12 @@ class OCMOIdentityProviderGithub(OCMOIdentityProvider):
570
570
  )
571
571
 
572
572
 
573
- class OCMOIdentityProviderOidcOpenIdClaims(BaseModel):
573
+ class OCMOIdentityProviderOidcOpenIdClaims(BaseModel, frozen=True):
574
574
  email: list[str]
575
- name: list[str]
575
+ name: list[str] = []
576
576
  preferred_username: list[str]
577
577
  groups: list[str] = []
578
578
 
579
- class Config:
580
- frozen = True
581
-
582
579
 
583
580
  class OCMOIdentityProviderOidcOpenId(BaseModel):
584
581
  client_id: str
@@ -618,11 +615,11 @@ class OCMAddonUpgradePolicy(BaseModel):
618
615
  id: str
619
616
  addon_id: str
620
617
  cluster_id: str
621
- next_run: str | None
622
- schedule: str | None
618
+ next_run: str | None = None
619
+ schedule: str | None = None
623
620
  schedule_type: str
624
621
  version: str
625
- state: str | None
622
+ state: str | None = None
626
623
 
627
624
 
628
625
  def build_label_container(
@@ -17,7 +17,7 @@ def add_user_to_cluster_group(
17
17
  """
18
18
  ocm_api.post(
19
19
  build_cluster_group_users_url(cluster_id, group),
20
- OCMClusterUser(id=user_name).dict(by_alias=True),
20
+ OCMClusterUser(id=user_name).model_dump(by_alias=True),
21
21
  )
22
22
 
23
23
 
@@ -42,7 +42,7 @@ def add_identity_provider(
42
42
  )
43
43
  ocm_api.post(
44
44
  api_path=ocm_cluster.identity_providers.href,
45
- data=idp.dict(by_alias=True, exclude_none=True),
45
+ data=idp.model_dump(by_alias=True, exclude_none=True),
46
46
  )
47
47
 
48
48
 
@@ -55,7 +55,7 @@ def update_identity_provider(
55
55
  raise ValueError(f"IDP {idp.name} does not have a href!")
56
56
  ocm_api.patch(
57
57
  api_path=idp.href,
58
- data=idp.dict(by_alias=True, exclude_none=True, exclude={"name"}),
58
+ data=idp.model_dump(by_alias=True, exclude_none=True, exclude={"name"}),
59
59
  )
60
60
 
61
61
 
@@ -159,7 +159,7 @@ def build_container_for_prefix(
159
159
 
160
160
  return LabelContainer(
161
161
  labels={
162
- strip_prefix_if_needed(label.key): label.copy(
162
+ strip_prefix_if_needed(label.key): label.model_copy(
163
163
  update={"key": strip_prefix_if_needed(label.key)}
164
164
  )
165
165
  for label in container.labels.values()
@@ -47,6 +47,7 @@ SPEC_ATTR_MULTI_AZ = "multi_az"
47
47
  SPEC_ATTR_HYPERSHIFT = "hypershift"
48
48
  SPEC_ATTR_SUBNET_IDS = "subnet_ids"
49
49
  SPEC_ATTR_AVAILABILITY_ZONES = "availability_zones"
50
+ SPEC_ATTR_FIPS = "fips"
50
51
 
51
52
  SPEC_ATTR_NETWORK = "network"
52
53
  IGNORE_NETWORK_TYPE_ATTR = "type"
@@ -177,10 +178,11 @@ class OCMProductOsd(OCMProduct):
177
178
  ],
178
179
  provision_shard_id=provision_shard_id,
179
180
  hypershift=cluster["hypershift"]["enabled"],
181
+ fips=cluster.get("fips") or False,
180
182
  )
181
183
 
182
184
  if not cluster["ccs"]["enabled"]:
183
- cluster_spec_data = spec.dict()
185
+ cluster_spec_data = spec.model_dump()
184
186
  cluster_spec_data["storage"] = (
185
187
  cluster["storage_quota"]["value"] // BYTES_IN_GIGABYTE
186
188
  )
@@ -227,7 +229,7 @@ class OCMProductOsd(OCMProduct):
227
229
  "compute_machine_type": {"id": default_machine_pool.instance_type},
228
230
  }
229
231
  if default_machine_pool.autoscale is not None:
230
- spec["autoscale_compute"] = default_machine_pool.autoscale.dict()
232
+ spec["autoscale_compute"] = default_machine_pool.autoscale.model_dump()
231
233
  else:
232
234
  spec["compute"] = default_machine_pool.replicas
233
235
  return spec
@@ -257,6 +259,7 @@ class OCMProductOsd(OCMProduct):
257
259
  if (duwm := cluster.spec.disable_user_workload_monitoring) is not None
258
260
  else True
259
261
  ),
262
+ "fips": cluster.spec.fips,
260
263
  }
261
264
 
262
265
  # Workaround to enable type checks.
@@ -426,6 +429,7 @@ class OCMProductRosa(OCMProduct):
426
429
  subnet_ids=cluster["aws"].get("subnet_ids"),
427
430
  availability_zones=cluster["nodes"].get("availability_zones"),
428
431
  oidc_endpoint_url=oidc_endpoint_url,
432
+ fips=cluster.get("fips") or False,
429
433
  )
430
434
 
431
435
  machine_pools = [
@@ -470,7 +474,7 @@ class OCMProductRosa(OCMProduct):
470
474
  "compute_machine_type": {"id": default_machine_pool.instance_type},
471
475
  }
472
476
  if default_machine_pool.autoscale is not None:
473
- spec["autoscale_compute"] = default_machine_pool.autoscale.dict()
477
+ spec["autoscale_compute"] = default_machine_pool.autoscale.model_dump()
474
478
  else:
475
479
  spec["compute"] = default_machine_pool.replicas
476
480
  return spec
@@ -513,6 +517,7 @@ class OCMProductRosa(OCMProduct):
513
517
  if (duwm := cluster.spec.disable_user_workload_monitoring) is not None
514
518
  else True
515
519
  ),
520
+ "fips": cluster.spec.fips,
516
521
  }
517
522
 
518
523
  provision_shard_id = cluster.spec.provision_shard_id
@@ -701,6 +706,7 @@ class OCMProductHypershift(OCMProduct):
701
706
  availability_zones=cluster["nodes"].get("availability_zones"),
702
707
  hypershift=cluster["hypershift"]["enabled"],
703
708
  oidc_endpoint_url=oidc_endpoint_url,
709
+ fips=cluster.get("fips") or False,
704
710
  )
705
711
 
706
712
  network = OCMClusterNetwork(
@@ -5,7 +5,6 @@ from abc import (
5
5
  from collections.abc import Iterable
6
6
  from dataclasses import dataclass
7
7
  from datetime import (
8
- UTC,
9
8
  datetime,
10
9
  )
11
10
  from enum import Enum
@@ -16,6 +15,8 @@ from typing import (
16
15
 
17
16
  import dateparser
18
17
 
18
+ from reconcile.utils.datetime_util import utc_now
19
+
19
20
 
20
21
  @dataclass
21
22
  class FilterCondition:
@@ -166,17 +167,13 @@ class DateRangeCondition(FilterCondition):
166
167
  return date
167
168
  parsed = dateparser.parse(
168
169
  date,
169
- settings={"RELATIVE_BASE": DateRangeCondition.now()},
170
+ settings={"RELATIVE_BASE": utc_now()},
170
171
  )
171
172
  if parsed is None:
172
173
  raise InvalidFilterError(f"Invalid relative date: {date}")
173
174
 
174
175
  return parsed
175
176
 
176
- @staticmethod
177
- def now() -> datetime:
178
- return datetime.now(tz=UTC)
179
-
180
177
 
181
178
  class InvalidFilterError(Exception):
182
179
  pass
@@ -1,9 +1,7 @@
1
1
  from collections.abc import Generator
2
- from datetime import (
3
- datetime,
4
- timedelta,
5
- )
2
+ from datetime import timedelta
6
3
 
4
+ from reconcile.utils.datetime_util import utc_now
7
5
  from reconcile.utils.ocm.base import (
8
6
  OCMClusterServiceLog,
9
7
  OCMClusterServiceLogCreateModel,
@@ -47,7 +45,7 @@ def create_service_log(
47
45
  .eq("severity", service_log.severity.value)
48
46
  .eq("summary", service_log.summary)
49
47
  .eq("description", service_log.description)
50
- .after("created_at", datetime.utcnow() - dedup_interval),
48
+ .after("created_at", utc_now() - dedup_interval),
51
49
  ),
52
50
  None,
53
51
  )
@@ -57,6 +55,6 @@ def create_service_log(
57
55
  return OCMClusterServiceLog(
58
56
  **ocm_api.post(
59
57
  api_path=CLUSTER_SERVICE_LOGS_CREATE_ENDPOINT,
60
- data=service_log.dict(by_alias=True),
58
+ data=service_log.model_dump(by_alias=True),
61
59
  )
62
60
  )
@@ -1,7 +1,7 @@
1
1
  from typing import Any
2
2
 
3
- from pydantic import Field
4
- from pydantic.fields import ModelField
3
+ from pydantic import WithJsonSchema
4
+ from pydantic.fields import FieldInfo
5
5
 
6
6
  from reconcile.utils.ocm.base import (
7
7
  LabelContainer,
@@ -22,11 +22,11 @@ def sre_capability_label_key(
22
22
  return f"sre-capabilities.{sre_capability}.{config_atom}"
23
23
 
24
24
 
25
- def labelset_groupfield(group_prefix: str) -> Any:
25
+ def labelset_groupfield(group_prefix: str) -> WithJsonSchema:
26
26
  """
27
27
  Helper function to build the FieldMeta for a labelset field that groups labels.
28
28
  """
29
- return Field(group_by_prefix=group_prefix)
29
+ return WithJsonSchema({"group_by_prefix": group_prefix})
30
30
 
31
31
 
32
32
  def build_labelset(
@@ -36,16 +36,23 @@ def build_labelset(
36
36
  Instantiates a dataclass from a set of labels.
37
37
  """
38
38
  raw_data = {
39
- field.alias: _labelset_field_value(labels, field)
40
- for field in dataclass.__fields__.values()
39
+ field.alias or name: _labelset_field_value(labels, name, field)
40
+ for name, field in dataclass.model_fields.items()
41
41
  }
42
42
  return dataclass(**raw_data)
43
43
 
44
44
 
45
- def _labelset_field_value(labels: LabelContainer, field: ModelField) -> Any | None:
46
- key_prefix = field.field_info.extra.get("group_by_prefix")
47
- if key_prefix:
48
- return build_container_for_prefix(
49
- labels, key_prefix, strip_key_prefix=True
50
- ).get_values_dict()
51
- return labels.get_label_value(field.alias)
45
+ def _labelset_field_value(
46
+ labels: LabelContainer, name: str, field: FieldInfo
47
+ ) -> Any | None:
48
+ schema = next((m for m in field.metadata if isinstance(m, WithJsonSchema)), None)
49
+ if (
50
+ schema is None
51
+ or not schema.json_schema
52
+ or "group_by_prefix" not in schema.json_schema
53
+ ):
54
+ return labels.get_label_value(field.alias or name)
55
+
56
+ return build_container_for_prefix(
57
+ labels, schema.json_schema["group_by_prefix"], strip_key_prefix=True
58
+ ).get_values_dict()
@@ -4,9 +4,8 @@ from __future__ import annotations
4
4
  import base64
5
5
  import contextlib
6
6
  import copy
7
- import datetime
8
7
  import hashlib
9
- import json
8
+ import logging
10
9
  import re
11
10
  from threading import Lock
12
11
  from typing import TYPE_CHECKING, Any
@@ -15,6 +14,8 @@ import semver
15
14
  from pydantic import BaseModel
16
15
 
17
16
  from reconcile.external_resources.meta import SECRET_UPDATED_AT
17
+ from reconcile.utils.datetime_util import to_utc_seconds_iso_format, utc_now
18
+ from reconcile.utils.json import json_dumps
18
19
  from reconcile.utils.metrics import GaugeMetric
19
20
 
20
21
  if TYPE_CHECKING:
@@ -368,8 +369,8 @@ class OpenshiftResource:
368
369
  annotations[QONTRACT_ANNOTATION_INTEGRATION] = self.integration
369
370
  annotations[QONTRACT_ANNOTATION_INTEGRATION_VERSION] = self.integration_version
370
371
  annotations[QONTRACT_ANNOTATION_SHA256SUM] = sha256sum
371
- now = datetime.datetime.utcnow().replace(microsecond=0).isoformat()
372
- annotations[QONTRACT_ANNOTATION_UPDATE] = now
372
+ now = utc_now()
373
+ annotations[QONTRACT_ANNOTATION_UPDATE] = to_utc_seconds_iso_format(now)
373
374
  if self.caller_name:
374
375
  annotations[QONTRACT_ANNOTATION_CALLER_NAME] = self.caller_name
375
376
 
@@ -530,7 +531,7 @@ class OpenshiftResource:
530
531
 
531
532
  @staticmethod
532
533
  def serialize(body: dict[str, Any]) -> str:
533
- return json.dumps(body, sort_keys=True)
534
+ return json_dumps(body)
534
535
 
535
536
  @staticmethod
536
537
  def calculate_sha256sum(body: str) -> str:
@@ -601,6 +602,10 @@ class ResourceInventory:
601
602
  resource: OpenshiftResource,
602
603
  privileged: bool = False,
603
604
  ) -> None:
605
+ if cluster not in self._clusters:
606
+ logging.error(f"Cluster {cluster} not initialized in ResourceInventory")
607
+ return
608
+
604
609
  if resource.kind_and_group in self._clusters[cluster][namespace]:
605
610
  kind = resource.kind_and_group
606
611
  else:
reconcile/utils/output.py CHANGED
@@ -1,10 +1,11 @@
1
- import json
2
1
  import re
3
2
  from collections.abc import Iterable, Mapping
4
3
 
5
4
  import yaml
6
5
  from tabulate import tabulate
7
6
 
7
+ from reconcile.utils.json import json_dumps
8
+
8
9
 
9
10
  def print_output(
10
11
  options: Mapping[str, str | bool],
@@ -30,7 +31,7 @@ def print_output(
30
31
  )
31
32
  print(formatted_content)
32
33
  elif output == "json":
33
- formatted_content = json.dumps(content)
34
+ formatted_content = json_dumps(content)
34
35
  print(formatted_content)
35
36
  elif output == "yaml":
36
37
  formatted_content = yaml.dump(content)
@@ -3,8 +3,7 @@ from collections.abc import (
3
3
  Callable,
4
4
  Iterable,
5
5
  )
6
- from datetime import datetime as dt
7
- from datetime import timedelta
6
+ from datetime import datetime, timedelta
8
7
  from typing import (
9
8
  Protocol,
10
9
  )
@@ -14,6 +13,7 @@ import requests
14
13
  from pydantic import BaseModel
15
14
  from sretoolbox.utils import retry
16
15
 
16
+ from reconcile.utils.datetime_util import utc_now
17
17
  from reconcile.utils.secret_reader import (
18
18
  HasSecret,
19
19
  SecretReader,
@@ -52,10 +52,13 @@ class PagerDutyTarget(Protocol):
52
52
  which must be implemented by a class to be compatible."""
53
53
 
54
54
  name: str
55
- instance: PagerDutyInstance
56
55
  escalation_policy_id: str | None
57
56
  schedule_id: str | None
58
57
 
58
+ @property
59
+ def instance(self) -> PagerDutyInstance:
60
+ pass
61
+
59
62
 
60
63
  class PagerDutyConfig(BaseModel):
61
64
  """PagerDuty Config."""
@@ -80,7 +83,7 @@ class PagerDutyApi:
80
83
  def get_pagerduty_users(
81
84
  self, resource_type: str, resource_id: str
82
85
  ) -> list[pypd.User]:
83
- now = dt.utcnow()
86
+ now = utc_now()
84
87
 
85
88
  try:
86
89
  if resource_type == "schedule":
@@ -103,7 +106,7 @@ class PagerDutyApi:
103
106
  self.users.append(user)
104
107
  return user.email.split("@")[0]
105
108
 
106
- def get_schedule_users(self, schedule_id: str, now: dt) -> list[pypd.User]:
109
+ def get_schedule_users(self, schedule_id: str, now: datetime) -> list[pypd.User]:
107
110
  until = now + timedelta(seconds=60)
108
111
  s = pypd.Schedule.fetch(id=schedule_id, since=now, until=until, time_zone="UTC")
109
112
  entries = s["final_schedule"]["rendered_schedule_entries"]
@@ -115,7 +118,7 @@ class PagerDutyApi:
115
118
  ]
116
119
 
117
120
  def get_escalation_policy_users(
118
- self, escalation_policy_id: str, now: dt
121
+ self, escalation_policy_id: str, now: datetime
119
122
  ) -> list[pypd.User]:
120
123
  ep = pypd.EscalationPolicy.fetch(
121
124
  id=escalation_policy_id, since=now, until=now, time_zone="UTC"
@@ -189,7 +192,7 @@ def get_pagerduty_name(user: PagerDutyUser) -> str:
189
192
  return user.pagerduty_username or user.org_username
190
193
 
191
194
 
192
- @retry(no_retry_exceptions=PagerDutyTargetError)
195
+ @retry(no_retry_exceptions=(PagerDutyTargetError,))
193
196
  def get_usernames_from_pagerduty(
194
197
  pagerduties: Iterable[PagerDutyTarget],
195
198
  users: Iterable[PagerDutyUser],
@@ -3,13 +3,12 @@ from collections import defaultdict
3
3
 
4
4
  from pydantic import (
5
5
  BaseModel,
6
- Extra,
7
6
  )
8
7
 
9
8
  from reconcile.utils.state import State
10
9
 
11
10
 
12
- class PromotionData(BaseModel):
11
+ class PromotionData(BaseModel, extra="forbid"):
13
12
  """
14
13
  A class that strictly corresponds to the json stored in S3.
15
14
 
@@ -20,17 +19,13 @@ class PromotionData(BaseModel):
20
19
 
21
20
  # The success is primarily used for SAPM auto-promotions
22
21
  success: bool
23
- target_config_hash: str | None
24
- saas_file: str | None
25
- check_in: str | None
22
+ target_config_hash: str | None = None
23
+ saas_file: str | None = None
24
+ check_in: str | None = None
26
25
  # Whether this promotion has ever succeeded
27
26
  # Note, this shouldnt be overridden on subsequent promotions of same ref
28
27
  # This attribute is primarily used by saasherder validations
29
- has_succeeded_once: bool | None
30
-
31
- class Config:
32
- smart_union = True
33
- extra = Extra.forbid
28
+ has_succeeded_once: bool | None = None
34
29
 
35
30
 
36
31
  class PromotionState:
@@ -107,5 +102,5 @@ class PromotionState:
107
102
  self, sha: str, channel: str, target_uid: str, data: PromotionData
108
103
  ) -> None:
109
104
  state_key_v2 = f"promotions_v2/{channel}/{target_uid}/{sha}"
110
- self._state.add(state_key_v2, data.dict(), force=True)
105
+ self._state.add(state_key_v2, data.model_dump(), force=True)
111
106
  logging.info("Uploaded %s to %s", data, state_key_v2)
@@ -76,7 +76,7 @@ class RawGithubApi:
76
76
  if login is not None
77
77
  ]
78
78
 
79
- def team_invitations(self, org_id: str, team_id: str) -> list[str]:
79
+ def team_invitations(self, org_id: str | int, team_id: str | int) -> list[str]:
80
80
  invitations = self.query(f"/organizations/{org_id}/team/{team_id}/invitations")
81
81
 
82
82
  return [