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
@@ -1,13 +1,16 @@
1
+ import contextlib
1
2
  from typing import Any
2
3
 
3
4
  import requests
4
5
 
6
+ from reconcile.utils.rest_api_base import ApiBase, BearerTokenAuth
7
+
5
8
 
6
9
  class QuayTeamNotFoundError(Exception):
7
10
  pass
8
11
 
9
12
 
10
- class QuayApi:
13
+ class QuayApi(ApiBase):
11
14
  LIMIT_FOLLOWS = 15
12
15
 
13
16
  def __init__(
@@ -17,14 +20,18 @@ class QuayApi:
17
20
  base_url: str = "quay.io",
18
21
  timeout: int = 60,
19
22
  ) -> None:
20
- self.token = token
23
+ # Support both hostname (e.g., "quay.io") and full URLs (e.g., "http://localhost:12345")
24
+ if base_url.startswith(("http://", "https://")):
25
+ host = base_url
26
+ else:
27
+ host = f"https://{base_url}"
28
+ super().__init__(
29
+ host=host,
30
+ auth=BearerTokenAuth(token),
31
+ read_timeout=timeout,
32
+ )
21
33
  self.organization = organization
22
- self.auth_header = {"Authorization": "Bearer %s" % (token,)}
23
34
  self.team_members: dict[str, Any] = {}
24
- self.api_url = f"https://{base_url}/api/v1"
25
-
26
- self._timeout = timeout
27
- """Timeout to use for HTTP calls to Quay (seconds)."""
28
35
 
29
36
  def list_team_members(self, team: str, **kwargs: Any) -> list[dict]:
30
37
  """
@@ -38,19 +45,20 @@ class QuayApi:
38
45
  if cache_members:
39
46
  return cache_members
40
47
 
41
- url = f"{self.api_url}/organization/{self.organization}/team/{team}/members?includePending=true"
42
-
43
- r = requests.get(url, headers=self.auth_header, timeout=self._timeout)
44
- if r.status_code == 404:
45
- raise QuayTeamNotFoundError(
46
- f"team {team} is not found in "
47
- f"org {self.organization}. "
48
- f"contact org owner to create the "
49
- f"team manually."
50
- )
51
- r.raise_for_status()
52
-
53
- body = r.json()
48
+ url = f"/api/v1/organization/{self.organization}/team/{team}/members"
49
+ params = {"includePending": "true"}
50
+
51
+ try:
52
+ body = self._get(url, params=params)
53
+ except requests.exceptions.HTTPError as e:
54
+ if e.response.status_code == 404:
55
+ raise QuayTeamNotFoundError(
56
+ f"team {team} is not found in "
57
+ f"org {self.organization}. "
58
+ f"contact org owner to create the "
59
+ f"team manually."
60
+ ) from e
61
+ raise
54
62
 
55
63
  # Using a set because members may be repeated
56
64
  members = {member["name"] for member in body["members"]}
@@ -61,30 +69,37 @@ class QuayApi:
61
69
  return members_list
62
70
 
63
71
  def user_exists(self, user: str) -> bool:
64
- url = f"{self.api_url}/users/{user}"
65
- r = requests.get(url, headers=self.auth_header, timeout=self._timeout)
66
- return r.ok
72
+ url = f"/api/v1/users/{user}"
73
+ try:
74
+ self._get(url)
75
+ return True
76
+ except requests.exceptions.HTTPError:
77
+ return False
67
78
 
68
79
  def remove_user_from_team(self, user: str, team: str) -> bool:
69
80
  """Deletes an user from a team.
70
81
 
71
82
  :raises HTTPError if there are any problems with the request
72
83
  """
73
- url_team = f"{self.api_url}/organization/{self.organization}/team/{team}/members/{user}"
84
+ url_team = (
85
+ f"/api/v1/organization/{self.organization}/team/{team}/members/{user}"
86
+ )
74
87
 
75
- r = requests.delete(url_team, headers=self.auth_header, timeout=self._timeout)
76
- if not r.ok:
77
- message = r.json().get("message", "")
88
+ try:
89
+ self._delete(url_team)
90
+ except requests.exceptions.HTTPError as e:
91
+ message = ""
92
+ if e.response is not None:
93
+ with contextlib.suppress(ValueError, AttributeError):
94
+ message = e.response.json().get("message", "")
78
95
 
79
96
  expected_message = f"User {user} does not belong to team {team}"
80
97
 
81
98
  if message != expected_message:
82
- r.raise_for_status()
99
+ raise
83
100
 
84
- url_org = f"{self.api_url}/organization/{self.organization}/members/{user}"
85
-
86
- r = requests.delete(url_org, headers=self.auth_header, timeout=self._timeout)
87
- r.raise_for_status()
101
+ url_org = f"/api/v1/organization/{self.organization}/members/{user}"
102
+ self._delete(url_org)
88
103
 
89
104
  return True
90
105
 
@@ -96,9 +111,8 @@ class QuayApi:
96
111
  if user in self.list_team_members(team, cache=True):
97
112
  return True
98
113
 
99
- url = f"{self.api_url}/organization/{self.organization}/team/{team}/members/{user}"
100
- r = requests.put(url, headers=self.auth_header, timeout=self._timeout)
101
- r.raise_for_status()
114
+ url = f"/api/v1/organization/{self.organization}/team/{team}/members/{user}"
115
+ self._put(url)
102
116
  return True
103
117
 
104
118
  def create_or_update_team(
@@ -115,17 +129,14 @@ class QuayApi:
115
129
  :raises HTTPError: unsuccessful attempt to create the team
116
130
  """
117
131
 
118
- url = f"{self.api_url}/organization/{self.organization}/team/{team}"
132
+ url = f"/api/v1/organization/{self.organization}/team/{team}"
119
133
 
120
134
  payload = {"role": role}
121
135
 
122
136
  if description:
123
137
  payload.update({"description": description})
124
138
 
125
- r = requests.put(
126
- url, headers=self.auth_header, json=payload, timeout=self._timeout
127
- )
128
- r.raise_for_status()
139
+ self._put(url, data=payload)
129
140
 
130
141
  def list_images(
131
142
  self, images: list | None = None, page: str | None = None, count: int = 0
@@ -140,7 +151,7 @@ class QuayApi:
140
151
  if count > self.LIMIT_FOLLOWS:
141
152
  raise ValueError("Too many page follows")
142
153
 
143
- url = f"{self.api_url}/repository"
154
+ url = "/api/v1/repository"
144
155
 
145
156
  # params
146
157
  params = {"namespace": self.organization}
@@ -148,13 +159,7 @@ class QuayApi:
148
159
  params["next_page"] = page
149
160
 
150
161
  # perform request
151
- r = requests.get(
152
- url, params=params, headers=self.auth_header, timeout=self._timeout
153
- )
154
- r.raise_for_status()
155
-
156
- # read body
157
- body = r.json()
162
+ body = self._get(url, params=params)
158
163
  repositories = body.get("repositories", [])
159
164
  next_page = body.get("next_page")
160
165
 
@@ -176,7 +181,7 @@ class QuayApi:
176
181
  """
177
182
  visibility = "public" if public else "private"
178
183
 
179
- url = f"{self.api_url}/repository"
184
+ url = "/repository"
180
185
 
181
186
  params = {
182
187
  "repo_kind": "image",
@@ -186,29 +191,16 @@ class QuayApi:
186
191
  "description": description,
187
192
  }
188
193
 
189
- # perform request
190
- r = requests.post(
191
- url, json=params, headers=self.auth_header, timeout=self._timeout
192
- )
193
- r.raise_for_status()
194
+ self._post(url, data=params)
194
195
 
195
196
  def repo_delete(self, repo_name: str) -> None:
196
- url = f"{self.api_url}/repository/{self.organization}/{repo_name}"
197
-
198
- # perform request
199
- r = requests.delete(url, headers=self.auth_header, timeout=self._timeout)
200
- r.raise_for_status()
197
+ url = f"/api/v1/repository/{self.organization}/{repo_name}"
198
+ self._delete(url)
201
199
 
202
200
  def repo_update_description(self, repo_name: str, description: str) -> None:
203
- url = f"{self.api_url}/repository/{self.organization}/{repo_name}"
204
-
201
+ url = f"/api/v1/repository/{self.organization}/{repo_name}"
205
202
  params = {"description": description}
206
-
207
- # perform request
208
- r = requests.put(
209
- url, json=params, headers=self.auth_header, timeout=self._timeout
210
- )
211
- r.raise_for_status()
203
+ self._put(url, data=params)
212
204
 
213
205
  def repo_make_public(self, repo_name: str) -> None:
214
206
  self._repo_change_visibility(repo_name, "public")
@@ -217,39 +209,34 @@ class QuayApi:
217
209
  self._repo_change_visibility(repo_name, "private")
218
210
 
219
211
  def _repo_change_visibility(self, repo_name: str, visibility: str) -> None:
220
- url = f"{self.api_url}/repository/{self.organization}/{repo_name}/changevisibility"
221
-
212
+ url = f"/api/v1/repository/{self.organization}/{repo_name}/changevisibility"
222
213
  params = {"visibility": visibility}
223
-
224
- # perform request
225
- r = requests.post(
226
- url, json=params, headers=self.auth_header, timeout=self._timeout
227
- )
228
- r.raise_for_status()
214
+ self._post(url, data=params)
229
215
 
230
216
  def get_repo_team_permissions(self, repo_name: str, team: str) -> str | None:
231
217
  url = (
232
- f"{self.api_url}/repository/{self.organization}/"
218
+ f"/api/v1/repository/{self.organization}/"
233
219
  + f"{repo_name}/permissions/team/{team}"
234
220
  )
235
- r = requests.get(url, headers=self.auth_header, timeout=self._timeout)
236
- if not r.ok:
237
- message = r.json().get("message")
221
+ try:
222
+ body = self._get(url)
223
+ return body.get("role") or None
224
+ except requests.exceptions.HTTPError as e:
225
+ message = ""
226
+ if e.response is not None:
227
+ with contextlib.suppress(ValueError, AttributeError):
228
+ message = e.response.json().get("message", "")
229
+
238
230
  expected_message = "Team does not have permission for repo."
239
231
  if message == expected_message:
240
232
  return None
241
233
 
242
- r.raise_for_status()
243
-
244
- return r.json().get("role") or None
234
+ raise
245
235
 
246
236
  def set_repo_team_permissions(self, repo_name: str, team: str, role: str) -> None:
247
237
  url = (
248
- f"{self.api_url}/repository/{self.organization}/"
238
+ f"/api/v1/repository/{self.organization}/"
249
239
  + f"{repo_name}/permissions/team/{team}"
250
240
  )
251
241
  body = {"role": role}
252
- r = requests.put(
253
- url, json=body, headers=self.auth_header, timeout=self._timeout
254
- )
255
- r.raise_for_status()
242
+ self._put(url, data=body)
@@ -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 [
@@ -1,22 +1,33 @@
1
+ import base64
1
2
  import re
2
3
  from datetime import UTC
4
+ from enum import StrEnum
3
5
 
4
6
  import requests
5
7
  from cryptography import x509
6
8
  from cryptography.hazmat.primitives import hashes, serialization
7
9
  from cryptography.hazmat.primitives.asymmetric import rsa
10
+ from cryptography.hazmat.primitives.serialization import pkcs12
8
11
  from cryptography.x509.oid import NameOID
9
12
  from pydantic import BaseModel, Field
10
13
 
11
14
 
12
- class RhcsV2Cert(BaseModel):
15
+ class CertificateFormat(StrEnum):
16
+ PEM = "PEM"
17
+ PKCS12 = "PKCS12"
18
+
19
+
20
+ class RhcsV2CertPem(BaseModel, validate_by_name=True, validate_by_alias=True):
13
21
  certificate: str = Field(alias="tls.crt")
14
22
  private_key: str = Field(alias="tls.key")
15
23
  ca_cert: str = Field(alias="ca.crt")
16
24
  expiration_timestamp: int
17
25
 
18
- class Config:
19
- allow_population_by_field_name = True
26
+
27
+ class RhcsV2CertPkcs12(BaseModel, validate_by_name=True, validate_by_alias=True):
28
+ pkcs12_keystore: str = Field(alias="keystore.pkcs12.b64")
29
+ pkcs12_truststore: str = Field(alias="truststore.pkcs12.b64")
30
+ expiration_timestamp: int
20
31
 
21
32
 
22
33
  def extract_cert(text: str) -> re.Match:
@@ -70,7 +81,66 @@ def get_cert_expiry_timestamp(js_escaped_pem: str) -> int:
70
81
  return int(dt_expiry.timestamp())
71
82
 
72
83
 
73
- def generate_cert(issuer_url: str, uid: str, pwd: str, ca_url: str) -> RhcsV2Cert:
84
+ def _format_pem(
85
+ private_key: rsa.RSAPrivateKey,
86
+ cert_pem: str,
87
+ ca_pem: str,
88
+ cert_expiry_timestamp: int,
89
+ ) -> RhcsV2CertPem:
90
+ """Generate RhcsV2Cert with PEM components."""
91
+ private_key_pem = private_key.private_bytes(
92
+ encoding=serialization.Encoding.PEM,
93
+ format=serialization.PrivateFormat.TraditionalOpenSSL,
94
+ encryption_algorithm=serialization.NoEncryption(),
95
+ ).decode()
96
+ return RhcsV2CertPem(
97
+ private_key=private_key_pem,
98
+ certificate=cert_pem.encode().decode("unicode_escape").replace("\\/", "/"),
99
+ ca_cert=ca_pem,
100
+ expiration_timestamp=cert_expiry_timestamp,
101
+ )
102
+
103
+
104
+ def _format_pkcs12(
105
+ private_key: rsa.RSAPrivateKey,
106
+ cert_pem: str,
107
+ ca_pem: str,
108
+ uid: str,
109
+ pwd: str,
110
+ cert_expiry_timestamp: int,
111
+ ) -> RhcsV2CertPkcs12:
112
+ """Generate PKCS#12 keystore and truststore components, returns base64-encoded strings."""
113
+ clean_cert_pem = cert_pem.encode().decode("unicode_escape").replace("\\/", "/")
114
+ cert_obj = x509.load_pem_x509_certificate(clean_cert_pem.encode())
115
+ ca_obj = x509.load_pem_x509_certificate(ca_pem.encode())
116
+ keystore_p12 = pkcs12.serialize_key_and_certificates(
117
+ name=uid.encode("utf-8"),
118
+ key=private_key,
119
+ cert=cert_obj,
120
+ cas=[ca_obj],
121
+ encryption_algorithm=serialization.BestAvailableEncryption(pwd.encode("utf-8")),
122
+ )
123
+ truststore_p12 = pkcs12.serialize_key_and_certificates(
124
+ name=b"ca-trust",
125
+ key=None,
126
+ cert=None,
127
+ cas=[ca_obj],
128
+ encryption_algorithm=serialization.NoEncryption(),
129
+ )
130
+ return RhcsV2CertPkcs12(
131
+ pkcs12_keystore=base64.b64encode(keystore_p12).decode("utf-8"),
132
+ pkcs12_truststore=base64.b64encode(truststore_p12).decode("utf-8"),
133
+ expiration_timestamp=cert_expiry_timestamp,
134
+ )
135
+
136
+
137
+ def generate_cert(
138
+ issuer_url: str,
139
+ uid: str,
140
+ pwd: str,
141
+ ca_url: str,
142
+ cert_format: CertificateFormat = CertificateFormat.PEM,
143
+ ) -> RhcsV2CertPem | RhcsV2CertPkcs12:
74
144
  private_key = rsa.generate_private_key(65537, 4096)
75
145
  csr = (
76
146
  x509.CertificateSigningRequestBuilder()
@@ -81,6 +151,7 @@ def generate_cert(issuer_url: str, uid: str, pwd: str, ca_url: str) -> RhcsV2Cer
81
151
  )
82
152
  .sign(private_key, hashes.SHA256())
83
153
  )
154
+
84
155
  data = {
85
156
  "uid": uid,
86
157
  "pwd": pwd,
@@ -90,27 +161,19 @@ def generate_cert(issuer_url: str, uid: str, pwd: str, ca_url: str) -> RhcsV2Cer
90
161
  "renewal": "false",
91
162
  "xmlOutput": "false",
92
163
  }
93
- response = requests.post(issuer_url, data=data)
164
+ response = requests.post(issuer_url, data=data, timeout=30)
94
165
  response.raise_for_status()
166
+ cert_pem = extract_cert(response.text).group(1)
167
+ cert_expiry_timestamp = get_cert_expiry_timestamp(cert_pem)
95
168
 
96
- cert_pem = extract_cert(response.text)
97
- cert_expiry_timestamp = get_cert_expiry_timestamp(cert_pem.group(1))
98
- private_key_pem = private_key.private_bytes(
99
- encoding=serialization.Encoding.PEM,
100
- format=serialization.PrivateFormat.TraditionalOpenSSL,
101
- encryption_algorithm=serialization.NoEncryption(),
102
- ).decode()
103
-
104
- response = requests.get(ca_url)
169
+ response = requests.get(ca_url, timeout=30)
105
170
  response.raise_for_status()
106
171
  ca_pem = response.text
107
172
 
108
- return RhcsV2Cert(
109
- private_key=private_key_pem,
110
- certificate=cert_pem.group(1)
111
- .encode()
112
- .decode("unicode_escape")
113
- .replace("\\/", "/"),
114
- ca_cert=ca_pem,
115
- expiration_timestamp=cert_expiry_timestamp,
116
- )
173
+ match cert_format:
174
+ case CertificateFormat.PKCS12:
175
+ return _format_pkcs12(
176
+ private_key, cert_pem, ca_pem, uid, pwd, cert_expiry_timestamp
177
+ )
178
+ case CertificateFormat.PEM:
179
+ return _format_pem(private_key, cert_pem, ca_pem, cert_expiry_timestamp)
@@ -178,6 +178,22 @@ class RosaSession:
178
178
  )
179
179
  result.write_logs_to_logger(logging.info)
180
180
 
181
+ def upgrade_rosa_roles(
182
+ self,
183
+ cluster_name: str,
184
+ upgrade_version: str,
185
+ policy_version: str,
186
+ dry_run: bool,
187
+ ) -> None:
188
+ logging.info(
189
+ f"Upgrade roles in AWS account {self.aws_account_id} to {upgrade_version}"
190
+ )
191
+ if not dry_run:
192
+ result = self.cli_execute(
193
+ f"rosa upgrade roles -c {cluster_name} --cluster-version {upgrade_version} --policy-version {policy_version} -y -m=auto"
194
+ )
195
+ result.write_logs_to_logger(logging.info)
196
+
181
197
 
182
198
  def generate_rosa_creation_script(
183
199
  cluster_name: str, cluster: OCMSpec, dry_run: bool
@@ -7,7 +7,6 @@ from dataclasses import dataclass
7
7
  from types import ModuleType
8
8
  from typing import (
9
9
  Any,
10
- Generic,
11
10
  Optional,
12
11
  TypeVar,
13
12
  )
@@ -120,7 +119,7 @@ class PydanticRunParams(RunParams, BaseModel):
120
119
  def copy_and_update(
121
120
  self: PydanticRunParamsSelfTypeVar, update: dict[str, Any]
122
121
  ) -> PydanticRunParamsSelfTypeVar:
123
- return self.copy(update=update)
122
+ return self.model_copy(update=update)
124
123
 
125
124
  def get(self, field: str) -> Any:
126
125
  return getattr(self, field)
@@ -144,7 +143,7 @@ IntegrationClassTypeVar = TypeVar(
144
143
  )
145
144
 
146
145
 
147
- class QontractReconcileIntegration(ABC, Generic[RunParamsTypeVar]):
146
+ class QontractReconcileIntegration[RunParamsTypeVar: RunParams](ABC):
148
147
  """
149
148
  The base class for all integrations. It defines the basic interface to interact
150
149
  with an integration and offers hook methods that allow the integration to opt
@@ -156,7 +156,7 @@ def run_integration_cfg(run_cfg: IntegrationRunConfiguration) -> None:
156
156
  _integration_wet_run(run_cfg.integration)
157
157
 
158
158
 
159
- def _integration_wet_run(
159
+ def _integration_wet_run[RunParamsTypeVar: RunParams](
160
160
  integration: QontractReconcileIntegration[RunParamsTypeVar],
161
161
  ) -> None:
162
162
  """
@@ -165,7 +165,7 @@ def _integration_wet_run(
165
165
  integration.run(False)
166
166
 
167
167
 
168
- def _integration_dry_run(
168
+ def _integration_dry_run[RunParamsTypeVar: RunParams](
169
169
  integration: QontractReconcileIntegration[RunParamsTypeVar],
170
170
  desired_state_diff: DesiredStateDiff | None,
171
171
  ) -> None:
@@ -1,7 +1,7 @@
1
1
  # ruff: noqa: N801
2
2
  from __future__ import annotations
3
3
 
4
- from collections.abc import Mapping, Sequence, Set
4
+ from collections.abc import Sequence
5
5
  from typing import (
6
6
  TYPE_CHECKING,
7
7
  Any,
@@ -12,6 +12,8 @@ from typing import (
12
12
  from reconcile.utils import oc_connection_parameters
13
13
 
14
14
  if TYPE_CHECKING:
15
+ from pydantic.main import IncEx
16
+
15
17
  from reconcile.gql_definitions.fragments.saas_slo_document import SLODocument
16
18
  from reconcile.utils.secret_reader import HasSecret
17
19
 
@@ -27,18 +29,12 @@ class SaasFileSecretParameters(Protocol):
27
29
  @property
28
30
  def secret(self) -> HasSecret: ...
29
31
 
30
- def dict(
31
- self,
32
- *,
33
- by_alias: bool = False,
34
- include: AbstractSetIntStr | MappingIntStrAny | None = None,
32
+ def model_dump(
33
+ self, *, by_alias: bool = False, include: IncEx | None = None
35
34
  ) -> dict[str, Any]: ...
36
35
 
37
36
 
38
37
  SaasSecretParameters = Sequence[SaasFileSecretParameters] | None
39
- # Taken from pydantic.typing
40
- AbstractSetIntStr = Set[int | str]
41
- MappingIntStrAny = Mapping[int | str, Any]
42
38
 
43
39
 
44
40
  @runtime_checkable
@@ -212,11 +208,8 @@ class SaasResourceTemplateTargetNamespace(Protocol):
212
208
  @property
213
209
  def cluster(self) -> oc_connection_parameters.Cluster: ...
214
210
 
215
- def dict(
216
- self,
217
- *,
218
- by_alias: bool = False,
219
- include: AbstractSetIntStr | MappingIntStrAny | None = None,
211
+ def model_dump(
212
+ self, *, by_alias: bool = False, include: IncEx | None = None
220
213
  ) -> dict[str, Any]: ...
221
214
 
222
215
 
@@ -249,7 +242,7 @@ class SaasResourceTemplateTargetPromotion(Protocol):
249
242
  @property
250
243
  def promotion_data(self) -> Sequence[SaasPromotionData] | None: ...
251
244
 
252
- def dict(self, *, by_alias: bool = False) -> dict[str, Any]: ...
245
+ def model_dump(self, *, by_alias: bool = False) -> dict[str, Any]: ...
253
246
 
254
247
 
255
248
  class Channel(Protocol):
@@ -274,7 +267,7 @@ class SaasPromotion(Protocol):
274
267
  @property
275
268
  def subscribe(self) -> list[Channel] | None: ...
276
269
 
277
- def dict(self, *, by_alias: bool = False) -> dict[str, Any]: ...
270
+ def model_dump(self, *, by_alias: bool = False) -> dict[str, Any]: ...
278
271
 
279
272
 
280
273
  class SaasResourceTemplateTarget_SaasSecretParameters(Protocol):
@@ -295,7 +288,7 @@ class SaasResourceTemplateTargetUpstream(Protocol):
295
288
  @property
296
289
  def instance(self) -> SaasJenkinsInstance: ...
297
290
 
298
- def dict(self, *, by_alias: bool = False) -> dict[str, Any]: ...
291
+ def model_dump(self, *, by_alias: bool = False) -> dict[str, Any]: ...
299
292
 
300
293
 
301
294
  class SaasQuayInstance(Protocol):
@@ -315,7 +308,7 @@ class SaasResourceTemplateTargetImage(Protocol):
315
308
  @property
316
309
  def org(self) -> SaasQuayOrg: ...
317
310
 
318
- def dict(self, *, by_alias: bool = False) -> dict[str, Any]: ...
311
+ def model_dump(self, *, by_alias: bool = False) -> dict[str, Any]: ...
319
312
 
320
313
 
321
314
  class SaasResourceTemplateTarget(HasParameters, HasSecretParameters, Protocol):
@@ -344,7 +337,7 @@ class SaasResourceTemplateTarget(HasParameters, HasSecretParameters, Protocol):
344
337
  self, parent_saas_file_name: str, parent_resource_template_name: str
345
338
  ) -> str: ...
346
339
 
347
- def dict(self, *, by_alias: bool = False) -> dict[str, Any]: ...
340
+ def model_dump(self, *, by_alias: bool = False) -> dict[str, Any]: ...
348
341
 
349
342
 
350
343
  class SaasResourceTemplate(HasParameters, HasSecretParameters, Protocol):
@@ -381,7 +374,7 @@ class ManagedResourceName(Protocol):
381
374
  resource: str
382
375
  resource_names: list[str]
383
376
 
384
- def dict(self) -> dict[str, str]: ...
377
+ def model_dump(self) -> dict[str, str]: ...
385
378
 
386
379
 
387
380
  class SaasFile(HasParameters, HasSecretParameters, Protocol):