zenml-nightly 0.58.2.dev20240615__py3-none-any.whl → 0.58.2.dev20240623__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.
- zenml/VERSION +1 -1
- zenml/_hub/client.py +8 -5
- zenml/actions/base_action.py +8 -10
- zenml/artifact_stores/base_artifact_store.py +20 -15
- zenml/artifact_stores/local_artifact_store.py +3 -2
- zenml/artifacts/artifact_config.py +34 -19
- zenml/artifacts/external_artifact.py +18 -8
- zenml/artifacts/external_artifact_config.py +14 -6
- zenml/artifacts/unmaterialized_artifact.py +2 -11
- zenml/cli/__init__.py +6 -0
- zenml/cli/artifact.py +20 -2
- zenml/cli/base.py +1 -1
- zenml/cli/served_model.py +0 -1
- zenml/cli/server.py +3 -3
- zenml/cli/utils.py +36 -40
- zenml/cli/web_login.py +2 -2
- zenml/client.py +198 -24
- zenml/client_lazy_loader.py +20 -14
- zenml/config/base_settings.py +5 -6
- zenml/config/build_configuration.py +1 -1
- zenml/config/compiler.py +3 -3
- zenml/config/docker_settings.py +27 -28
- zenml/config/global_config.py +33 -37
- zenml/config/pipeline_configurations.py +8 -11
- zenml/config/pipeline_run_configuration.py +6 -2
- zenml/config/pipeline_spec.py +3 -4
- zenml/config/resource_settings.py +8 -9
- zenml/config/schedule.py +16 -20
- zenml/config/secret_reference_mixin.py +6 -3
- zenml/config/secrets_store_config.py +16 -23
- zenml/config/server_config.py +50 -46
- zenml/config/settings_resolver.py +1 -1
- zenml/config/source.py +45 -35
- zenml/config/step_configurations.py +53 -31
- zenml/config/step_run_info.py +3 -0
- zenml/config/store_config.py +20 -19
- zenml/config/strict_base_model.py +2 -6
- zenml/constants.py +26 -2
- zenml/container_registries/base_container_registry.py +3 -2
- zenml/container_registries/default_container_registry.py +3 -3
- zenml/event_hub/base_event_hub.py +1 -1
- zenml/event_sources/base_event_source.py +11 -16
- zenml/exceptions.py +4 -0
- zenml/integrations/airflow/__init__.py +2 -6
- zenml/integrations/airflow/flavors/airflow_orchestrator_flavor.py +6 -7
- zenml/integrations/airflow/orchestrators/airflow_orchestrator.py +13 -249
- zenml/integrations/airflow/orchestrators/dag_generator.py +5 -3
- zenml/integrations/argilla/flavors/argilla_annotator_flavor.py +5 -4
- zenml/integrations/aws/__init__.py +1 -1
- zenml/integrations/aws/flavors/aws_container_registry_flavor.py +3 -2
- zenml/integrations/aws/flavors/sagemaker_orchestrator_flavor.py +11 -5
- zenml/integrations/aws/flavors/sagemaker_step_operator_flavor.py +6 -2
- zenml/integrations/aws/service_connectors/aws_service_connector.py +5 -4
- zenml/integrations/aws/step_operators/sagemaker_step_operator.py +1 -1
- zenml/integrations/azure/flavors/azureml_step_operator_flavor.py +4 -4
- zenml/integrations/azure/service_connectors/azure_service_connector.py +4 -3
- zenml/integrations/azure/step_operators/azureml_step_operator.py +2 -1
- zenml/integrations/bentoml/steps/bentoml_deployer.py +1 -1
- zenml/integrations/bitbucket/plugins/event_sources/bitbucket_webhook_event_source.py +8 -12
- zenml/integrations/comet/flavors/comet_experiment_tracker_flavor.py +1 -1
- zenml/integrations/constants.py +0 -1
- zenml/integrations/deepchecks/__init__.py +1 -0
- zenml/integrations/evidently/__init__.py +5 -3
- zenml/integrations/evidently/column_mapping.py +11 -3
- zenml/integrations/evidently/data_validators/evidently_data_validator.py +21 -3
- zenml/integrations/evidently/metrics.py +5 -6
- zenml/integrations/evidently/tests.py +5 -6
- zenml/integrations/facets/models.py +2 -6
- zenml/integrations/feast/__init__.py +3 -1
- zenml/integrations/feast/feature_stores/feast_feature_store.py +0 -23
- zenml/integrations/gcp/__init__.py +1 -1
- zenml/integrations/gcp/flavors/vertex_orchestrator_flavor.py +1 -1
- zenml/integrations/gcp/flavors/vertex_step_operator_flavor.py +1 -1
- zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +234 -103
- zenml/integrations/gcp/service_connectors/gcp_service_connector.py +57 -42
- zenml/integrations/gcp/step_operators/vertex_step_operator.py +1 -0
- zenml/integrations/github/code_repositories/github_code_repository.py +1 -1
- zenml/integrations/github/plugins/event_sources/github_webhook_event_source.py +9 -13
- zenml/integrations/great_expectations/__init__.py +1 -1
- zenml/integrations/great_expectations/data_validators/ge_data_validator.py +44 -44
- zenml/integrations/great_expectations/flavors/great_expectations_data_validator_flavor.py +35 -2
- zenml/integrations/great_expectations/ge_store_backend.py +24 -11
- zenml/integrations/great_expectations/materializers/ge_materializer.py +3 -3
- zenml/integrations/great_expectations/utils.py +5 -5
- zenml/integrations/huggingface/__init__.py +3 -0
- zenml/integrations/huggingface/flavors/huggingface_model_deployer_flavor.py +1 -1
- zenml/integrations/huggingface/steps/__init__.py +3 -0
- zenml/integrations/huggingface/steps/accelerate_runner.py +149 -0
- zenml/integrations/huggingface/steps/huggingface_deployer.py +2 -2
- zenml/integrations/hyperai/flavors/hyperai_orchestrator_flavor.py +1 -1
- zenml/integrations/hyperai/service_connectors/hyperai_service_connector.py +4 -3
- zenml/integrations/kubeflow/__init__.py +1 -1
- zenml/integrations/kubeflow/flavors/kubeflow_orchestrator_flavor.py +48 -81
- zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py +295 -245
- zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py +1 -1
- zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py +11 -2
- zenml/integrations/kubernetes/pod_settings.py +17 -31
- zenml/integrations/kubernetes/service_connectors/kubernetes_service_connector.py +8 -7
- zenml/integrations/label_studio/__init__.py +1 -3
- zenml/integrations/label_studio/annotators/label_studio_annotator.py +3 -4
- zenml/integrations/label_studio/flavors/label_studio_annotator_flavor.py +2 -2
- zenml/integrations/langchain/__init__.py +5 -1
- zenml/integrations/langchain/materializers/document_materializer.py +44 -8
- zenml/integrations/mlflow/__init__.py +9 -3
- zenml/integrations/mlflow/experiment_trackers/mlflow_experiment_tracker.py +1 -1
- zenml/integrations/mlflow/flavors/mlflow_experiment_tracker_flavor.py +29 -37
- zenml/integrations/mlflow/model_registries/mlflow_model_registry.py +4 -4
- zenml/integrations/mlflow/steps/mlflow_deployer.py +1 -1
- zenml/integrations/neptune/flavors/neptune_experiment_tracker_flavor.py +1 -1
- zenml/integrations/neural_prophet/__init__.py +5 -1
- zenml/integrations/pigeon/flavors/pigeon_annotator_flavor.py +1 -1
- zenml/integrations/s3/flavors/s3_artifact_store_flavor.py +9 -8
- zenml/integrations/seldon/seldon_client.py +52 -67
- zenml/integrations/seldon/services/seldon_deployment.py +3 -3
- zenml/integrations/seldon/steps/seldon_deployer.py +4 -4
- zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py +15 -5
- zenml/integrations/skypilot_aws/__init__.py +1 -1
- zenml/integrations/skypilot_aws/flavors/skypilot_orchestrator_aws_vm_flavor.py +1 -1
- zenml/integrations/skypilot_azure/__init__.py +1 -1
- zenml/integrations/skypilot_azure/flavors/skypilot_orchestrator_azure_vm_flavor.py +1 -1
- zenml/integrations/skypilot_gcp/__init__.py +2 -1
- zenml/integrations/skypilot_gcp/flavors/skypilot_orchestrator_gcp_vm_flavor.py +1 -1
- zenml/integrations/skypilot_lambda/flavors/skypilot_orchestrator_lambda_vm_flavor.py +2 -2
- zenml/integrations/spark/flavors/spark_step_operator_flavor.py +1 -1
- zenml/integrations/spark/step_operators/spark_step_operator.py +2 -0
- zenml/integrations/tekton/__init__.py +1 -1
- zenml/integrations/tekton/flavors/tekton_orchestrator_flavor.py +66 -23
- zenml/integrations/tekton/orchestrators/tekton_orchestrator.py +547 -233
- zenml/integrations/tensorboard/__init__.py +1 -12
- zenml/integrations/tensorboard/services/tensorboard_service.py +3 -5
- zenml/integrations/tensorboard/visualizers/tensorboard_visualizer.py +6 -6
- zenml/integrations/tensorflow/__init__.py +2 -10
- zenml/integrations/tensorflow/materializers/keras_materializer.py +17 -9
- zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py +9 -14
- zenml/integrations/whylogs/flavors/whylogs_data_validator_flavor.py +1 -1
- zenml/lineage_graph/lineage_graph.py +1 -1
- zenml/logging/step_logging.py +15 -7
- zenml/materializers/built_in_materializer.py +3 -3
- zenml/materializers/pydantic_materializer.py +2 -2
- zenml/metadata/lazy_load.py +4 -4
- zenml/metadata/metadata_types.py +64 -4
- zenml/model/model.py +79 -54
- zenml/model_deployers/base_model_deployer.py +14 -12
- zenml/model_registries/base_model_registry.py +17 -15
- zenml/models/__init__.py +79 -206
- zenml/models/v2/base/base.py +54 -41
- zenml/models/v2/base/base_plugin_flavor.py +2 -6
- zenml/models/v2/base/filter.py +91 -76
- zenml/models/v2/base/page.py +2 -12
- zenml/models/v2/base/scoped.py +4 -7
- zenml/models/v2/core/api_key.py +22 -8
- zenml/models/v2/core/artifact.py +2 -2
- zenml/models/v2/core/artifact_version.py +74 -40
- zenml/models/v2/core/code_repository.py +37 -10
- zenml/models/v2/core/component.py +65 -16
- zenml/models/v2/core/device.py +14 -4
- zenml/models/v2/core/event_source.py +1 -2
- zenml/models/v2/core/flavor.py +74 -8
- zenml/models/v2/core/logs.py +68 -8
- zenml/models/v2/core/model.py +8 -4
- zenml/models/v2/core/model_version.py +25 -6
- zenml/models/v2/core/model_version_artifact.py +51 -21
- zenml/models/v2/core/model_version_pipeline_run.py +45 -13
- zenml/models/v2/core/pipeline.py +37 -72
- zenml/models/v2/core/pipeline_build.py +29 -17
- zenml/models/v2/core/pipeline_deployment.py +18 -6
- zenml/models/v2/core/pipeline_namespace.py +113 -0
- zenml/models/v2/core/pipeline_run.py +50 -22
- zenml/models/v2/core/run_metadata.py +59 -36
- zenml/models/v2/core/schedule.py +37 -24
- zenml/models/v2/core/secret.py +31 -12
- zenml/models/v2/core/service.py +64 -36
- zenml/models/v2/core/service_account.py +24 -11
- zenml/models/v2/core/service_connector.py +219 -44
- zenml/models/v2/core/stack.py +45 -17
- zenml/models/v2/core/step_run.py +28 -8
- zenml/models/v2/core/tag.py +8 -4
- zenml/models/v2/core/trigger.py +2 -2
- zenml/models/v2/core/trigger_execution.py +1 -0
- zenml/models/v2/core/user.py +18 -21
- zenml/models/v2/core/workspace.py +13 -3
- zenml/models/v2/misc/build_item.py +3 -3
- zenml/models/v2/misc/external_user.py +2 -6
- zenml/models/v2/misc/hub_plugin_models.py +9 -9
- zenml/models/v2/misc/loaded_visualization.py +2 -2
- zenml/models/v2/misc/service_connector_type.py +8 -17
- zenml/models/v2/misc/user_auth.py +7 -2
- zenml/new/pipelines/build_utils.py +3 -3
- zenml/new/pipelines/pipeline.py +17 -13
- zenml/new/pipelines/run_utils.py +103 -1
- zenml/orchestrators/base_orchestrator.py +10 -7
- zenml/orchestrators/local_docker/local_docker_orchestrator.py +1 -1
- zenml/orchestrators/step_launcher.py +28 -4
- zenml/orchestrators/step_runner.py +3 -6
- zenml/orchestrators/utils.py +1 -1
- zenml/plugins/base_plugin_flavor.py +6 -10
- zenml/plugins/plugin_flavor_registry.py +3 -7
- zenml/secret/base_secret.py +7 -8
- zenml/service_connectors/docker_service_connector.py +4 -3
- zenml/service_connectors/service_connector.py +5 -12
- zenml/service_connectors/service_connector_registry.py +2 -4
- zenml/services/container/container_service.py +1 -1
- zenml/services/container/container_service_endpoint.py +1 -1
- zenml/services/local/local_service.py +1 -1
- zenml/services/local/local_service_endpoint.py +1 -1
- zenml/services/service.py +16 -10
- zenml/services/service_type.py +4 -5
- zenml/services/terraform/terraform_service.py +1 -1
- zenml/stack/flavor.py +1 -5
- zenml/stack/flavor_registry.py +4 -4
- zenml/stack/stack.py +4 -1
- zenml/stack/stack_component.py +55 -31
- zenml/step_operators/step_operator_entrypoint_configuration.py +1 -0
- zenml/steps/base_step.py +34 -28
- zenml/steps/entrypoint_function_utils.py +3 -5
- zenml/steps/utils.py +12 -14
- zenml/utils/cuda_utils.py +50 -0
- zenml/utils/deprecation_utils.py +18 -20
- zenml/utils/dict_utils.py +1 -1
- zenml/utils/filesync_model.py +65 -28
- zenml/utils/function_utils.py +260 -0
- zenml/utils/json_utils.py +131 -0
- zenml/utils/mlstacks_utils.py +2 -2
- zenml/utils/pipeline_docker_image_builder.py +9 -0
- zenml/utils/pydantic_utils.py +270 -62
- zenml/utils/secret_utils.py +65 -12
- zenml/utils/source_utils.py +2 -2
- zenml/utils/typed_model.py +5 -3
- zenml/utils/typing_utils.py +243 -0
- zenml/utils/yaml_utils.py +1 -1
- zenml/zen_server/auth.py +2 -2
- zenml/zen_server/cloud_utils.py +6 -6
- zenml/zen_server/deploy/base_provider.py +1 -1
- zenml/zen_server/deploy/deployment.py +6 -8
- zenml/zen_server/deploy/docker/docker_zen_server.py +3 -4
- zenml/zen_server/deploy/local/local_provider.py +0 -1
- zenml/zen_server/deploy/local/local_zen_server.py +6 -6
- zenml/zen_server/deploy/terraform/terraform_zen_server.py +4 -6
- zenml/zen_server/exceptions.py +4 -1
- zenml/zen_server/feature_gate/zenml_cloud_feature_gate.py +1 -1
- zenml/zen_server/pipeline_deployment/utils.py +48 -68
- zenml/zen_server/rbac/models.py +2 -5
- zenml/zen_server/rbac/utils.py +11 -14
- zenml/zen_server/routers/auth_endpoints.py +2 -2
- zenml/zen_server/routers/pipeline_builds_endpoints.py +1 -1
- zenml/zen_server/routers/runs_endpoints.py +1 -1
- zenml/zen_server/routers/secrets_endpoints.py +3 -2
- zenml/zen_server/routers/server_endpoints.py +1 -1
- zenml/zen_server/routers/steps_endpoints.py +1 -1
- zenml/zen_server/routers/workspaces_endpoints.py +1 -1
- zenml/zen_stores/base_zen_store.py +46 -9
- zenml/zen_stores/migrations/utils.py +42 -46
- zenml/zen_stores/migrations/versions/0701da9951a0_added_service_table.py +1 -1
- zenml/zen_stores/migrations/versions/1041bc644e0d_remove_secrets_manager.py +5 -3
- zenml/zen_stores/migrations/versions/10a907dad202_delete_mlmd_tables.py +1 -1
- zenml/zen_stores/migrations/versions/26b776ad583e_redesign_artifacts.py +8 -10
- zenml/zen_stores/migrations/versions/37835ce041d2_optimizing_database.py +3 -3
- zenml/zen_stores/migrations/versions/46506f72f0ed_add_server_settings.py +10 -12
- zenml/zen_stores/migrations/versions/5994f9ad0489_introduce_role_permissions.py +3 -2
- zenml/zen_stores/migrations/versions/6917bce75069_add_pipeline_run_unique_constraint.py +4 -4
- zenml/zen_stores/migrations/versions/728c6369cfaa_add_name_column_to_input_artifact_pk.py +3 -2
- zenml/zen_stores/migrations/versions/743ec82b1b3c_update_size_of_build_images.py +2 -2
- zenml/zen_stores/migrations/versions/7500f434b71c_remove_shared_columns.py +3 -2
- zenml/zen_stores/migrations/versions/7834208cc3f6_artifact_project_scoping.py +8 -7
- zenml/zen_stores/migrations/versions/7b651bf6822e_track_secrets_in_db.py +6 -4
- zenml/zen_stores/migrations/versions/7e4a481d17f7_add_identity_table.py +2 -2
- zenml/zen_stores/migrations/versions/7f603e583dd7_fixed_migration.py +1 -1
- zenml/zen_stores/migrations/versions/a39c4184c8ce_remove_secrets_manager_flavors.py +2 -2
- zenml/zen_stores/migrations/versions/a91762e6be36_artifact_version_table.py +4 -4
- zenml/zen_stores/migrations/versions/alembic_start.py +1 -1
- zenml/zen_stores/migrations/versions/fbd7f18ced1e_increase_step_run_field_lengths.py +4 -4
- zenml/zen_stores/rest_zen_store.py +109 -49
- zenml/zen_stores/schemas/api_key_schemas.py +1 -1
- zenml/zen_stores/schemas/artifact_schemas.py +8 -8
- zenml/zen_stores/schemas/artifact_visualization_schemas.py +3 -3
- zenml/zen_stores/schemas/code_repository_schemas.py +1 -1
- zenml/zen_stores/schemas/component_schemas.py +8 -3
- zenml/zen_stores/schemas/device_schemas.py +8 -6
- zenml/zen_stores/schemas/event_source_schemas.py +3 -4
- zenml/zen_stores/schemas/flavor_schemas.py +5 -3
- zenml/zen_stores/schemas/model_schemas.py +26 -1
- zenml/zen_stores/schemas/pipeline_build_schemas.py +1 -1
- zenml/zen_stores/schemas/pipeline_deployment_schemas.py +4 -4
- zenml/zen_stores/schemas/pipeline_run_schemas.py +6 -6
- zenml/zen_stores/schemas/pipeline_schemas.py +5 -2
- zenml/zen_stores/schemas/run_metadata_schemas.py +2 -2
- zenml/zen_stores/schemas/secret_schemas.py +8 -5
- zenml/zen_stores/schemas/server_settings_schemas.py +3 -1
- zenml/zen_stores/schemas/service_connector_schemas.py +1 -1
- zenml/zen_stores/schemas/service_schemas.py +11 -2
- zenml/zen_stores/schemas/stack_schemas.py +1 -1
- zenml/zen_stores/schemas/step_run_schemas.py +11 -11
- zenml/zen_stores/schemas/tag_schemas.py +6 -2
- zenml/zen_stores/schemas/trigger_schemas.py +2 -2
- zenml/zen_stores/schemas/user_schemas.py +2 -2
- zenml/zen_stores/schemas/workspace_schemas.py +3 -1
- zenml/zen_stores/secrets_stores/aws_secrets_store.py +19 -20
- zenml/zen_stores/secrets_stores/azure_secrets_store.py +17 -20
- zenml/zen_stores/secrets_stores/base_secrets_store.py +79 -12
- zenml/zen_stores/secrets_stores/gcp_secrets_store.py +17 -20
- zenml/zen_stores/secrets_stores/hashicorp_secrets_store.py +4 -8
- zenml/zen_stores/secrets_stores/service_connector_secrets_store.py +10 -7
- zenml/zen_stores/secrets_stores/sql_secrets_store.py +5 -6
- zenml/zen_stores/sql_zen_store.py +196 -120
- zenml/zen_stores/zen_store_interface.py +33 -0
- {zenml_nightly-0.58.2.dev20240615.dist-info → zenml_nightly-0.58.2.dev20240623.dist-info}/METADATA +9 -7
- {zenml_nightly-0.58.2.dev20240615.dist-info → zenml_nightly-0.58.2.dev20240623.dist-info}/RECORD +310 -307
- zenml/integrations/kubeflow/utils.py +0 -95
- zenml/models/v2/base/internal.py +0 -37
- zenml/models/v2/base/update.py +0 -44
- {zenml_nightly-0.58.2.dev20240615.dist-info → zenml_nightly-0.58.2.dev20240623.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.58.2.dev20240615.dist-info → zenml_nightly-0.58.2.dev20240623.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.58.2.dev20240615.dist-info → zenml_nightly-0.58.2.dev20240623.dist-info}/entry_points.txt +0 -0
@@ -31,7 +31,7 @@
|
|
31
31
|
"""Implementation of the Kubeflow orchestrator."""
|
32
32
|
|
33
33
|
import os
|
34
|
-
import
|
34
|
+
import types
|
35
35
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type, cast
|
36
36
|
from uuid import UUID
|
37
37
|
|
@@ -39,15 +39,15 @@ import kfp
|
|
39
39
|
import requests
|
40
40
|
import urllib3
|
41
41
|
from kfp import dsl
|
42
|
-
from kfp.
|
42
|
+
from kfp.client import Client as KFPClient
|
43
|
+
from kfp.compiler import Compiler
|
43
44
|
from kfp_server_api.exceptions import ApiException
|
44
45
|
from kubernetes import client as k8s_client
|
45
46
|
from kubernetes import config as k8s_config
|
46
47
|
|
47
48
|
from zenml.client import Client
|
48
|
-
from zenml.config.
|
49
|
+
from zenml.config.resource_settings import ResourceSettings
|
49
50
|
from zenml.constants import (
|
50
|
-
ENV_ZENML_LOCAL_STORES_PATH,
|
51
51
|
METADATA_ORCHESTRATOR_URL,
|
52
52
|
)
|
53
53
|
from zenml.entrypoints import StepEntrypointConfiguration
|
@@ -57,19 +57,17 @@ from zenml.integrations.kubeflow.flavors.kubeflow_orchestrator_flavor import (
|
|
57
57
|
KubeflowOrchestratorConfig,
|
58
58
|
KubeflowOrchestratorSettings,
|
59
59
|
)
|
60
|
-
from zenml.integrations.kubeflow.utils import apply_pod_settings
|
61
60
|
from zenml.io import fileio
|
62
61
|
from zenml.logger import get_logger
|
63
62
|
from zenml.metadata.metadata_types import MetadataType, Uri
|
64
63
|
from zenml.orchestrators import ContainerizedOrchestrator
|
65
64
|
from zenml.orchestrators.utils import get_orchestrator_run_name
|
66
65
|
from zenml.stack import StackValidator
|
67
|
-
from zenml.utils import io_utils, settings_utils
|
66
|
+
from zenml.utils import io_utils, settings_utils, yaml_utils
|
68
67
|
|
69
68
|
if TYPE_CHECKING:
|
70
69
|
from zenml.models import PipelineDeploymentResponse
|
71
70
|
from zenml.stack import Stack
|
72
|
-
from zenml.steps import ResourceSettings
|
73
71
|
|
74
72
|
|
75
73
|
logger = get_logger(__name__)
|
@@ -80,6 +78,7 @@ KFP_POD_LABELS = {
|
|
80
78
|
}
|
81
79
|
|
82
80
|
ENV_KFP_RUN_ID = "KFP_RUN_ID"
|
81
|
+
KFP_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL = "accelerator"
|
83
82
|
|
84
83
|
|
85
84
|
class KubeClientKFPClient(kfp.Client): # type: ignore[misc]
|
@@ -121,7 +120,7 @@ class KubeClientKFPClient(kfp.Client): # type: ignore[misc]
|
|
121
120
|
host = (
|
122
121
|
kube_config.host
|
123
122
|
+ "/"
|
124
|
-
+ self.
|
123
|
+
+ self._KUBE_PROXY_PATH.format(kwargs.get("namespace", "kubeflow"))
|
125
124
|
)
|
126
125
|
|
127
126
|
config = Configuration(
|
@@ -145,6 +144,70 @@ class KubeClientKFPClient(kfp.Client): # type: ignore[misc]
|
|
145
144
|
class KubeflowOrchestrator(ContainerizedOrchestrator):
|
146
145
|
"""Orchestrator responsible for running pipelines using Kubeflow."""
|
147
146
|
|
147
|
+
_k8s_client: Optional[k8s_client.ApiClient] = None
|
148
|
+
|
149
|
+
def _get_kfp_client(
|
150
|
+
self,
|
151
|
+
settings: KubeflowOrchestratorSettings,
|
152
|
+
) -> kfp.Client:
|
153
|
+
"""Creates a KFP client instance.
|
154
|
+
|
155
|
+
Args:
|
156
|
+
settings: Settings which can be used to
|
157
|
+
configure the client instance.
|
158
|
+
|
159
|
+
Returns:
|
160
|
+
A KFP client instance.
|
161
|
+
|
162
|
+
Raises:
|
163
|
+
RuntimeError: If the linked Kubernetes connector behaves
|
164
|
+
unexpectedly.
|
165
|
+
"""
|
166
|
+
connector = self.get_connector()
|
167
|
+
client_args = settings.client_args.copy()
|
168
|
+
|
169
|
+
# The kube_context, host and namespace are stack component
|
170
|
+
# configurations that refer to the Kubeflow deployment. We don't want
|
171
|
+
# these overwritten on a run by run basis by user settings
|
172
|
+
client_args["namespace"] = self.config.kubeflow_namespace
|
173
|
+
|
174
|
+
if connector:
|
175
|
+
client = connector.connect()
|
176
|
+
if not isinstance(client, k8s_client.ApiClient):
|
177
|
+
raise RuntimeError(
|
178
|
+
f"Expected a k8s_client.ApiClient while trying to use the "
|
179
|
+
f"linked connector, but got {type(client)}."
|
180
|
+
)
|
181
|
+
return KubeClientKFPClient(
|
182
|
+
client=client,
|
183
|
+
**client_args,
|
184
|
+
)
|
185
|
+
|
186
|
+
elif self.config.kubernetes_context:
|
187
|
+
client_args["kube_context"] = self.config.kubernetes_context
|
188
|
+
|
189
|
+
elif self.config.kubeflow_hostname:
|
190
|
+
client_args["host"] = self.config.kubeflow_hostname
|
191
|
+
|
192
|
+
# Handle username and password, ignore the case if one is passed and
|
193
|
+
# not the other. Also do not attempt to get cookie if cookie is
|
194
|
+
# already passed in client_args
|
195
|
+
if settings.client_username and settings.client_password:
|
196
|
+
# If cookie is already set, then ignore
|
197
|
+
if "cookie" in client_args:
|
198
|
+
logger.warning(
|
199
|
+
"Cookie already set in `client_args`, ignoring "
|
200
|
+
"`client_username` and `client_password`..."
|
201
|
+
)
|
202
|
+
else:
|
203
|
+
session_cookie = self._get_session_cookie(
|
204
|
+
username=settings.client_username,
|
205
|
+
password=settings.client_password,
|
206
|
+
)
|
207
|
+
|
208
|
+
client_args["cookies"] = session_cookie
|
209
|
+
return KFPClient(**client_args)
|
210
|
+
|
148
211
|
@property
|
149
212
|
def config(self) -> KubeflowOrchestratorConfig:
|
150
213
|
"""Returns the `KubeflowOrchestratorConfig` config.
|
@@ -272,10 +335,7 @@ class KubeflowOrchestrator(ContainerizedOrchestrator):
|
|
272
335
|
f"--skip_local_validations=True'\n"
|
273
336
|
)
|
274
337
|
|
275
|
-
if
|
276
|
-
not self.config.skip_local_validations
|
277
|
-
and not self.config.is_local
|
278
|
-
):
|
338
|
+
if not self.config.is_local:
|
279
339
|
# if the orchestrator is not running in a local k3d cluster,
|
280
340
|
# we cannot have any other local components in our stack,
|
281
341
|
# because we cannot mount the local path into the container.
|
@@ -354,114 +414,49 @@ class KubeflowOrchestrator(ContainerizedOrchestrator):
|
|
354
414
|
"""
|
355
415
|
return os.path.join(self.root_directory, "pipelines")
|
356
416
|
|
357
|
-
def
|
417
|
+
def _create_dynamic_component(
|
358
418
|
self,
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
writes to a local path. Adds some labels to the container_op and applies
|
366
|
-
some functions to ir.
|
419
|
+
image: str,
|
420
|
+
command: List[str],
|
421
|
+
arguments: List[str],
|
422
|
+
component_name: str,
|
423
|
+
) -> dsl.PipelineTask:
|
424
|
+
"""Creates a dynamic container component for a Kubeflow pipeline.
|
367
425
|
|
368
426
|
Args:
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
stack = Client().active_stack
|
375
|
-
|
376
|
-
if self.config.is_local:
|
377
|
-
stack.check_local_paths()
|
378
|
-
|
379
|
-
local_stores_path = GlobalConfiguration().local_stores_path
|
427
|
+
image: The image to use for the component.
|
428
|
+
command: The command to use for the component.
|
429
|
+
arguments: The arguments to use for the component.
|
430
|
+
component_name: The name of the component.
|
380
431
|
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
volumes[local_stores_path] = k8s_client.V1Volume(
|
386
|
-
name="local-stores",
|
387
|
-
host_path=host_path,
|
388
|
-
)
|
389
|
-
logger.debug(
|
390
|
-
"Adding host path volume for the local ZenML stores (path: %s) "
|
391
|
-
"in kubeflow pipelines container.",
|
392
|
-
local_stores_path,
|
393
|
-
)
|
394
|
-
|
395
|
-
if sys.platform == "win32":
|
396
|
-
# File permissions are not checked on Windows. This if clause
|
397
|
-
# prevents mypy from complaining about unused 'type: ignore'
|
398
|
-
# statements
|
399
|
-
pass
|
400
|
-
else:
|
401
|
-
# Run KFP containers in the context of the local UID/GID
|
402
|
-
# to ensure that the local stores can be shared
|
403
|
-
# with the local pipeline runs.
|
404
|
-
container_op.container.security_context = (
|
405
|
-
k8s_client.V1SecurityContext(
|
406
|
-
run_as_user=os.getuid(),
|
407
|
-
run_as_group=os.getgid(),
|
408
|
-
)
|
409
|
-
)
|
410
|
-
logger.debug(
|
411
|
-
"Setting security context UID and GID to local user/group "
|
412
|
-
"in kubeflow pipelines container."
|
413
|
-
)
|
414
|
-
|
415
|
-
container_op.container.add_env_variable(
|
416
|
-
k8s_client.V1EnvVar(
|
417
|
-
name=ENV_ZENML_LOCAL_STORES_PATH,
|
418
|
-
value=local_stores_path,
|
419
|
-
)
|
420
|
-
)
|
421
|
-
|
422
|
-
container_op.add_pvolumes(volumes)
|
432
|
+
Returns:
|
433
|
+
The dynamic container component.
|
434
|
+
"""
|
423
435
|
|
424
|
-
#
|
425
|
-
|
426
|
-
|
436
|
+
@dsl.container_component # type: ignore[misc]
|
437
|
+
def dynamic_container_component() -> dsl.ContainerSpec:
|
438
|
+
"""Dynamic container component.
|
427
439
|
|
428
|
-
|
429
|
-
|
430
|
-
|
440
|
+
Returns:
|
441
|
+
The dynamic container component.
|
442
|
+
"""
|
443
|
+
return dsl.ContainerSpec(
|
444
|
+
image=image,
|
445
|
+
command=command,
|
446
|
+
args=arguments,
|
431
447
|
)
|
432
448
|
|
433
|
-
#
|
434
|
-
|
435
|
-
|
436
|
-
|
449
|
+
# Change the name of the function
|
450
|
+
new_container_spec_func = types.FunctionType(
|
451
|
+
dynamic_container_component.__code__,
|
452
|
+
dynamic_container_component.__globals__,
|
453
|
+
name=component_name,
|
454
|
+
argdefs=dynamic_container_component.__defaults__,
|
455
|
+
closure=dynamic_container_component.__closure__,
|
437
456
|
)
|
438
|
-
|
439
|
-
|
440
|
-
@staticmethod
|
441
|
-
def _configure_container_resources(
|
442
|
-
container_op: dsl.ContainerOp,
|
443
|
-
resource_settings: "ResourceSettings",
|
444
|
-
) -> None:
|
445
|
-
"""Adds resource requirements to the container.
|
457
|
+
pipeline_task = dsl.container_component(new_container_spec_func)
|
446
458
|
|
447
|
-
|
448
|
-
container_op: The kubeflow container operation to configure.
|
449
|
-
resource_settings: The resource settings to use for this
|
450
|
-
container.
|
451
|
-
"""
|
452
|
-
if resource_settings.cpu_count is not None:
|
453
|
-
container_op = container_op.set_cpu_limit(
|
454
|
-
str(resource_settings.cpu_count)
|
455
|
-
)
|
456
|
-
|
457
|
-
if resource_settings.gpu_count is not None:
|
458
|
-
container_op = container_op.set_gpu_limit(
|
459
|
-
resource_settings.gpu_count
|
460
|
-
)
|
461
|
-
|
462
|
-
if resource_settings.memory is not None:
|
463
|
-
memory_limit = resource_settings.memory[:-1]
|
464
|
-
container_op = container_op.set_memory_limit(memory_limit)
|
459
|
+
return pipeline_task
|
465
460
|
|
466
461
|
def prepare_or_run_pipeline(
|
467
462
|
self,
|
@@ -517,89 +512,149 @@ class KubeflowOrchestrator(ContainerizedOrchestrator):
|
|
517
512
|
assert stack.container_registry
|
518
513
|
|
519
514
|
# Create a callable for future compilation into a dsl.Pipeline.
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
This should contain the name of the docker image and configures the
|
524
|
-
entrypoint of the docker image to run the step.
|
515
|
+
orchestrator_run_name = get_orchestrator_run_name(
|
516
|
+
pipeline_name=deployment.pipeline_configuration.name
|
517
|
+
).replace("_", "-")
|
525
518
|
|
526
|
-
|
527
|
-
|
519
|
+
def _create_dynamic_pipeline() -> Any:
|
520
|
+
"""Create a dynamic pipeline including each step.
|
528
521
|
|
529
|
-
|
530
|
-
|
531
|
-
automatically added to a singular dsl.Pipeline instance.
|
522
|
+
Returns:
|
523
|
+
pipeline_func
|
532
524
|
"""
|
533
|
-
|
534
|
-
|
525
|
+
step_name_to_dynamic_component: Dict[str, Any] = {}
|
526
|
+
node_selector_constraint: Optional[Tuple[str, str]] = None
|
535
527
|
|
536
528
|
for step_name, step in deployment.step_configurations.items():
|
537
529
|
image = self.get_image(
|
538
|
-
deployment=deployment,
|
530
|
+
deployment=deployment,
|
531
|
+
step_name=step_name,
|
539
532
|
)
|
540
|
-
|
541
|
-
# The command will be needed to eventually call the python step
|
542
|
-
# within the docker container
|
543
533
|
command = StepEntrypointConfiguration.get_entrypoint_command()
|
544
|
-
|
545
|
-
# The arguments are passed to configure the entrypoint of the
|
546
|
-
# docker container when the step is called.
|
547
534
|
arguments = (
|
548
535
|
StepEntrypointConfiguration.get_entrypoint_arguments(
|
549
|
-
step_name=step_name,
|
536
|
+
step_name=step_name,
|
537
|
+
deployment_id=deployment.id,
|
550
538
|
)
|
551
539
|
)
|
552
|
-
|
553
|
-
|
554
|
-
# contains the name of the step, the name of the docker image,
|
555
|
-
# the command to use to run the step entrypoint
|
556
|
-
# (e.g. `python -m zenml.entrypoints.step_entrypoint`)
|
557
|
-
# and the arguments to be passed along with the command. Find
|
558
|
-
# out more about how these arguments are parsed and used
|
559
|
-
# in the base entrypoint `run()` method.
|
560
|
-
container_op = dsl.ContainerOp(
|
561
|
-
name=step_name,
|
562
|
-
image=image,
|
563
|
-
command=command,
|
564
|
-
arguments=arguments,
|
540
|
+
dynamic_component = self._create_dynamic_component(
|
541
|
+
image, command, arguments, step_name
|
565
542
|
)
|
566
|
-
|
567
|
-
settings = cast(
|
543
|
+
step_settings = cast(
|
568
544
|
KubeflowOrchestratorSettings, self.get_settings(step)
|
569
545
|
)
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
546
|
+
pod_settings = step_settings.pod_settings
|
547
|
+
if pod_settings:
|
548
|
+
if pod_settings.host_ipc:
|
549
|
+
logger.warning(
|
550
|
+
"Host IPC is set to `True` but not supported in "
|
551
|
+
"this orchestrator. Ignoring..."
|
552
|
+
)
|
553
|
+
if pod_settings.affinity:
|
554
|
+
logger.warning(
|
555
|
+
"Affinity is set but not supported in Kubeflow with "
|
556
|
+
"Kubeflow Pipelines 2.x. Ignoring..."
|
557
|
+
)
|
558
|
+
if pod_settings.tolerations:
|
559
|
+
logger.warning(
|
560
|
+
"Tolerations are set but not supported in "
|
561
|
+
"Kubeflow with Kubeflow Pipelines 2.x. Ignoring..."
|
562
|
+
)
|
563
|
+
if pod_settings.volumes:
|
564
|
+
logger.warning(
|
565
|
+
"Volumes are set but not supported in Kubeflow with "
|
566
|
+
"Kubeflow Pipelines 2.x. Ignoring..."
|
567
|
+
)
|
568
|
+
if pod_settings.volume_mounts:
|
569
|
+
logger.warning(
|
570
|
+
"Volume mounts are set but not supported in "
|
571
|
+
"Kubeflow with Kubeflow Pipelines 2.x. Ignoring..."
|
572
|
+
)
|
574
573
|
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
)
|
574
|
+
# apply pod settings
|
575
|
+
if (
|
576
|
+
KFP_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL
|
577
|
+
in pod_settings.node_selectors.keys()
|
578
|
+
):
|
579
|
+
node_selector_constraint = (
|
580
|
+
KFP_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL,
|
581
|
+
pod_settings.node_selectors[
|
582
|
+
KFP_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL
|
583
|
+
],
|
584
|
+
)
|
580
585
|
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
+
step_name_to_dynamic_component[step_name] = dynamic_component
|
587
|
+
|
588
|
+
@dsl.pipeline( # type: ignore[misc]
|
589
|
+
display_name=orchestrator_run_name,
|
590
|
+
)
|
591
|
+
def dynamic_pipeline() -> None:
|
592
|
+
"""Dynamic pipeline."""
|
593
|
+
# iterate through the components one by one
|
594
|
+
# (from step_name_to_dynamic_component)
|
595
|
+
for (
|
596
|
+
component_name,
|
597
|
+
component,
|
598
|
+
) in step_name_to_dynamic_component.items():
|
599
|
+
# for each component, check to see what other steps are
|
600
|
+
# upstream of it
|
601
|
+
step = deployment.step_configurations[component_name]
|
602
|
+
upstream_step_components = [
|
603
|
+
step_name_to_dynamic_component[upstream_step_name]
|
604
|
+
for upstream_step_name in step.spec.upstream_steps
|
605
|
+
]
|
606
|
+
task = (
|
607
|
+
component()
|
608
|
+
.set_display_name(
|
609
|
+
name=component_name,
|
586
610
|
)
|
611
|
+
.set_caching_options(enable_caching=False)
|
612
|
+
.set_env_variable(
|
613
|
+
name=ENV_KFP_RUN_ID,
|
614
|
+
value=dsl.PIPELINE_JOB_NAME_PLACEHOLDER,
|
615
|
+
)
|
616
|
+
.after(*upstream_step_components)
|
617
|
+
)
|
618
|
+
self._configure_container_resources(
|
619
|
+
task,
|
620
|
+
step.config.resource_settings,
|
621
|
+
node_selector_constraint,
|
587
622
|
)
|
588
623
|
|
589
|
-
|
590
|
-
# configure the current container op to run after them
|
591
|
-
for upstream_step_name in step.spec.upstream_steps:
|
592
|
-
upstream_container_op = step_name_to_container_op[
|
593
|
-
upstream_step_name
|
594
|
-
]
|
595
|
-
container_op.after(upstream_container_op)
|
624
|
+
return dynamic_pipeline
|
596
625
|
|
597
|
-
|
598
|
-
|
626
|
+
def _update_yaml_with_environment(
|
627
|
+
yaml_file_path: str, environment: Dict[str, str]
|
628
|
+
) -> None:
|
629
|
+
"""Updates the env section of the steps in the YAML file with the given environment variables.
|
599
630
|
|
600
|
-
|
601
|
-
|
602
|
-
|
631
|
+
Args:
|
632
|
+
yaml_file_path: The path to the YAML file to update.
|
633
|
+
environment: A dictionary of environment variables to add.
|
634
|
+
"""
|
635
|
+
pipeline_definition = yaml_utils.read_yaml(pipeline_file_path)
|
636
|
+
|
637
|
+
# Iterate through each component and add the environment variables
|
638
|
+
for executor in pipeline_definition["deploymentSpec"]["executors"]:
|
639
|
+
if (
|
640
|
+
"container"
|
641
|
+
in pipeline_definition["deploymentSpec"]["executors"][
|
642
|
+
executor
|
643
|
+
]
|
644
|
+
):
|
645
|
+
container = pipeline_definition["deploymentSpec"][
|
646
|
+
"executors"
|
647
|
+
][executor]["container"]
|
648
|
+
if "env" not in container:
|
649
|
+
container["env"] = []
|
650
|
+
for key, value in environment.items():
|
651
|
+
container["env"].append({"name": key, "value": value})
|
652
|
+
|
653
|
+
yaml_utils.write_yaml(pipeline_file_path, pipeline_definition)
|
654
|
+
|
655
|
+
print(
|
656
|
+
f"Updated YAML file with environment variables at {yaml_file_path}"
|
657
|
+
)
|
603
658
|
|
604
659
|
# Get a filepath to use to save the finished yaml to
|
605
660
|
fileio.makedirs(self.pipeline_directory)
|
@@ -608,11 +663,15 @@ class KubeflowOrchestrator(ContainerizedOrchestrator):
|
|
608
663
|
)
|
609
664
|
|
610
665
|
# write the argo pipeline yaml
|
611
|
-
|
612
|
-
pipeline_func=
|
613
|
-
pipeline_name=deployment.pipeline_configuration.name,
|
666
|
+
Compiler().compile(
|
667
|
+
pipeline_func=_create_dynamic_pipeline(),
|
614
668
|
package_path=pipeline_file_path,
|
669
|
+
pipeline_name=orchestrator_run_name,
|
615
670
|
)
|
671
|
+
|
672
|
+
# Let's update the YAML file with the environment variables
|
673
|
+
_update_yaml_with_environment(pipeline_file_path, environment)
|
674
|
+
|
616
675
|
logger.info(
|
617
676
|
"Writing Kubeflow workflow definition to `%s`.", pipeline_file_path
|
618
677
|
)
|
@@ -696,7 +755,7 @@ class KubeflowOrchestrator(ContainerizedOrchestrator):
|
|
696
755
|
else None
|
697
756
|
)
|
698
757
|
result = client.create_recurring_run(
|
699
|
-
experiment_id=experiment.
|
758
|
+
experiment_id=experiment.experiment_id,
|
700
759
|
job_name=run_name,
|
701
760
|
pipeline_package_path=pipeline_file_path,
|
702
761
|
enable_caching=False,
|
@@ -707,7 +766,10 @@ class KubeflowOrchestrator(ContainerizedOrchestrator):
|
|
707
766
|
no_catchup=not deployment.schedule.catchup,
|
708
767
|
)
|
709
768
|
|
710
|
-
logger.info(
|
769
|
+
logger.info(
|
770
|
+
"Started recurring run with ID '%s'.",
|
771
|
+
result.recurring_run_id,
|
772
|
+
)
|
711
773
|
else:
|
712
774
|
logger.info(
|
713
775
|
"No schedule detected. Creating a one-off pipeline run.."
|
@@ -773,72 +835,6 @@ class KubeflowOrchestrator(ContainerizedOrchestrator):
|
|
773
835
|
f"{ENV_KFP_RUN_ID}."
|
774
836
|
)
|
775
837
|
|
776
|
-
def _get_kfp_client(
|
777
|
-
self,
|
778
|
-
settings: KubeflowOrchestratorSettings,
|
779
|
-
) -> kfp.Client:
|
780
|
-
"""Creates a KFP client instance.
|
781
|
-
|
782
|
-
Args:
|
783
|
-
settings: Settings which can be used to
|
784
|
-
configure the client instance.
|
785
|
-
|
786
|
-
Returns:
|
787
|
-
A KFP client instance.
|
788
|
-
|
789
|
-
Raises:
|
790
|
-
RuntimeError: If the linked Kubernetes connector behaves
|
791
|
-
unexpectedly.
|
792
|
-
"""
|
793
|
-
connector = self.get_connector()
|
794
|
-
client_args = settings.client_args.copy()
|
795
|
-
|
796
|
-
# The kube_context, host and namespace are stack component
|
797
|
-
# configurations that refer to the Kubeflow deployment. We don't want
|
798
|
-
# these overwritten on a run by run basis by user settings
|
799
|
-
client_args["namespace"] = self.config.kubeflow_namespace
|
800
|
-
|
801
|
-
if connector:
|
802
|
-
client = connector.connect()
|
803
|
-
if not isinstance(client, k8s_client.ApiClient):
|
804
|
-
raise RuntimeError(
|
805
|
-
f"Expected a k8s_client.ApiClient while trying to use the "
|
806
|
-
f"linked connector, but got {type(client)}."
|
807
|
-
)
|
808
|
-
|
809
|
-
kfp_client = KubeClientKFPClient(
|
810
|
-
client=client,
|
811
|
-
**client_args,
|
812
|
-
)
|
813
|
-
|
814
|
-
return kfp_client
|
815
|
-
|
816
|
-
elif self.config.kubernetes_context:
|
817
|
-
client_args["kube_context"] = self.config.kubernetes_context
|
818
|
-
|
819
|
-
elif self.config.kubeflow_hostname:
|
820
|
-
client_args["host"] = self.config.kubeflow_hostname
|
821
|
-
|
822
|
-
# Handle username and password, ignore the case if one is passed and
|
823
|
-
# not the other. Also do not attempt to get cookie if cookie is
|
824
|
-
# already passed in client_args
|
825
|
-
if settings.client_username and settings.client_password:
|
826
|
-
# If cookie is already set, then ignore
|
827
|
-
if "cookie" in client_args:
|
828
|
-
logger.warning(
|
829
|
-
"Cookie already set in `client_args`, ignoring "
|
830
|
-
"`client_username` and `client_password`..."
|
831
|
-
)
|
832
|
-
else:
|
833
|
-
session_cookie = self._get_session_cookie(
|
834
|
-
username=settings.client_username,
|
835
|
-
password=settings.client_password,
|
836
|
-
)
|
837
|
-
|
838
|
-
client_args["cookies"] = session_cookie
|
839
|
-
|
840
|
-
return kfp.Client(**client_args)
|
841
|
-
|
842
838
|
def _get_session_cookie(self, username: str, password: str) -> str:
|
843
839
|
"""Gets session cookie from username and password.
|
844
840
|
|
@@ -892,7 +888,8 @@ class KubeflowOrchestrator(ContainerizedOrchestrator):
|
|
892
888
|
raise RuntimeError(
|
893
889
|
f"Error while trying to fetch kubeflow cookie: {errh}"
|
894
890
|
)
|
895
|
-
|
891
|
+
|
892
|
+
cookie_dict: Dict[str, str] = session.cookies.get_dict() # type: ignore[no-untyped-call]
|
896
893
|
|
897
894
|
if "authservice_session" not in cookie_dict:
|
898
895
|
raise RuntimeError("Invalid username and/or password!")
|
@@ -924,8 +921,8 @@ class KubeflowOrchestrator(ContainerizedOrchestrator):
|
|
924
921
|
run = Client().get_pipeline_run(run_id)
|
925
922
|
|
926
923
|
settings_key = settings_utils.get_stack_component_setting_key(self)
|
927
|
-
run_settings = self.settings_class.
|
928
|
-
run.config.
|
924
|
+
run_settings = self.settings_class.model_validate(
|
925
|
+
run.config.model_dump().get(settings_key, self.config)
|
929
926
|
)
|
930
927
|
user_namespace = run_settings.user_namespace
|
931
928
|
|
@@ -941,3 +938,56 @@ class KubeflowOrchestrator(ContainerizedOrchestrator):
|
|
941
938
|
return {
|
942
939
|
METADATA_ORCHESTRATOR_URL: Uri(f"{hostname}"),
|
943
940
|
}
|
941
|
+
|
942
|
+
def _configure_container_resources(
|
943
|
+
self,
|
944
|
+
dynamic_component: dsl.PipelineTask,
|
945
|
+
resource_settings: "ResourceSettings",
|
946
|
+
node_selector_constraint: Optional[Tuple[str, str]] = None,
|
947
|
+
) -> dsl.PipelineTask:
|
948
|
+
"""Adds resource requirements to the container.
|
949
|
+
|
950
|
+
Args:
|
951
|
+
dynamic_component: The dynamic component to add the resource
|
952
|
+
settings to.
|
953
|
+
resource_settings: The resource settings to use for this
|
954
|
+
container.
|
955
|
+
node_selector_constraint: Node selector constraint to apply to
|
956
|
+
the container.
|
957
|
+
|
958
|
+
Returns:
|
959
|
+
The dynamic component with the resource settings applied.
|
960
|
+
"""
|
961
|
+
# Set optional CPU, RAM and GPU constraints for the pipeline
|
962
|
+
if resource_settings:
|
963
|
+
cpu_limit = resource_settings.cpu_count or None
|
964
|
+
|
965
|
+
if cpu_limit is not None:
|
966
|
+
dynamic_component = dynamic_component.set_cpu_limit(str(cpu_limit))
|
967
|
+
|
968
|
+
memory_limit = resource_settings.get_memory() or None
|
969
|
+
if memory_limit is not None:
|
970
|
+
dynamic_component = dynamic_component.set_memory_limit(
|
971
|
+
memory_limit
|
972
|
+
)
|
973
|
+
|
974
|
+
gpu_limit = (
|
975
|
+
resource_settings.gpu_count
|
976
|
+
if resource_settings.gpu_count is not None
|
977
|
+
else 0
|
978
|
+
)
|
979
|
+
|
980
|
+
if node_selector_constraint:
|
981
|
+
(constraint_label, value) = node_selector_constraint
|
982
|
+
if gpu_limit is not None and gpu_limit > 0:
|
983
|
+
dynamic_component = (
|
984
|
+
dynamic_component.set_accelerator_type(value)
|
985
|
+
.set_accelerator_limit(gpu_limit)
|
986
|
+
.set_gpu_limit(gpu_limit)
|
987
|
+
)
|
988
|
+
elif constraint_label == "accelerator" and gpu_limit == 0:
|
989
|
+
logger.warning(
|
990
|
+
"GPU limit is set to 0 but a GPU type is specified. Ignoring GPU settings."
|
991
|
+
)
|
992
|
+
|
993
|
+
return dynamic_component
|