qontract-reconcile 0.10.2.dev349__py3-none-any.whl → 0.10.2.dev414__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.dev349.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/METADATA +12 -11
- {qontract_reconcile-0.10.2.dev349.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/RECORD +356 -350
- reconcile/acs_rbac.py +2 -2
- reconcile/aus/advanced_upgrade_service.py +15 -12
- reconcile/aus/base.py +26 -27
- reconcile/aus/cluster_version_data.py +15 -5
- reconcile/aus/models.py +1 -1
- reconcile/automated_actions/config/integration.py +15 -3
- reconcile/aws_account_manager/integration.py +8 -8
- reconcile/aws_account_manager/reconciler.py +3 -3
- reconcile/aws_ami_cleanup/integration.py +8 -12
- reconcile/aws_ami_share.py +69 -62
- reconcile/aws_cloudwatch_log_retention/integration.py +155 -126
- reconcile/aws_ecr_image_pull_secrets.py +2 -2
- reconcile/aws_iam_keys.py +7 -41
- reconcile/aws_saml_idp/integration.py +12 -4
- reconcile/aws_saml_roles/integration.py +32 -25
- 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/change_owners/diff.py +2 -4
- reconcile/checkpoint.py +11 -3
- reconcile/cli.py +33 -8
- reconcile/dashdotdb_dora.py +5 -12
- reconcile/dashdotdb_slo.py +1 -1
- reconcile/database_access_manager.py +123 -117
- 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 +9 -11
- reconcile/external_resources/factories.py +5 -12
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +24 -10
- reconcile/external_resources/meta.py +0 -1
- 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 +6 -8
- reconcile/external_resources/state.py +60 -17
- reconcile/fleet_labeler/integration.py +1 -1
- reconcile/gabi_authorized_users.py +8 -5
- reconcile/gcp_image_mirror.py +2 -2
- reconcile/github_org.py +1 -1
- reconcile/github_owners.py +4 -0
- reconcile/gitlab_housekeeping.py +13 -15
- reconcile/gitlab_members.py +6 -12
- reconcile/gitlab_mr_sqs_consumer.py +2 -2
- reconcile/gitlab_owners.py +15 -11
- 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 +15 -5
- reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +27 -66
- reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +15 -5
- reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +15 -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 +15 -5
- reconcile/gql_definitions/common/aws_vpcs.py +5 -5
- reconcile/gql_definitions/common/clusters.py +7 -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 +89 -6
- reconcile/gql_definitions/external_resources/external_resources_settings.py +7 -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 +7 -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 +33 -0
- reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
- reconcile/gql_definitions/fragments/aws_vpc_request.py +7 -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 +2137 -1053
- 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 +9 -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 +5 -5
- 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 +19 -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 +38 -6
- reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +15 -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 +10 -8
- reconcile/jira_permissions_validator.py +237 -122
- reconcile/ldap_groups/integration.py +1 -1
- reconcile/ocm/types.py +35 -56
- 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 +23 -23
- reconcile/openshift_base.py +53 -2
- reconcile/openshift_cluster_bots.py +3 -2
- 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 +5 -5
- reconcile/openshift_rolebindings.py +7 -11
- reconcile/openshift_saas_deploy.py +6 -7
- reconcile/openshift_saas_deploy_change_tester.py +9 -7
- reconcile/openshift_saas_deploy_trigger_cleaner.py +3 -5
- reconcile/openshift_serviceaccount_tokens.py +2 -2
- reconcile/openshift_upgrade_watcher.py +4 -4
- 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 +131 -1
- reconcile/rhidp/common.py +3 -5
- reconcile/rhidp/sso_client/base.py +1 -1
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
- reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
- reconcile/skupper_network/integration.py +2 -2
- reconcile/slack_usergroups.py +35 -14
- reconcile/sql_query.py +1 -0
- reconcile/status_board.py +6 -6
- reconcile/statuspage/atlassian.py +7 -7
- reconcile/statuspage/integrations/maintenances.py +4 -3
- reconcile/statuspage/page.py +4 -9
- reconcile/statuspage/status.py +5 -8
- reconcile/templates/rosa-classic-cluster-creation.sh.j2 +4 -0
- reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +3 -0
- reconcile/templating/lib/rendering.py +3 -3
- reconcile/templating/renderer.py +4 -3
- reconcile/terraform_aws_route53.py +7 -1
- 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 +187 -23
- reconcile/terraform_repo.py +16 -12
- reconcile/terraform_resources.py +17 -7
- reconcile/terraform_tgw_attachments.py +27 -19
- reconcile/terraform_users.py +7 -0
- reconcile/terraform_vpc_peerings.py +14 -3
- reconcile/terraform_vpc_resources/integration.py +10 -1
- reconcile/typed_queries/aws_account_tags.py +41 -0
- 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 +13 -13
- 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/aggregated_list.py +4 -3
- reconcile/utils/aws_api.py +51 -54
- reconcile/utils/aws_api_typed/api.py +38 -9
- reconcile/utils/aws_api_typed/cloudformation.py +149 -0
- reconcile/utils/aws_api_typed/logs.py +73 -0
- reconcile/utils/aws_api_typed/organization.py +4 -2
- reconcile/utils/datetime_util.py +67 -0
- reconcile/utils/deadmanssnitch_api.py +1 -1
- reconcile/utils/differ.py +2 -3
- reconcile/utils/early_exit_cache.py +11 -12
- reconcile/utils/expiration.py +7 -3
- reconcile/utils/external_resource_spec.py +24 -1
- reconcile/utils/filtering.py +1 -1
- 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/helm.py +2 -1
- reconcile/utils/helpers.py +1 -1
- 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 +6 -101
- reconcile/utils/jira_client.py +82 -63
- reconcile/utils/jjb_client.py +9 -12
- reconcile/utils/jobcontroller/controller.py +1 -1
- reconcile/utils/jobcontroller/models.py +17 -1
- reconcile/utils/json.py +70 -0
- 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 +4 -4
- reconcile/utils/merge_request_manager/parser.py +6 -6
- reconcile/utils/metrics.py +5 -5
- reconcile/utils/models.py +304 -82
- reconcile/utils/mr/app_interface_reporter.py +2 -2
- reconcile/utils/mr/base.py +2 -2
- reconcile/utils/mr/notificator.py +3 -3
- reconcile/utils/mr/update_access_report_base.py +3 -4
- reconcile/utils/mr/user_maintenance.py +3 -2
- reconcile/utils/oc.py +118 -97
- reconcile/utils/oc_filters.py +3 -3
- 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 +9 -3
- reconcile/utils/ocm/search_filters.py +3 -6
- reconcile/utils/ocm/service_log.py +4 -6
- reconcile/utils/ocm/sre_capability_labels.py +20 -13
- reconcile/utils/openshift_resource.py +10 -5
- reconcile/utils/output.py +3 -2
- reconcile/utils/pagerduty_api.py +10 -7
- reconcile/utils/promotion_state.py +6 -11
- reconcile/utils/raw_github_api.py +1 -1
- reconcile/utils/rhcsv2_certs.py +1 -4
- reconcile/utils/runtime/integration.py +2 -3
- reconcile/utils/runtime/runner.py +2 -2
- reconcile/utils/saasherder/interfaces.py +13 -20
- reconcile/utils/saasherder/models.py +25 -21
- reconcile/utils/saasherder/saasherder.py +35 -24
- reconcile/utils/slack_api.py +26 -4
- reconcile/utils/sloth.py +171 -2
- reconcile/utils/sqs_gateway.py +2 -1
- reconcile/utils/state.py +2 -1
- reconcile/utils/structs.py +1 -1
- reconcile/utils/terraform_client.py +5 -4
- reconcile/utils/terrascript_aws_client.py +171 -114
- reconcile/utils/unleash/server.py +2 -8
- reconcile/utils/vault.py +5 -12
- reconcile/utils/vcs.py +8 -8
- reconcile/vault_replication.py +107 -42
- tools/app_interface_reporter.py +4 -4
- 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 +3 -1
- tools/cli_commands/systems_and_tools.py +5 -1
- tools/qontract_cli.py +31 -18
- tools/template_validation.py +3 -1
- {qontract_reconcile-0.10.2.dev349.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev349.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/entry_points.txt +0 -0
reconcile/utils/oc.py
CHANGED
|
@@ -12,7 +12,6 @@ import threading
|
|
|
12
12
|
import time
|
|
13
13
|
from contextlib import suppress
|
|
14
14
|
from dataclasses import dataclass
|
|
15
|
-
from datetime import datetime
|
|
16
15
|
from functools import cache, wraps
|
|
17
16
|
from subprocess import Popen
|
|
18
17
|
from threading import Lock
|
|
@@ -47,6 +46,8 @@ from sretoolbox.utils import (
|
|
|
47
46
|
)
|
|
48
47
|
|
|
49
48
|
from reconcile.status import RunningState
|
|
49
|
+
from reconcile.utils.datetime_util import utc_now
|
|
50
|
+
from reconcile.utils.json import json_dumps
|
|
50
51
|
from reconcile.utils.jump_host import (
|
|
51
52
|
JumphostParameters,
|
|
52
53
|
JumpHostSSH,
|
|
@@ -67,7 +68,8 @@ if TYPE_CHECKING:
|
|
|
67
68
|
urllib3.disable_warnings()
|
|
68
69
|
|
|
69
70
|
GET_REPLICASET_MAX_ATTEMPTS = 20
|
|
70
|
-
|
|
71
|
+
DEFAULT_GROUP = ""
|
|
72
|
+
PROJECT_KIND = "Project.project.openshift.io"
|
|
71
73
|
|
|
72
74
|
oc_run_execution_counter = Counter(
|
|
73
75
|
name="oc_run_execution_counter",
|
|
@@ -144,6 +146,14 @@ class RequestEntityTooLargeError(Exception):
|
|
|
144
146
|
pass
|
|
145
147
|
|
|
146
148
|
|
|
149
|
+
class KindNotFoundError(Exception):
|
|
150
|
+
pass
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class AmbiguousResourceTypeError(Exception):
|
|
154
|
+
pass
|
|
155
|
+
|
|
156
|
+
|
|
147
157
|
class OCDecorators:
|
|
148
158
|
@classmethod
|
|
149
159
|
def process_reconcile_time(cls, function: Callable) -> Callable:
|
|
@@ -379,10 +389,7 @@ class OCCli:
|
|
|
379
389
|
|
|
380
390
|
self.init_projects = init_projects
|
|
381
391
|
if self.init_projects:
|
|
382
|
-
if self.is_kind_supported("
|
|
383
|
-
kind = "Project.project.openshift.io"
|
|
384
|
-
else:
|
|
385
|
-
kind = "Namespace"
|
|
392
|
+
kind = PROJECT_KIND if self.is_kind_supported(PROJECT_KIND) else "Namespace"
|
|
386
393
|
self.projects = {p["metadata"]["name"] for p in self.get_all(kind)["items"]}
|
|
387
394
|
|
|
388
395
|
self.slow_oc_reconcile_threshold = float(
|
|
@@ -452,10 +459,7 @@ class OCCli:
|
|
|
452
459
|
|
|
453
460
|
self.init_projects = init_projects
|
|
454
461
|
if self.init_projects:
|
|
455
|
-
if self.is_kind_supported("
|
|
456
|
-
kind = "Project.project.openshift.io"
|
|
457
|
-
else:
|
|
458
|
-
kind = "Namespace"
|
|
462
|
+
kind = PROJECT_KIND if self.is_kind_supported(PROJECT_KIND) else "Namespace"
|
|
459
463
|
self.projects = {p["metadata"]["name"] for p in self.get_all(kind)["items"]}
|
|
460
464
|
|
|
461
465
|
self.slow_oc_reconcile_threshold = float(
|
|
@@ -563,7 +567,7 @@ class OCCli:
|
|
|
563
567
|
"-f",
|
|
564
568
|
"-",
|
|
565
569
|
] + parameters_to_process
|
|
566
|
-
result = self._run(cmd, stdin=
|
|
570
|
+
result = self._run(cmd, stdin=json_dumps(template))
|
|
567
571
|
return json.loads(result)["items"]
|
|
568
572
|
|
|
569
573
|
@OCDecorators.process_reconcile_time
|
|
@@ -592,7 +596,7 @@ class OCCli:
|
|
|
592
596
|
def patch(
|
|
593
597
|
self, namespace: str, kind: str, name: str, patch: Mapping[str, Any]
|
|
594
598
|
) -> OCProcessReconcileTimeDecoratorMsg:
|
|
595
|
-
cmd = ["patch", "-n", namespace, kind, name, "-p",
|
|
599
|
+
cmd = ["patch", "-n", namespace, kind, name, "-p", json_dumps(patch)]
|
|
596
600
|
self._run(cmd)
|
|
597
601
|
resource = OR({"kind": kind, "metadata": {"name": name}}, "", "")
|
|
598
602
|
return self._msg_to_process_reconcile_time(namespace, resource)
|
|
@@ -636,11 +640,9 @@ class OCCli:
|
|
|
636
640
|
def project_exists(self, name: str) -> bool:
|
|
637
641
|
if name in self.projects:
|
|
638
642
|
return True
|
|
643
|
+
kind = PROJECT_KIND if self.is_kind_supported(PROJECT_KIND) else "Namespace"
|
|
639
644
|
try:
|
|
640
|
-
|
|
641
|
-
self.get(None, "Project.project.openshift.io", name)
|
|
642
|
-
else:
|
|
643
|
-
self.get(None, "Namespace", name)
|
|
645
|
+
self.get(None, kind, name)
|
|
644
646
|
except StatusCodeError as e:
|
|
645
647
|
if "NotFound" in str(e):
|
|
646
648
|
return False
|
|
@@ -649,7 +651,7 @@ class OCCli:
|
|
|
649
651
|
|
|
650
652
|
@OCDecorators.process_reconcile_time
|
|
651
653
|
def new_project(self, namespace: str) -> OCProcessReconcileTimeDecoratorMsg:
|
|
652
|
-
if self.is_kind_supported(
|
|
654
|
+
if self.is_kind_supported(PROJECT_KIND):
|
|
653
655
|
cmd = ["new-project", namespace]
|
|
654
656
|
else:
|
|
655
657
|
cmd = ["create", "namespace", namespace]
|
|
@@ -665,7 +667,7 @@ class OCCli:
|
|
|
665
667
|
|
|
666
668
|
@OCDecorators.process_reconcile_time
|
|
667
669
|
def delete_project(self, namespace: str) -> OCProcessReconcileTimeDecoratorMsg:
|
|
668
|
-
if self.is_kind_supported(
|
|
670
|
+
if self.is_kind_supported(PROJECT_KIND):
|
|
669
671
|
cmd = ["delete", "project", namespace]
|
|
670
672
|
else:
|
|
671
673
|
cmd = ["delete", "namespace", namespace]
|
|
@@ -714,9 +716,9 @@ class OCCli:
|
|
|
714
716
|
|
|
715
717
|
def sa_get_token(self, namespace: str, name: str) -> str:
|
|
716
718
|
cmd = ["sa", "-n", namespace, "get-token", name]
|
|
717
|
-
return self._run(cmd)
|
|
719
|
+
return self._run(cmd).decode("utf-8")
|
|
718
720
|
|
|
719
|
-
def get_api_resources(self) -> dict[str,
|
|
721
|
+
def get_api_resources(self) -> dict[str, list[OCCliApiResource]]:
|
|
720
722
|
with self.api_resources_lock:
|
|
721
723
|
if not self.api_resources:
|
|
722
724
|
cmd = ["api-resources", "--no-headers"]
|
|
@@ -1009,7 +1011,7 @@ class OCCli:
|
|
|
1009
1011
|
name = obj["metadata"]["name"]
|
|
1010
1012
|
logging.info([f"recycle_{kind.lower()}", self.cluster_name, namespace, name])
|
|
1011
1013
|
if not dry_run:
|
|
1012
|
-
now =
|
|
1014
|
+
now = utc_now()
|
|
1013
1015
|
recycle_time = now.strftime("%d/%m/%Y %H:%M:%S")
|
|
1014
1016
|
|
|
1015
1017
|
# get the object in case it was modified
|
|
@@ -1020,7 +1022,7 @@ class OCCli:
|
|
|
1020
1022
|
a["recycle.time"] = recycle_time
|
|
1021
1023
|
obj["spec"]["template"]["metadata"]["annotations"] = a
|
|
1022
1024
|
cmd = ["apply", "-n", namespace, "-f", "-"]
|
|
1023
|
-
stdin =
|
|
1025
|
+
stdin = json_dumps(obj)
|
|
1024
1026
|
self._run(cmd, stdin=stdin, apply=True)
|
|
1025
1027
|
|
|
1026
1028
|
def get_obj_root_owner(
|
|
@@ -1186,7 +1188,7 @@ class OCCli:
|
|
|
1186
1188
|
def _run_json(
|
|
1187
1189
|
self, cmd: list[str], allow_not_found: bool = False
|
|
1188
1190
|
) -> dict[str, Any]:
|
|
1189
|
-
out = self._run(cmd, allow_not_found=allow_not_found)
|
|
1191
|
+
out = self._run(cmd, allow_not_found=allow_not_found).decode("utf-8")
|
|
1190
1192
|
|
|
1191
1193
|
try:
|
|
1192
1194
|
out_json = json.loads(out)
|
|
@@ -1195,76 +1197,90 @@ class OCCli:
|
|
|
1195
1197
|
|
|
1196
1198
|
return out_json
|
|
1197
1199
|
|
|
1198
|
-
def
|
|
1199
|
-
|
|
1200
|
-
# the api resources initialization.
|
|
1201
|
-
if not self.api_resources:
|
|
1202
|
-
self.get_api_resources()
|
|
1200
|
+
def parse_kind(self, kind: str) -> tuple[str, str, str]:
|
|
1201
|
+
"""Parse a Kubernetes kind string into its components.
|
|
1203
1202
|
|
|
1204
|
-
|
|
1205
|
-
kind
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
else:
|
|
1209
|
-
raise StatusCodeError(f"{self.server}: {kind} does not exist")
|
|
1210
|
-
|
|
1211
|
-
# if a kind_group has more than 1 entry than the kind_name is in
|
|
1212
|
-
# the format kind.apigroup. Find the apigroup/version that matches
|
|
1213
|
-
# the apigroup passed with the kind_name
|
|
1214
|
-
if len(kind_group) > 1:
|
|
1215
|
-
apigroup_override = kind_group[1]
|
|
1216
|
-
find = False
|
|
1217
|
-
for gv in self.api_resources[kind]:
|
|
1218
|
-
if apigroup_override == gv.group:
|
|
1219
|
-
if not gv.group:
|
|
1220
|
-
group_version = gv.api_version
|
|
1221
|
-
else:
|
|
1222
|
-
group_version = f"{gv.group}/{gv.api_version}"
|
|
1223
|
-
find = True
|
|
1224
|
-
break
|
|
1203
|
+
Supports three formats:
|
|
1204
|
+
- kind
|
|
1205
|
+
- kind.group.whatever
|
|
1206
|
+
- kind.group.whatever/version
|
|
1225
1207
|
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1208
|
+
Args:
|
|
1209
|
+
kind: A Kubernetes kind string in one of the supported formats
|
|
1210
|
+
|
|
1211
|
+
Returns:
|
|
1212
|
+
Tuple of (kind, group, version) where missing parts are empty strings
|
|
1213
|
+
|
|
1214
|
+
Raises:
|
|
1215
|
+
ValueError: If the kind string format is invalid
|
|
1216
|
+
|
|
1217
|
+
Examples:
|
|
1218
|
+
>>> parse_kind_string("Deployment")
|
|
1219
|
+
('Deployment', '', '')
|
|
1220
|
+
>>> parse_kind_string("ClusterRoleBinding.rbac.authorization.k8s.io")
|
|
1221
|
+
('ClusterRoleBinding', 'rbac.authorization.k8s.io', '')
|
|
1222
|
+
>>> parse_kind_string("CustomResource.mygroup.example.com/v1")
|
|
1223
|
+
('CustomResource', 'mygroup.example.com', 'v1')
|
|
1224
|
+
"""
|
|
1225
|
+
pattern = r"^(?P<kind>[^./]+)(?:\.(?P<group>[^/]+))?(?:/(?P<version>.+))?$"
|
|
1226
|
+
match = re.match(pattern, kind)
|
|
1227
|
+
if not match:
|
|
1228
|
+
raise ValueError(f"Invalid kind string: {kind}")
|
|
1229
|
+
|
|
1230
|
+
kind = match.group("kind") or ""
|
|
1231
|
+
group = match.group("group") or DEFAULT_GROUP
|
|
1232
|
+
version = match.group("version") or ""
|
|
1233
|
+
|
|
1234
|
+
return kind, group, version
|
|
1231
1235
|
|
|
1232
1236
|
def is_kind_supported(self, kind: str) -> bool:
|
|
1233
|
-
|
|
1234
|
-
# the api resources initialization.
|
|
1235
|
-
if not self.api_resources:
|
|
1236
|
-
self.get_api_resources()
|
|
1237
|
+
"""Returns True if the given kind is supported by the cluster, False otherwise.
|
|
1237
1238
|
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
else:
|
|
1245
|
-
return kind in self.api_resources
|
|
1239
|
+
Kind can be either kind, kind.group or kind.group/version."""
|
|
1240
|
+
try:
|
|
1241
|
+
self.get_api_resource(kind)
|
|
1242
|
+
return True
|
|
1243
|
+
except KindNotFoundError:
|
|
1244
|
+
return False
|
|
1246
1245
|
|
|
1247
1246
|
def is_kind_namespaced(self, kind: str) -> bool:
|
|
1248
|
-
|
|
1249
|
-
|
|
1247
|
+
"""Returns True if the given kind is namespaced, False if it's cluster scoped.
|
|
1248
|
+
|
|
1249
|
+
Kind can be either kind, kind.group or kind.group/version."""
|
|
1250
|
+
return self.get_api_resource(kind).namespaced
|
|
1251
|
+
|
|
1252
|
+
def get_api_resource(self, kind: str) -> OCCliApiResource:
|
|
1253
|
+
"""Return the OCCliApiResource for the given resource type.
|
|
1254
|
+
|
|
1255
|
+
Resource type can be either kind, kind.group or kind.group/version.
|
|
1256
|
+
If kind is not unique, group must be specified."""
|
|
1257
|
+
|
|
1250
1258
|
if not self.api_resources:
|
|
1251
|
-
|
|
1259
|
+
raise RuntimeError("API resources not initialized")
|
|
1260
|
+
|
|
1261
|
+
kind, group, _ = self.parse_kind(kind)
|
|
1252
1262
|
|
|
1253
|
-
|
|
1254
|
-
|
|
1263
|
+
if not (resources := self.api_resources.get(kind)):
|
|
1264
|
+
# the kind not found at all
|
|
1265
|
+
raise KindNotFoundError(f"Unsupported resource type: {kind}")
|
|
1255
1266
|
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
if not kind_resources:
|
|
1259
|
-
raise StatusCodeError(f"Kind {kind} does not exist in the ApiServer")
|
|
1267
|
+
if len(resources) == 1 and group == DEFAULT_GROUP:
|
|
1268
|
+
return resources[0]
|
|
1260
1269
|
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1270
|
+
# get the resource with the specified group
|
|
1271
|
+
if resource := next((r for r in resources if r.group == group), None):
|
|
1272
|
+
return resource
|
|
1273
|
+
|
|
1274
|
+
# no resource with the specified group found
|
|
1275
|
+
if group == DEFAULT_GROUP:
|
|
1276
|
+
message = (
|
|
1277
|
+
f"Ambiguous resource type: {kind}. "
|
|
1278
|
+
"Please fully qualify it with its API group. E.g., ClusterRoleBinding -> ClusterRoleBinding.rbac.authorization.k8s.io"
|
|
1279
|
+
)
|
|
1280
|
+
raise AmbiguousResourceTypeError(message)
|
|
1281
|
+
|
|
1282
|
+
# group was specified but no matching resource found
|
|
1283
|
+
raise KindNotFoundError(f"Unsupported resource type: {kind}")
|
|
1268
1284
|
|
|
1269
1285
|
|
|
1270
1286
|
REQUEST_TIMEOUT = 60
|
|
@@ -1304,20 +1320,19 @@ class OCNative(OCCli):
|
|
|
1304
1320
|
|
|
1305
1321
|
server = connection_parameters.server_url
|
|
1306
1322
|
|
|
1307
|
-
if server:
|
|
1308
|
-
|
|
1309
|
-
self.api_resources = self.get_api_resources()
|
|
1323
|
+
if not server:
|
|
1324
|
+
raise Exception("Server name is required!")
|
|
1310
1325
|
|
|
1311
|
-
|
|
1312
|
-
raise Exception("
|
|
1326
|
+
if not token:
|
|
1327
|
+
raise Exception("Token is required!")
|
|
1328
|
+
|
|
1329
|
+
self.client = self._get_client(server, token)
|
|
1330
|
+
self.api_resources = self.get_api_resources()
|
|
1313
1331
|
|
|
1314
1332
|
self.projects = set()
|
|
1315
1333
|
self.init_projects = init_projects
|
|
1316
1334
|
if self.init_projects:
|
|
1317
|
-
if self.is_kind_supported("
|
|
1318
|
-
kind = "Project.project.openshift.io"
|
|
1319
|
-
else:
|
|
1320
|
-
kind = "Namespace"
|
|
1335
|
+
kind = PROJECT_KIND if self.is_kind_supported(PROJECT_KIND) else "Namespace"
|
|
1321
1336
|
self.projects = {p["metadata"]["name"] for p in self.get_all(kind)["items"]}
|
|
1322
1337
|
|
|
1323
1338
|
def __enter__(self) -> OCNative:
|
|
@@ -1367,8 +1382,10 @@ class OCNative(OCCli):
|
|
|
1367
1382
|
|
|
1368
1383
|
@retry(max_attempts=5, exceptions=(ServerTimeoutError))
|
|
1369
1384
|
def get_items(self, kind: str, **kwargs: Any) -> list[dict[str, Any]]:
|
|
1370
|
-
|
|
1371
|
-
obj_client = self._get_obj_client(
|
|
1385
|
+
resource = self.get_api_resource(kind)
|
|
1386
|
+
obj_client = self._get_obj_client(
|
|
1387
|
+
group_version=resource.group_version, kind=resource.kind
|
|
1388
|
+
)
|
|
1372
1389
|
|
|
1373
1390
|
namespace = ""
|
|
1374
1391
|
if "namespace" in kwargs:
|
|
@@ -1420,8 +1437,10 @@ class OCNative(OCCli):
|
|
|
1420
1437
|
name: str | None = None,
|
|
1421
1438
|
allow_not_found: bool = False,
|
|
1422
1439
|
) -> dict[str, Any]:
|
|
1423
|
-
|
|
1424
|
-
obj_client = self._get_obj_client(
|
|
1440
|
+
resource = self.get_api_resource(kind)
|
|
1441
|
+
obj_client = self._get_obj_client(
|
|
1442
|
+
group_version=resource.group_version, kind=resource.kind
|
|
1443
|
+
)
|
|
1425
1444
|
try:
|
|
1426
1445
|
obj = obj_client.get(
|
|
1427
1446
|
name=name,
|
|
@@ -1435,8 +1454,10 @@ class OCNative(OCCli):
|
|
|
1435
1454
|
raise StatusCodeError(f"[{self.server}]: {e}") from None
|
|
1436
1455
|
|
|
1437
1456
|
def get_all(self, kind: str, all_namespaces: bool = False) -> dict[str, Any]:
|
|
1438
|
-
|
|
1439
|
-
obj_client = self._get_obj_client(
|
|
1457
|
+
resource = self.get_api_resource(kind)
|
|
1458
|
+
obj_client = self._get_obj_client(
|
|
1459
|
+
group_version=resource.group_version, kind=resource.kind
|
|
1460
|
+
)
|
|
1440
1461
|
try:
|
|
1441
1462
|
return obj_client.get(_request_timeout=REQUEST_TIMEOUT).to_dict()
|
|
1442
1463
|
except NotFoundError as e:
|
reconcile/utils/oc_filters.py
CHANGED
|
@@ -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,
|
reconcile/utils/ocm/addons.py
CHANGED
reconcile/utils/ocm/base.py
CHANGED
|
@@ -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
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(
|
|
@@ -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.
|
|
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.
|
|
58
|
+
data=idp.model_dump(by_alias=True, exclude_none=True, exclude={"name"}),
|
|
59
59
|
)
|
|
60
60
|
|
|
61
61
|
|
reconcile/utils/ocm/labels.py
CHANGED
|
@@ -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.
|
|
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()
|
reconcile/utils/ocm/products.py
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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":
|
|
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",
|
|
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.
|
|
58
|
+
data=service_log.model_dump(by_alias=True),
|
|
61
59
|
)
|
|
62
60
|
)
|