qontract-reconcile 0.10.2.dev394__py3-none-any.whl → 0.10.2.dev427__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.
- {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev427.dist-info}/METADATA +5 -4
- {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev427.dist-info}/RECORD +316 -315
- reconcile/acs_rbac.py +2 -2
- reconcile/aus/advanced_upgrade_service.py +18 -12
- reconcile/aus/base.py +117 -18
- reconcile/aus/cluster_version_data.py +15 -5
- reconcile/aus/models.py +3 -1
- reconcile/aus/ocm_addons_upgrade_scheduler_org.py +1 -0
- reconcile/aus/ocm_upgrade_scheduler.py +8 -1
- reconcile/aus/ocm_upgrade_scheduler_org.py +20 -5
- reconcile/aus/version_gates/sts_version_gate_handler.py +54 -1
- reconcile/automated_actions/config/integration.py +16 -4
- reconcile/aws_account_manager/integration.py +6 -6
- reconcile/aws_account_manager/reconciler.py +3 -3
- reconcile/aws_ami_cleanup/integration.py +2 -5
- reconcile/aws_ami_share.py +69 -62
- reconcile/aws_saml_idp/integration.py +5 -3
- reconcile/aws_saml_roles/integration.py +23 -22
- reconcile/aws_version_sync/integration.py +6 -12
- reconcile/change_owners/bundle.py +3 -3
- reconcile/change_owners/change_log_tracking.py +3 -2
- reconcile/change_owners/change_owners.py +1 -1
- reconcile/cli.py +62 -4
- reconcile/dashdotdb_dora.py +1 -1
- reconcile/dashdotdb_slo.py +1 -1
- reconcile/database_access_manager.py +8 -9
- reconcile/dynatrace_token_provider/integration.py +1 -1
- reconcile/endpoints_discovery/integration.py +4 -1
- reconcile/endpoints_discovery/merge_request.py +1 -1
- reconcile/endpoints_discovery/merge_request_manager.py +1 -1
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +3 -2
- reconcile/external_resources/metrics.py +1 -1
- reconcile/external_resources/model.py +13 -13
- reconcile/external_resources/reconciler.py +7 -4
- reconcile/external_resources/secrets_sync.py +2 -2
- reconcile/external_resources/state.py +22 -13
- reconcile/fleet_labeler/integration.py +1 -1
- reconcile/gcp_image_mirror.py +2 -2
- reconcile/github_org.py +1 -1
- reconcile/github_owners.py +4 -0
- reconcile/gitlab_members.py +6 -12
- reconcile/gitlab_permissions.py +8 -12
- reconcile/glitchtip_project_alerts/integration.py +3 -1
- reconcile/gql_definitions/acs/acs_instances.py +5 -5
- reconcile/gql_definitions/acs/acs_policies.py +5 -5
- reconcile/gql_definitions/acs/acs_rbac.py +5 -5
- reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +5 -5
- reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +5 -5
- reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +5 -5
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
- reconcile/gql_definitions/automated_actions/instance.py +46 -7
- reconcile/gql_definitions/aws_account_manager/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
- reconcile/gql_definitions/aws_version_sync/clusters.py +5 -5
- reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
- reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
- reconcile/gql_definitions/change_owners/queries/self_service_roles.py +5 -5
- reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +5 -5
- reconcile/gql_definitions/common/alerting_services_settings.py +5 -5
- reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
- reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
- reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_roles.py +5 -5
- reconcile/gql_definitions/common/app_interface_state_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
- reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
- reconcile/gql_definitions/common/apps.py +5 -5
- reconcile/gql_definitions/common/aws_vpc_requests.py +5 -5
- reconcile/gql_definitions/common/aws_vpcs.py +5 -5
- reconcile/gql_definitions/common/clusters.py +5 -5
- reconcile/gql_definitions/common/clusters_minimal.py +5 -5
- reconcile/gql_definitions/common/clusters_with_dms.py +5 -5
- reconcile/gql_definitions/common/clusters_with_peering.py +5 -5
- reconcile/gql_definitions/common/github_orgs.py +5 -5
- reconcile/gql_definitions/common/jira_settings.py +5 -5
- reconcile/gql_definitions/common/jiralert_settings.py +5 -5
- reconcile/gql_definitions/common/ldap_settings.py +5 -5
- reconcile/gql_definitions/common/namespaces.py +5 -5
- reconcile/gql_definitions/common/namespaces_minimal.py +7 -5
- reconcile/gql_definitions/common/ocm_env_telemeter.py +5 -5
- reconcile/gql_definitions/common/ocm_environments.py +5 -5
- reconcile/gql_definitions/common/pagerduty_instances.py +5 -5
- reconcile/gql_definitions/common/pgp_reencryption_settings.py +5 -5
- reconcile/gql_definitions/common/pipeline_providers.py +5 -5
- reconcile/gql_definitions/common/quay_instances.py +5 -5
- reconcile/gql_definitions/common/quay_orgs.py +5 -5
- reconcile/gql_definitions/common/reserved_networks.py +5 -5
- reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
- reconcile/gql_definitions/common/saas_files.py +5 -5
- reconcile/gql_definitions/common/saas_target_namespaces.py +5 -5
- reconcile/gql_definitions/common/saasherder_settings.py +5 -5
- reconcile/gql_definitions/common/slack_workspaces.py +5 -5
- reconcile/gql_definitions/common/smtp_client_settings.py +5 -5
- reconcile/gql_definitions/common/state_aws_account.py +5 -5
- reconcile/gql_definitions/common/users.py +5 -5
- reconcile/gql_definitions/common/users_with_paths.py +5 -5
- reconcile/gql_definitions/cost_report/app_names.py +5 -5
- reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
- reconcile/gql_definitions/cost_report/settings.py +5 -5
- reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +5 -5
- reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +5 -5
- reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
- reconcile/gql_definitions/email_sender/apps.py +5 -5
- reconcile/gql_definitions/email_sender/emails.py +5 -5
- reconcile/gql_definitions/email_sender/users.py +5 -5
- reconcile/gql_definitions/endpoints_discovery/apps.py +5 -5
- reconcile/gql_definitions/external_resources/aws_accounts.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_modules.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_namespaces.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_settings.py +5 -5
- reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
- reconcile/gql_definitions/fleet_labeler/fleet_labels.py +5 -5
- reconcile/gql_definitions/fragments/aus_organization.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_common.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
- reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
- reconcile/gql_definitions/fragments/aws_organization.py +5 -5
- reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
- reconcile/gql_definitions/fragments/aws_vpc_request.py +5 -5
- reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
- reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
- reconcile/gql_definitions/fragments/disable.py +5 -5
- reconcile/gql_definitions/fragments/email_service.py +5 -5
- reconcile/gql_definitions/fragments/email_user.py +5 -5
- reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
- reconcile/gql_definitions/fragments/membership_source.py +5 -5
- reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
- reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
- reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
- reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
- reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
- reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_values.py +5 -5
- reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
- reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
- reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
- reconcile/gql_definitions/fragments/terraform_state.py +5 -5
- reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
- reconcile/gql_definitions/fragments/user.py +5 -5
- reconcile/gql_definitions/fragments/vault_secret.py +5 -5
- reconcile/gql_definitions/gcp/gcp_docker_repos.py +5 -5
- reconcile/gql_definitions/gcp/gcp_projects.py +5 -5
- reconcile/gql_definitions/gitlab_members/gitlab_instances.py +5 -5
- reconcile/gql_definitions/gitlab_members/permissions.py +5 -5
- reconcile/gql_definitions/glitchtip/glitchtip_instance.py +5 -5
- reconcile/gql_definitions/glitchtip/glitchtip_project.py +5 -5
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +5 -5
- reconcile/gql_definitions/integrations/integrations.py +5 -5
- reconcile/gql_definitions/introspection.json +231 -0
- reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +5 -5
- reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +5 -5
- reconcile/gql_definitions/jira/jira_servers.py +5 -5
- reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +5 -5
- reconcile/gql_definitions/jumphosts/jumphosts.py +5 -5
- reconcile/gql_definitions/ldap_groups/roles.py +5 -5
- reconcile/gql_definitions/ldap_groups/settings.py +5 -5
- reconcile/gql_definitions/maintenance/maintenances.py +5 -5
- reconcile/gql_definitions/membershipsources/roles.py +5 -5
- reconcile/gql_definitions/ocm_labels/clusters.py +5 -5
- reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
- reconcile/gql_definitions/openshift_cluster_bots/clusters.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_roles.py +5 -5
- reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +5 -5
- reconcile/gql_definitions/quay_membership/quay_membership.py +5 -5
- reconcile/gql_definitions/rhcs/certs.py +24 -79
- reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +42 -0
- reconcile/gql_definitions/rhidp/organizations.py +5 -5
- reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
- reconcile/gql_definitions/service_dependencies/service_dependencies.py +5 -5
- reconcile/gql_definitions/sharding/aws_accounts.py +5 -5
- reconcile/gql_definitions/sharding/ocm_organization.py +5 -5
- reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
- reconcile/gql_definitions/skupper_network/skupper_networks.py +5 -5
- reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
- reconcile/gql_definitions/slack_usergroups/permissions.py +5 -5
- reconcile/gql_definitions/slack_usergroups/users.py +5 -5
- reconcile/gql_definitions/slo_documents/slo_documents.py +5 -5
- reconcile/gql_definitions/status_board/status_board.py +5 -5
- reconcile/gql_definitions/statuspage/statuspages.py +5 -5
- reconcile/gql_definitions/templating/template_collection.py +5 -5
- reconcile/gql_definitions/templating/templates.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +5 -5
- reconcile/gql_definitions/terraform_init/aws_accounts.py +5 -5
- reconcile/gql_definitions/terraform_repo/terraform_repo.py +5 -5
- reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
- reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +5 -5
- reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +5 -5
- reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +5 -5
- reconcile/gql_definitions/vault_instances/vault_instances.py +5 -5
- reconcile/gql_definitions/vault_policies/vault_policies.py +5 -5
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +5 -5
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +5 -5
- reconcile/integrations_manager.py +3 -3
- reconcile/jenkins_worker_fleets.py +9 -8
- reconcile/jira_permissions_validator.py +2 -2
- reconcile/ldap_groups/integration.py +1 -1
- reconcile/ocm/types.py +35 -57
- reconcile/ocm_aws_infrastructure_access.py +1 -1
- reconcile/ocm_clusters.py +4 -4
- reconcile/ocm_labels/integration.py +3 -2
- reconcile/ocm_machine_pools.py +33 -27
- reconcile/openshift_base.py +113 -4
- reconcile/openshift_cluster_bots.py +1 -1
- reconcile/openshift_namespace_labels.py +1 -1
- reconcile/openshift_namespaces.py +97 -101
- reconcile/openshift_resources_base.py +6 -2
- reconcile/openshift_rhcs_certs.py +27 -29
- reconcile/openshift_rolebindings.py +7 -11
- reconcile/openshift_saas_deploy.py +4 -5
- reconcile/openshift_saas_deploy_change_tester.py +9 -7
- reconcile/openshift_serviceaccount_tokens.py +2 -2
- reconcile/openshift_upgrade_watcher.py +1 -1
- reconcile/oum/labelset.py +5 -3
- reconcile/oum/models.py +1 -4
- reconcile/prometheus_rules_tester/integration.py +3 -3
- reconcile/quay_mirror.py +1 -1
- reconcile/queries.py +6 -0
- reconcile/rhidp/common.py +3 -5
- reconcile/rhidp/sso_client/base.py +16 -5
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
- reconcile/skupper_network/integration.py +2 -2
- reconcile/slack_usergroups.py +31 -11
- reconcile/status_board.py +6 -6
- reconcile/statuspage/atlassian.py +7 -7
- reconcile/statuspage/page.py +4 -9
- reconcile/templating/lib/rendering.py +3 -3
- reconcile/templating/renderer.py +2 -2
- reconcile/terraform_cloudflare_dns.py +3 -3
- reconcile/terraform_cloudflare_resources.py +5 -5
- reconcile/terraform_cloudflare_users.py +3 -2
- reconcile/terraform_init/integration.py +2 -2
- reconcile/terraform_repo.py +16 -12
- reconcile/terraform_resources.py +6 -6
- reconcile/terraform_tgw_attachments.py +20 -18
- reconcile/terraform_vpc_resources/integration.py +3 -1
- reconcile/typed_queries/cost_report/app_names.py +1 -1
- reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
- reconcile/typed_queries/saas_files.py +11 -11
- reconcile/typed_queries/status_board.py +2 -2
- reconcile/unleash_feature_toggles/integration.py +4 -2
- reconcile/utils/acs/base.py +6 -3
- reconcile/utils/acs/policies.py +2 -2
- reconcile/utils/aws_api.py +51 -20
- reconcile/utils/aws_api_typed/organization.py +4 -2
- reconcile/utils/binary.py +7 -12
- reconcile/utils/deadmanssnitch_api.py +1 -1
- reconcile/utils/early_exit_cache.py +8 -10
- reconcile/utils/gitlab_api.py +7 -5
- reconcile/utils/glitchtip/client.py +6 -2
- reconcile/utils/glitchtip/models.py +25 -28
- reconcile/utils/gql.py +4 -7
- reconcile/utils/instrumented_wrappers.py +1 -1
- reconcile/utils/internal_groups/client.py +2 -2
- reconcile/utils/internal_groups/models.py +8 -17
- reconcile/utils/jinja2/utils.py +2 -5
- reconcile/utils/jobcontroller/controller.py +2 -2
- reconcile/utils/jobcontroller/models.py +17 -1
- reconcile/utils/json.py +43 -1
- reconcile/utils/membershipsources/app_interface_resolver.py +4 -2
- reconcile/utils/membershipsources/models.py +16 -23
- reconcile/utils/membershipsources/resolver.py +4 -2
- reconcile/utils/merge_request_manager/merge_request_manager.py +1 -1
- reconcile/utils/merge_request_manager/parser.py +4 -4
- reconcile/utils/metrics.py +5 -5
- reconcile/utils/models.py +304 -82
- reconcile/utils/mr/notificator.py +1 -1
- reconcile/utils/mr/user_maintenance.py +3 -2
- reconcile/utils/oc.py +246 -201
- reconcile/utils/ocm/addons.py +0 -1
- reconcile/utils/ocm/base.py +17 -20
- reconcile/utils/ocm/cluster_groups.py +1 -1
- reconcile/utils/ocm/identity_providers.py +2 -2
- reconcile/utils/ocm/labels.py +1 -1
- reconcile/utils/ocm/products.py +8 -8
- reconcile/utils/ocm/service_log.py +1 -1
- reconcile/utils/ocm/sre_capability_labels.py +20 -13
- reconcile/utils/openshift_resource.py +5 -0
- reconcile/utils/pagerduty_api.py +5 -2
- reconcile/utils/promotion_state.py +6 -11
- reconcile/utils/raw_github_api.py +1 -1
- reconcile/utils/rhcsv2_certs.py +1 -4
- reconcile/utils/rosa/session.py +16 -0
- reconcile/utils/runtime/integration.py +1 -1
- reconcile/utils/saasherder/interfaces.py +13 -20
- reconcile/utils/saasherder/models.py +23 -20
- reconcile/utils/saasherder/saasherder.py +46 -24
- reconcile/utils/slack_api.py +2 -2
- reconcile/utils/structs.py +1 -1
- reconcile/utils/terraform_client.py +1 -1
- reconcile/utils/terrascript_aws_client.py +47 -43
- reconcile/utils/unleash/server.py +2 -8
- reconcile/utils/vault.py +5 -12
- reconcile/utils/vcs.py +8 -8
- reconcile/vault_replication.py +1 -1
- tools/cli_commands/cost_report/cost_management_api.py +3 -3
- tools/cli_commands/cost_report/view.py +7 -6
- tools/cli_commands/erv2.py +1 -1
- tools/qontract_cli.py +6 -5
- tools/template_validation.py +3 -1
- {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev427.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev427.dist-info}/entry_points.txt +0 -0
|
@@ -92,8 +92,7 @@ from reconcile.utils.state import State
|
|
|
92
92
|
from reconcile.utils.vcs import VCS
|
|
93
93
|
|
|
94
94
|
TARGET_CONFIG_HASH = "target_config_hash"
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
TEMPLATE_API_VERSION = "template.openshift.io/v1"
|
|
97
96
|
UNIQUE_SAAS_FILE_ENV_COMBO_LEN = 56
|
|
98
97
|
REQUEST_TIMEOUT = 60
|
|
99
98
|
|
|
@@ -765,7 +764,8 @@ class SaasHerder:
|
|
|
765
764
|
case "gitlab":
|
|
766
765
|
if not self.gitlab:
|
|
767
766
|
raise Exception("gitlab is not initialized")
|
|
768
|
-
project
|
|
767
|
+
if not (project := self.gitlab.get_project(url)):
|
|
768
|
+
raise Exception(f"Could not find gitlab project for {url}")
|
|
769
769
|
content = self.gitlab.get_raw_file(
|
|
770
770
|
project=project,
|
|
771
771
|
path=path,
|
|
@@ -801,7 +801,8 @@ class SaasHerder:
|
|
|
801
801
|
case "gitlab":
|
|
802
802
|
if not self.gitlab:
|
|
803
803
|
raise Exception("gitlab is not initialized")
|
|
804
|
-
project
|
|
804
|
+
if not (project := self.gitlab.get_project(url)):
|
|
805
|
+
raise Exception(f"Could not find gitlab project for {url}")
|
|
805
806
|
dir_contents = self.gitlab.get_directory_contents(
|
|
806
807
|
project,
|
|
807
808
|
ref=commit_sha,
|
|
@@ -826,7 +827,8 @@ class SaasHerder:
|
|
|
826
827
|
case "gitlab":
|
|
827
828
|
if not self.gitlab:
|
|
828
829
|
raise Exception("gitlab is not initialized")
|
|
829
|
-
project
|
|
830
|
+
if not (project := self.gitlab.get_project(url)):
|
|
831
|
+
raise Exception(f"Could not find gitlab project for {url}")
|
|
830
832
|
commits = project.commits.list(ref_name=ref, per_page=1, page=1)
|
|
831
833
|
return commits[0].id
|
|
832
834
|
case _:
|
|
@@ -871,10 +873,23 @@ class SaasHerder:
|
|
|
871
873
|
"""
|
|
872
874
|
if parameter_name in consolidated_parameters:
|
|
873
875
|
return False
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
876
|
+
return any(
|
|
877
|
+
template_parameter["name"] == parameter_name
|
|
878
|
+
for template_parameter in template.get("parameters") or []
|
|
879
|
+
)
|
|
880
|
+
|
|
881
|
+
@staticmethod
|
|
882
|
+
def _pre_process_template(template: dict[str, Any]) -> dict[str, Any]:
|
|
883
|
+
"""
|
|
884
|
+
The only supported apiVersion for OpenShift Template is "template.openshift.io/v1".
|
|
885
|
+
There are examples of templates using "v1", it can't pass validation on 4.19+ oc versions.
|
|
886
|
+
|
|
887
|
+
Args:
|
|
888
|
+
template (dict): The OpenShift template dictionary.
|
|
889
|
+
Returns:
|
|
890
|
+
dict: The OpenShift template dictionary with the correct apiVersion.
|
|
891
|
+
"""
|
|
892
|
+
return template | {"apiVersion": TEMPLATE_API_VERSION}
|
|
878
893
|
|
|
879
894
|
def _process_template(
|
|
880
895
|
self, spec: TargetSpec
|
|
@@ -964,7 +979,8 @@ class SaasHerder:
|
|
|
964
979
|
oc = OCLocal("cluster", None, None, local=True)
|
|
965
980
|
try:
|
|
966
981
|
resources: Iterable[Mapping[str, Any]] = oc.process(
|
|
967
|
-
template,
|
|
982
|
+
template=self._pre_process_template(template),
|
|
983
|
+
parameters=consolidated_parameters,
|
|
968
984
|
)
|
|
969
985
|
except StatusCodeError as e:
|
|
970
986
|
logging.error(f"{error_prefix} error processing template: {e!s}")
|
|
@@ -1179,13 +1195,13 @@ class SaasHerder:
|
|
|
1179
1195
|
images_list = threaded.run(
|
|
1180
1196
|
self._collect_images, resources, self.available_thread_pool_size
|
|
1181
1197
|
)
|
|
1182
|
-
|
|
1183
|
-
self.images.update(
|
|
1184
|
-
if not
|
|
1198
|
+
images_set = set(itertools.chain.from_iterable(images_list))
|
|
1199
|
+
self.images.update(images_set)
|
|
1200
|
+
if not images_set:
|
|
1185
1201
|
return False # no errors
|
|
1186
1202
|
images = threaded.run(
|
|
1187
1203
|
self._get_image,
|
|
1188
|
-
|
|
1204
|
+
images_set,
|
|
1189
1205
|
self.available_thread_pool_size,
|
|
1190
1206
|
image_patterns=spec.image_patterns,
|
|
1191
1207
|
image_auth=spec.image_auth,
|
|
@@ -1250,7 +1266,9 @@ class SaasHerder:
|
|
|
1250
1266
|
self.saas_files,
|
|
1251
1267
|
self.thread_pool_size,
|
|
1252
1268
|
)
|
|
1253
|
-
desired_state_specs = list(
|
|
1269
|
+
desired_state_specs: list[TargetSpec] = list(
|
|
1270
|
+
itertools.chain.from_iterable(results)
|
|
1271
|
+
)
|
|
1254
1272
|
promotions = threaded.run(
|
|
1255
1273
|
self.populate_desired_state_saas_file,
|
|
1256
1274
|
desired_state_specs,
|
|
@@ -1898,21 +1916,23 @@ class SaasHerder:
|
|
|
1898
1916
|
name=target.name,
|
|
1899
1917
|
ref=target.ref,
|
|
1900
1918
|
promotion=(
|
|
1901
|
-
target.promotion.
|
|
1919
|
+
target.promotion.model_dump(by_alias=True) if target.promotion else None
|
|
1902
1920
|
),
|
|
1903
1921
|
secretParameters=(
|
|
1904
|
-
[p.
|
|
1922
|
+
[p.model_dump(by_alias=True) for p in target.secret_parameters]
|
|
1905
1923
|
if target.secret_parameters
|
|
1906
1924
|
else None
|
|
1907
1925
|
),
|
|
1908
1926
|
slos=(
|
|
1909
|
-
[slo.
|
|
1927
|
+
[slo.model_dump(by_alias=True) for slo in target.slos]
|
|
1910
1928
|
if target.slos
|
|
1911
1929
|
else None
|
|
1912
1930
|
),
|
|
1913
|
-
upstream=(
|
|
1931
|
+
upstream=(
|
|
1932
|
+
target.upstream.model_dump(by_alias=True) if target.upstream else None
|
|
1933
|
+
),
|
|
1914
1934
|
images=(
|
|
1915
|
-
[i.
|
|
1935
|
+
[i.model_dump(by_alias=True) for i in target.images]
|
|
1916
1936
|
if target.images
|
|
1917
1937
|
else None
|
|
1918
1938
|
),
|
|
@@ -1948,16 +1968,16 @@ class SaasHerder:
|
|
|
1948
1968
|
)
|
|
1949
1969
|
if saas_file.managed_resource_names:
|
|
1950
1970
|
state_content["saas_file_managed_resource_names"] = [
|
|
1951
|
-
m.
|
|
1971
|
+
m.model_dump() for m in saas_file.managed_resource_names
|
|
1952
1972
|
]
|
|
1953
1973
|
# include secret parameters from resource template and saas file
|
|
1954
1974
|
if resource_template.secret_parameters:
|
|
1955
1975
|
state_content["rt_secretparameters"] = [
|
|
1956
|
-
p.
|
|
1976
|
+
p.model_dump() for p in resource_template.secret_parameters
|
|
1957
1977
|
]
|
|
1958
1978
|
if saas_file.secret_parameters:
|
|
1959
1979
|
state_content["saas_file_secretparameters"] = [
|
|
1960
|
-
p.
|
|
1980
|
+
p.model_dump() for p in saas_file.secret_parameters
|
|
1961
1981
|
]
|
|
1962
1982
|
return state_content
|
|
1963
1983
|
|
|
@@ -2240,7 +2260,9 @@ class SaasHerder:
|
|
|
2240
2260
|
for rt in saas_file.resource_templates:
|
|
2241
2261
|
for target in rt.targets:
|
|
2242
2262
|
template_vars = {
|
|
2243
|
-
"resource": {
|
|
2263
|
+
"resource": {
|
|
2264
|
+
"namespace": target.namespace.model_dump(by_alias=True)
|
|
2265
|
+
}
|
|
2244
2266
|
}
|
|
2245
2267
|
if target.parameters:
|
|
2246
2268
|
for param in target.parameters:
|
reconcile/utils/slack_api.py
CHANGED
|
@@ -71,14 +71,14 @@ class HasClientGlobalConfig(Protocol):
|
|
|
71
71
|
max_retries: int | None
|
|
72
72
|
timeout: int | None
|
|
73
73
|
|
|
74
|
-
def
|
|
74
|
+
def model_dump(self) -> dict[str, int | None]: ...
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
class HasClientMethodConfig(Protocol):
|
|
78
78
|
name: str
|
|
79
79
|
args: Any
|
|
80
80
|
|
|
81
|
-
def
|
|
81
|
+
def model_dump(self) -> dict[str, str]: ...
|
|
82
82
|
|
|
83
83
|
|
|
84
84
|
class HasClientConfig(Protocol):
|
reconcile/utils/structs.py
CHANGED
|
@@ -223,7 +223,7 @@ class TerraformClient:
|
|
|
223
223
|
if disable_deletions_detected:
|
|
224
224
|
raise RuntimeError("Terraform plan has disabled deletions detected")
|
|
225
225
|
|
|
226
|
-
@retry(no_retry_exceptions=RdsUpgradeValidationError)
|
|
226
|
+
@retry(no_retry_exceptions=(RdsUpgradeValidationError,))
|
|
227
227
|
def terraform_plan(
|
|
228
228
|
self, spec: TerraformSpec, enable_deletion: bool
|
|
229
229
|
) -> tuple[bool, list[AccountUser], bool]:
|
|
@@ -1058,7 +1058,9 @@ class TerrascriptClient:
|
|
|
1058
1058
|
ignore_changes = (
|
|
1059
1059
|
"all" if "all" in lifecycle.ignore_changes else lifecycle.ignore_changes
|
|
1060
1060
|
)
|
|
1061
|
-
return lifecycle.
|
|
1061
|
+
return lifecycle.model_dump(by_alias=True) | {
|
|
1062
|
+
"ignore_changes": ignore_changes
|
|
1063
|
+
}
|
|
1062
1064
|
return None
|
|
1063
1065
|
|
|
1064
1066
|
def populate_additional_providers(
|
|
@@ -1424,7 +1426,7 @@ class TerrascriptClient:
|
|
|
1424
1426
|
req_account_name = req_account.name
|
|
1425
1427
|
# Accepter's side of the connection - the cluster's account
|
|
1426
1428
|
acc_account = accepter.account
|
|
1427
|
-
acc_alias = self.get_provider_alias(acc_account.
|
|
1429
|
+
acc_alias = self.get_provider_alias(acc_account.model_dump(by_alias=True))
|
|
1428
1430
|
acc_uid = acc_account.uid
|
|
1429
1431
|
if acc_account.assume_role:
|
|
1430
1432
|
acc_uid = awsh.get_account_uid_from_arn(acc_account.assume_role)
|
|
@@ -2210,6 +2212,43 @@ class TerrascriptClient:
|
|
|
2210
2212
|
letters_and_digits = string.ascii_letters + string.digits
|
|
2211
2213
|
return "".join(random.choice(letters_and_digits) for i in range(string_length))
|
|
2212
2214
|
|
|
2215
|
+
@staticmethod
|
|
2216
|
+
def _build_tf_resource_s3_lifecycle_rules(
|
|
2217
|
+
versioning: bool,
|
|
2218
|
+
common_values: Mapping[str, Any],
|
|
2219
|
+
) -> list[dict]:
|
|
2220
|
+
lifecycle_rules = common_values.get("lifecycle_rules") or []
|
|
2221
|
+
if versioning and not any(
|
|
2222
|
+
"noncurrent_version_expiration" in lr for lr in lifecycle_rules
|
|
2223
|
+
):
|
|
2224
|
+
# Add a default noncurrent object expiration rule
|
|
2225
|
+
# if one isn't already set
|
|
2226
|
+
rule = {
|
|
2227
|
+
"id": "expire_noncurrent_versions",
|
|
2228
|
+
"enabled": True,
|
|
2229
|
+
"noncurrent_version_expiration": {"days": 30},
|
|
2230
|
+
"expiration": {"expired_object_delete_marker": True},
|
|
2231
|
+
"abort_incomplete_multipart_upload_days": 3,
|
|
2232
|
+
}
|
|
2233
|
+
lifecycle_rules.append(rule)
|
|
2234
|
+
|
|
2235
|
+
if storage_class := common_values.get("storage_class"):
|
|
2236
|
+
sc = storage_class.upper()
|
|
2237
|
+
days = "1"
|
|
2238
|
+
if sc.endswith("_IA"):
|
|
2239
|
+
# Infrequent Access storage class has minimum 30 days
|
|
2240
|
+
# before transition
|
|
2241
|
+
days = "30"
|
|
2242
|
+
rule = {
|
|
2243
|
+
"id": sc + "_storage_class",
|
|
2244
|
+
"enabled": True,
|
|
2245
|
+
"transition": {"days": days, "storage_class": sc},
|
|
2246
|
+
"noncurrent_version_transition": {"days": days, "storage_class": sc},
|
|
2247
|
+
}
|
|
2248
|
+
lifecycle_rules.append(rule)
|
|
2249
|
+
|
|
2250
|
+
return lifecycle_rules
|
|
2251
|
+
|
|
2213
2252
|
def populate_tf_resource_s3(self, spec: ExternalResourceSpec) -> aws_s3_bucket:
|
|
2214
2253
|
account = spec.provisioner_name
|
|
2215
2254
|
identifier = spec.identifier
|
|
@@ -2249,47 +2288,11 @@ class TerrascriptClient:
|
|
|
2249
2288
|
request_payer = common_values.get("request_payer")
|
|
2250
2289
|
if request_payer:
|
|
2251
2290
|
values["request_payer"] = request_payer
|
|
2252
|
-
lifecycle_rules
|
|
2253
|
-
|
|
2254
|
-
|
|
2291
|
+
if lifecycle_rules := self._build_tf_resource_s3_lifecycle_rules(
|
|
2292
|
+
versioning=versioning,
|
|
2293
|
+
common_values=common_values,
|
|
2294
|
+
):
|
|
2255
2295
|
values["lifecycle_rule"] = lifecycle_rules
|
|
2256
|
-
if versioning:
|
|
2257
|
-
lrs = values.get("lifecycle_rule", [])
|
|
2258
|
-
expiration_rule = False
|
|
2259
|
-
for lr in lrs:
|
|
2260
|
-
if "noncurrent_version_expiration" in lr:
|
|
2261
|
-
expiration_rule = True
|
|
2262
|
-
break
|
|
2263
|
-
if not expiration_rule:
|
|
2264
|
-
# Add a default noncurrent object expiration rule if
|
|
2265
|
-
# if one isn't already set
|
|
2266
|
-
rule = {
|
|
2267
|
-
"id": "expire_noncurrent_versions",
|
|
2268
|
-
"enabled": "true",
|
|
2269
|
-
"noncurrent_version_expiration": {"days": 30},
|
|
2270
|
-
}
|
|
2271
|
-
if len(lrs) > 0:
|
|
2272
|
-
lrs.append(rule)
|
|
2273
|
-
else:
|
|
2274
|
-
lrs = rule
|
|
2275
|
-
sc = common_values.get("storage_class")
|
|
2276
|
-
if sc:
|
|
2277
|
-
sc = sc.upper()
|
|
2278
|
-
days = "1"
|
|
2279
|
-
if sc.endswith("_IA"):
|
|
2280
|
-
# Infrequent Access storage class has minimum 30 days
|
|
2281
|
-
# before transition
|
|
2282
|
-
days = "30"
|
|
2283
|
-
rule = {
|
|
2284
|
-
"id": sc + "_storage_class",
|
|
2285
|
-
"enabled": "true",
|
|
2286
|
-
"transition": {"days": days, "storage_class": sc},
|
|
2287
|
-
"noncurrent_version_transition": {"days": days, "storage_class": sc},
|
|
2288
|
-
}
|
|
2289
|
-
if values.get("lifecycle_rule"):
|
|
2290
|
-
values["lifecycle_rule"].append(rule)
|
|
2291
|
-
else:
|
|
2292
|
-
values["lifecycle_rule"] = rule
|
|
2293
2296
|
cors_rules = common_values.get("cors_rules")
|
|
2294
2297
|
if cors_rules:
|
|
2295
2298
|
# common_values['cors_rules'] is a list of cors_rules
|
|
@@ -5907,7 +5910,8 @@ class TerrascriptClient:
|
|
|
5907
5910
|
return commit.sha
|
|
5908
5911
|
case "gitlab":
|
|
5909
5912
|
gitlab = self.init_gitlab()
|
|
5910
|
-
project
|
|
5913
|
+
if not (project := gitlab.get_project(url)):
|
|
5914
|
+
raise ValueError(f"could not find gitlab project for url {url}")
|
|
5911
5915
|
commits = project.commits.list(ref_name=ref, per_page=1, page=1)
|
|
5912
5916
|
return commits[0].id
|
|
5913
5917
|
case _:
|
|
@@ -24,30 +24,24 @@ class Environment(BaseModel):
|
|
|
24
24
|
return self.name == other
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
class FeatureToggle(BaseModel):
|
|
27
|
+
class FeatureToggle(BaseModel, validate_by_name=True, validate_by_alias=True):
|
|
28
28
|
name: str
|
|
29
29
|
type: FeatureToggleType = FeatureToggleType.release
|
|
30
30
|
description: str | None = None
|
|
31
31
|
impression_data: bool = Field(False, alias="impressionData")
|
|
32
32
|
environments: list[Environment]
|
|
33
33
|
|
|
34
|
-
class Config:
|
|
35
|
-
allow_population_by_field_name = True
|
|
36
|
-
|
|
37
34
|
def __eq__(self, other: object) -> bool:
|
|
38
35
|
if isinstance(other, FeatureToggle):
|
|
39
36
|
return self.name == other.name
|
|
40
37
|
return self.name == other
|
|
41
38
|
|
|
42
39
|
|
|
43
|
-
class Project(BaseModel):
|
|
40
|
+
class Project(BaseModel, validate_by_name=True, validate_by_alias=True):
|
|
44
41
|
pk: str = Field(alias="id")
|
|
45
42
|
name: str
|
|
46
43
|
feature_toggles: list[FeatureToggle] = []
|
|
47
44
|
|
|
48
|
-
class Config:
|
|
49
|
-
allow_population_by_field_name = True
|
|
50
|
-
|
|
51
45
|
|
|
52
46
|
class TokenAuth(BearerTokenAuth):
|
|
53
47
|
def __call__(self, r: requests.PreparedRequest) -> requests.PreparedRequest:
|
reconcile/utils/vault.py
CHANGED
|
@@ -6,7 +6,7 @@ import threading
|
|
|
6
6
|
import time
|
|
7
7
|
from collections.abc import Mapping
|
|
8
8
|
from functools import lru_cache
|
|
9
|
-
from typing import Any, Self
|
|
9
|
+
from typing import Any, Self
|
|
10
10
|
|
|
11
11
|
import hvac
|
|
12
12
|
import requests
|
|
@@ -48,13 +48,6 @@ class VaultConnectionError(Exception):
|
|
|
48
48
|
pass
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
class Secret(TypedDict):
|
|
52
|
-
path: str
|
|
53
|
-
field: str
|
|
54
|
-
format: str | None
|
|
55
|
-
version: str | None
|
|
56
|
-
|
|
57
|
-
|
|
58
51
|
SECRET_VERSION_LATEST = "LATEST"
|
|
59
52
|
|
|
60
53
|
|
|
@@ -197,7 +190,7 @@ class VaultClient:
|
|
|
197
190
|
self._client.auth_approle(self.role_id, self.secret_id)
|
|
198
191
|
|
|
199
192
|
@retry()
|
|
200
|
-
def read_all_with_version(self, secret: Mapping) -> tuple[
|
|
193
|
+
def read_all_with_version(self, secret: Mapping) -> tuple[dict, int | None]:
|
|
201
194
|
"""Returns a dictionary of keys and values in a Vault secret and the
|
|
202
195
|
version of the secret, for V1 secrets, version will be None.
|
|
203
196
|
|
|
@@ -207,7 +200,7 @@ class VaultClient:
|
|
|
207
200
|
a v2 KV engine)
|
|
208
201
|
"""
|
|
209
202
|
secret_path = secret["path"]
|
|
210
|
-
secret_version = secret.get("version"
|
|
203
|
+
secret_version = secret.get("version") or SECRET_VERSION_LATEST
|
|
211
204
|
|
|
212
205
|
kv_version = self._get_mount_version_by_secret_path(secret_path)
|
|
213
206
|
|
|
@@ -250,7 +243,7 @@ class VaultClient:
|
|
|
250
243
|
|
|
251
244
|
def __read_all_v2(
|
|
252
245
|
self, path: str, version: str | None
|
|
253
|
-
) -> tuple[dict[str, Any],
|
|
246
|
+
) -> tuple[dict[str, Any], int]:
|
|
254
247
|
path_split = path.split("/")
|
|
255
248
|
mount_point = path_split[0]
|
|
256
249
|
read_path = "/".join(path_split[1:])
|
|
@@ -294,7 +287,7 @@ class VaultClient:
|
|
|
294
287
|
return secret["data"]
|
|
295
288
|
|
|
296
289
|
@retry()
|
|
297
|
-
def read(self, secret:
|
|
290
|
+
def read(self, secret: Mapping[str, Any]) -> Any:
|
|
298
291
|
"""Returns a value of a key in a Vault secret.
|
|
299
292
|
|
|
300
293
|
The input secret is a dictionary which contains the following fields:
|
reconcile/utils/vcs.py
CHANGED
|
@@ -140,7 +140,7 @@ class VCS:
|
|
|
140
140
|
gitlab_instances: Iterable[GitlabInstanceV1],
|
|
141
141
|
) -> GitLabApi:
|
|
142
142
|
return GitLabApi(
|
|
143
|
-
next(iter(gitlab_instances)).
|
|
143
|
+
next(iter(gitlab_instances)).model_dump(by_alias=True),
|
|
144
144
|
secret_reader=self._secret_reader,
|
|
145
145
|
)
|
|
146
146
|
|
|
@@ -150,7 +150,7 @@ class VCS:
|
|
|
150
150
|
app_interface_repo_url: str,
|
|
151
151
|
) -> GitLabApi:
|
|
152
152
|
return GitLabApi(
|
|
153
|
-
next(iter(gitlab_instances)).
|
|
153
|
+
next(iter(gitlab_instances)).model_dump(by_alias=True),
|
|
154
154
|
secret_reader=self._secret_reader,
|
|
155
155
|
project_url=app_interface_repo_url,
|
|
156
156
|
)
|
|
@@ -221,26 +221,26 @@ class VCS:
|
|
|
221
221
|
match repo_info.platform:
|
|
222
222
|
case "github":
|
|
223
223
|
github = self._init_github(repo_url=repo_url, auth_code=auth_code)
|
|
224
|
-
data = github.compare(commit_from=commit_from, commit_to=commit_to)
|
|
225
224
|
return [
|
|
226
225
|
Commit(
|
|
227
226
|
repo=repo_url,
|
|
228
227
|
sha=gh_commit.sha,
|
|
229
228
|
date=gh_commit.commit.committer.date,
|
|
230
229
|
)
|
|
231
|
-
for gh_commit in
|
|
230
|
+
for gh_commit in github.compare(
|
|
231
|
+
commit_from=commit_from, commit_to=commit_to
|
|
232
|
+
)
|
|
232
233
|
]
|
|
233
234
|
case "gitlab":
|
|
234
|
-
data = self._gitlab_instance.repository_compare(
|
|
235
|
-
repo_url=repo_url, ref_from=commit_from, ref_to=commit_to
|
|
236
|
-
)
|
|
237
235
|
return [
|
|
238
236
|
Commit(
|
|
239
237
|
repo=repo_url,
|
|
240
238
|
sha=gl_commit["id"],
|
|
241
239
|
date=datetime.fromisoformat(gl_commit["committed_date"]),
|
|
242
240
|
)
|
|
243
|
-
for gl_commit in
|
|
241
|
+
for gl_commit in self._gitlab_instance.repository_compare(
|
|
242
|
+
repo_url=repo_url, ref_from=commit_from, ref_to=commit_to
|
|
243
|
+
)
|
|
244
244
|
]
|
|
245
245
|
case _:
|
|
246
246
|
raise ValueError(f"Unsupported repository URL: {repo_url}")
|
reconcile/vault_replication.py
CHANGED
|
@@ -217,7 +217,7 @@ def copy_vault_secret(
|
|
|
217
217
|
return
|
|
218
218
|
|
|
219
219
|
# If we reach here, we successfully read the destination secret
|
|
220
|
-
if dest_version is None
|
|
220
|
+
if dest_version is None or version is None:
|
|
221
221
|
# v1 secrets don't have version
|
|
222
222
|
if source_data == dest_data:
|
|
223
223
|
# If the secret is the same in both vaults, we don't need
|
|
@@ -74,7 +74,7 @@ class CostManagementApi(ApiBase):
|
|
|
74
74
|
timeout=self.read_timeout,
|
|
75
75
|
)
|
|
76
76
|
response.raise_for_status()
|
|
77
|
-
return AwsReportCostResponse.
|
|
77
|
+
return AwsReportCostResponse.model_validate(response.json())
|
|
78
78
|
|
|
79
79
|
def get_openshift_costs_report(
|
|
80
80
|
self,
|
|
@@ -97,7 +97,7 @@ class CostManagementApi(ApiBase):
|
|
|
97
97
|
timeout=self.read_timeout,
|
|
98
98
|
)
|
|
99
99
|
response.raise_for_status()
|
|
100
|
-
return OpenShiftReportCostResponse.
|
|
100
|
+
return OpenShiftReportCostResponse.model_validate(response.json())
|
|
101
101
|
|
|
102
102
|
def get_openshift_cost_optimization_report(
|
|
103
103
|
self,
|
|
@@ -120,7 +120,7 @@ class CostManagementApi(ApiBase):
|
|
|
120
120
|
response.raise_for_status()
|
|
121
121
|
|
|
122
122
|
data = self._get_paginated(response)
|
|
123
|
-
return OpenShiftCostOptimizationReportResponse.
|
|
123
|
+
return OpenShiftCostOptimizationReportResponse.model_validate(data)
|
|
124
124
|
|
|
125
125
|
def _get_paginated(
|
|
126
126
|
self,
|
|
@@ -4,6 +4,7 @@ from typing import Any
|
|
|
4
4
|
|
|
5
5
|
from pydantic import BaseModel
|
|
6
6
|
|
|
7
|
+
from reconcile.utils.json import json_dumps
|
|
7
8
|
from tools.cli_commands.cost_report.model import OptimizationReport, Report
|
|
8
9
|
|
|
9
10
|
LAYOUT = """\
|
|
@@ -244,7 +245,7 @@ def render_summary(
|
|
|
244
245
|
return template.format(
|
|
245
246
|
date=get_date(reports),
|
|
246
247
|
total_cost=format_cost_value(total_cost),
|
|
247
|
-
json_table=json_table
|
|
248
|
+
json_table=json_dumps(json_table, indent=2, mode="python"),
|
|
248
249
|
)
|
|
249
250
|
|
|
250
251
|
|
|
@@ -274,7 +275,7 @@ def render_month_over_month_change(reports: Mapping[str, Report]) -> str:
|
|
|
274
275
|
)
|
|
275
276
|
return MONTH_OVER_MONTH_CHANGE.format(
|
|
276
277
|
date=get_date(reports),
|
|
277
|
-
json_table=json_table
|
|
278
|
+
json_table=json_dumps(json_table, indent=2, mode="python"),
|
|
278
279
|
)
|
|
279
280
|
|
|
280
281
|
|
|
@@ -304,7 +305,7 @@ def render_aws_services_cost(
|
|
|
304
305
|
items_total=format_cost_value(report.items_total),
|
|
305
306
|
items_delta_value=format_delta_value(report.items_delta_value),
|
|
306
307
|
items_delta_percent=format_delta_percent(report.items_delta_percent),
|
|
307
|
-
json_table=json_table
|
|
308
|
+
json_table=json_dumps(json_table, indent=2, mode="python"),
|
|
308
309
|
)
|
|
309
310
|
|
|
310
311
|
|
|
@@ -316,7 +317,7 @@ def render_openshift_workloads_cost(
|
|
|
316
317
|
items_total=format_cost_value(report.items_total),
|
|
317
318
|
items_delta_value=format_delta_value(report.items_delta_value),
|
|
318
319
|
items_delta_percent=format_delta_percent(report.items_delta_percent),
|
|
319
|
-
json_table=json_table
|
|
320
|
+
json_table=json_dumps(json_table, indent=2, mode="python"),
|
|
320
321
|
)
|
|
321
322
|
|
|
322
323
|
|
|
@@ -362,7 +363,7 @@ def render_child_apps_cost(report: Report) -> str:
|
|
|
362
363
|
)
|
|
363
364
|
return CHILD_APPS_COST.format(
|
|
364
365
|
child_apps_total=format_cost_value(report.child_apps_total),
|
|
365
|
-
json_table=json_table
|
|
366
|
+
json_table=json_dumps(json_table, indent=2, mode="python"),
|
|
366
367
|
)
|
|
367
368
|
|
|
368
369
|
|
|
@@ -509,7 +510,7 @@ def render_optimization(
|
|
|
509
510
|
)
|
|
510
511
|
return OPTIMIZATION.format(
|
|
511
512
|
app_name=report.app_name,
|
|
512
|
-
json_table=json_table
|
|
513
|
+
json_table=json_dumps(json_table, indent=2, mode="python"),
|
|
513
514
|
)
|
|
514
515
|
|
|
515
516
|
|
tools/cli_commands/erv2.py
CHANGED
|
@@ -133,7 +133,7 @@ class Erv2Cli:
|
|
|
133
133
|
|
|
134
134
|
@property
|
|
135
135
|
def input_data(self) -> str:
|
|
136
|
-
return self._resource.
|
|
136
|
+
return self._resource.export(exclude={"data": {FLAG_RESOURCE_MANAGED_BY_ERV2}})
|
|
137
137
|
|
|
138
138
|
@property
|
|
139
139
|
def image(self) -> str:
|
tools/qontract_cli.py
CHANGED
|
@@ -141,6 +141,7 @@ from reconcile.utils.gitlab_api import (
|
|
|
141
141
|
)
|
|
142
142
|
from reconcile.utils.glitchtip.client import GlitchtipClient
|
|
143
143
|
from reconcile.utils.gql import GqlApiSingleton
|
|
144
|
+
from reconcile.utils.json import json_dumps
|
|
144
145
|
from reconcile.utils.keycloak import (
|
|
145
146
|
KeycloakAPI,
|
|
146
147
|
SSOClient,
|
|
@@ -1566,7 +1567,7 @@ def rosa_create_cluster_command(ctx: click.Context, cluster_name: str) -> None:
|
|
|
1566
1567
|
billing_account = account.billing_account.uid
|
|
1567
1568
|
else:
|
|
1568
1569
|
with AWSApi(
|
|
1569
|
-
1, [account.
|
|
1570
|
+
1, [account.model_dump(by_alias=True)], settings=settings, init_users=False
|
|
1570
1571
|
) as aws_api:
|
|
1571
1572
|
billing_account = aws_api.get_organization_billing_account(account.name)
|
|
1572
1573
|
|
|
@@ -1750,7 +1751,7 @@ def aws_terraform_resources(ctx: click.Context) -> None:
|
|
|
1750
1751
|
for ns_info in namespaces:
|
|
1751
1752
|
specs = (
|
|
1752
1753
|
get_external_resource_specs(
|
|
1753
|
-
ns_info.
|
|
1754
|
+
ns_info.model_dump(by_alias=True), provision_provider=PROVIDER_AWS
|
|
1754
1755
|
)
|
|
1755
1756
|
or []
|
|
1756
1757
|
)
|
|
@@ -1808,7 +1809,7 @@ def rds(ctx: click.Context) -> None:
|
|
|
1808
1809
|
specs = [
|
|
1809
1810
|
s
|
|
1810
1811
|
for s in get_external_resource_specs(
|
|
1811
|
-
namespace.
|
|
1812
|
+
namespace.model_dump(by_alias=True), provision_provider=PROVIDER_AWS
|
|
1812
1813
|
)
|
|
1813
1814
|
if s.provider == "rds"
|
|
1814
1815
|
]
|
|
@@ -2961,7 +2962,7 @@ def maintenances(ctx: click.Context) -> None:
|
|
|
2961
2962
|
maintenances = maintenances_gql.query(gql.get_api().query).maintenances or []
|
|
2962
2963
|
data = [
|
|
2963
2964
|
{
|
|
2964
|
-
**m.
|
|
2965
|
+
**m.model_dump(),
|
|
2965
2966
|
"services": ", ".join(a.name for a in m.affected_services),
|
|
2966
2967
|
}
|
|
2967
2968
|
for m in maintenances
|
|
@@ -4298,7 +4299,7 @@ def create(
|
|
|
4298
4299
|
bg="red",
|
|
4299
4300
|
fg="white",
|
|
4300
4301
|
)
|
|
4301
|
-
print(sso_client
|
|
4302
|
+
print(json_dumps(sso_client, indent=2))
|
|
4302
4303
|
|
|
4303
4304
|
|
|
4304
4305
|
@sso_client.command()
|
tools/template_validation.py
CHANGED
|
@@ -67,7 +67,9 @@ def main(templates: tuple[str]) -> None:
|
|
|
67
67
|
tests.append(test_yaml)
|
|
68
68
|
|
|
69
69
|
template_raw["templateTest"] = tests
|
|
70
|
-
|
|
70
|
+
data = data_default_none(TemplateV1, template_raw)
|
|
71
|
+
assert isinstance(data, dict)
|
|
72
|
+
template: TemplateV1 = TemplateV1(**data)
|
|
71
73
|
|
|
72
74
|
# templates_to_validate = {}
|
|
73
75
|
for test in template.template_test:
|
{qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev427.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|