Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/api_reference/api_inventory.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ mlflow.client.MlflowClient.create_prompt_version
mlflow.client.MlflowClient.create_registered_model
mlflow.client.MlflowClient.create_run
mlflow.client.MlflowClient.create_webhook
mlflow.client.MlflowClient.create_workspace
mlflow.client.MlflowClient.delete_dataset
mlflow.client.MlflowClient.delete_dataset_tag
mlflow.client.MlflowClient.delete_experiment
Expand All @@ -61,6 +62,7 @@ mlflow.client.MlflowClient.delete_tag
mlflow.client.MlflowClient.delete_trace_tag
mlflow.client.MlflowClient.delete_traces
mlflow.client.MlflowClient.delete_webhook
mlflow.client.MlflowClient.delete_workspace
mlflow.client.MlflowClient.detach_prompt_from_run
mlflow.client.MlflowClient.download_artifacts
mlflow.client.MlflowClient.end_span
Expand All @@ -84,6 +86,8 @@ mlflow.client.MlflowClient.get_registered_model
mlflow.client.MlflowClient.get_run
mlflow.client.MlflowClient.get_trace
mlflow.client.MlflowClient.get_webhook
mlflow.client.MlflowClient.get_workspace
mlflow.client.MlflowClient.get_workspace_store_uri
mlflow.client.MlflowClient.link_prompt_version_to_model
mlflow.client.MlflowClient.link_prompt_version_to_run
mlflow.client.MlflowClient.link_prompt_versions_to_trace
Expand All @@ -92,6 +96,7 @@ mlflow.client.MlflowClient.list_artifacts
mlflow.client.MlflowClient.list_logged_model_artifacts
mlflow.client.MlflowClient.list_logged_prompts
mlflow.client.MlflowClient.list_webhooks
mlflow.client.MlflowClient.list_workspaces
mlflow.client.MlflowClient.load_prompt
mlflow.client.MlflowClient.load_table
mlflow.client.MlflowClient.log_artifact
Expand Down Expand Up @@ -146,6 +151,7 @@ mlflow.client.MlflowClient.update_model_version
mlflow.client.MlflowClient.update_registered_model
mlflow.client.MlflowClient.update_run
mlflow.client.MlflowClient.update_webhook
mlflow.client.MlflowClient.update_workspace
mlflow.config.disable_system_metrics_logging
mlflow.config.enable_async_logging
mlflow.config.enable_system_metrics_logging
Expand Down Expand Up @@ -529,6 +535,10 @@ mlflow.entities.WebhookTestResult
mlflow.entities.WebhookTestResult.from_proto
mlflow.entities.WebhookTestResult.to_proto
mlflow.entities.Workspace
mlflow.entities.Workspace.from_dict
mlflow.entities.Workspace.from_proto
mlflow.entities.Workspace.to_dict
mlflow.entities.Workspace.to_proto
mlflow.entities.assessment.Assessment
mlflow.entities.assessment.Expectation
mlflow.entities.assessment.Feedback
Expand Down
40 changes: 39 additions & 1 deletion mlflow/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@
from mlflow import ai_commands, projects, version
from mlflow.entities import ViewType
from mlflow.entities.lifecycle_stage import LifecycleStage
from mlflow.environment_variables import MLFLOW_EXPERIMENT_ID, MLFLOW_EXPERIMENT_NAME
from mlflow.environment_variables import (
MLFLOW_ENABLE_WORKSPACES,
MLFLOW_EXPERIMENT_ID,
MLFLOW_EXPERIMENT_NAME,
MLFLOW_WORKSPACE_STORE_URI,
)
from mlflow.exceptions import InvalidUrlException, MlflowException
from mlflow.protos.databricks_pb2 import INVALID_PARAMETER_VALUE
from mlflow.store.artifact.artifact_repository_registry import get_artifact_repository
Expand Down Expand Up @@ -458,6 +463,26 @@ def _validate_static_prefix(ctx, param, value):
"Unsupported on Windows."
),
)
@click.option(
"--workspace-store-uri",
envvar=MLFLOW_WORKSPACE_STORE_URI.name,
metavar="URI",
default=None,
help=(
"Workspace provider backend URI used for workspace CRUD APIs and request routing. "
"When unspecified, defaults to the backend store URI. This only needs to be specified "
"when using a workspace store plugin leveraging externally managed workspaces (e.g. "
+ "Kubernetes namespaces)."
),
)
@click.option(
"--enable-workspaces",
envvar=MLFLOW_ENABLE_WORKSPACES.name,
is_flag=True,
default=False,
show_default=True,
help="Enable backwards compatible workspace-aware multi-tenancy mode.",
)
def server(
ctx,
backend_store_uri,
Expand All @@ -480,6 +505,8 @@ def server(
app_name,
dev,
uvicorn_opts,
workspace_store_uri,
enable_workspaces,
):
"""
Run the MLflow tracking server with built-in security middleware.
Expand Down Expand Up @@ -525,6 +552,17 @@ def server(
disable_security_middleware=disable_security_middleware,
)

if enable_workspaces:
os.environ[MLFLOW_ENABLE_WORKSPACES.name] = "true"
if workspace_store_uri:
os.environ[MLFLOW_WORKSPACE_STORE_URI.name] = workspace_store_uri
elif workspace_store_uri:
click.echo(
"Ignoring --workspace-store-uri because workspaces are not enabled. "
"Use --enable-workspaces to activate workspace mode.",
err=True,
)

if disable_security_middleware:
os.environ["MLFLOW_SERVER_DISABLE_SECURITY_MIDDLEWARE"] = "true"
else:
Expand Down
22 changes: 22 additions & 0 deletions mlflow/entities/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
from __future__ import annotations

from dataclasses import dataclass
from typing import Any

from mlflow.protos.service_pb2 import Workspace as ProtoWorkspace


@dataclass(frozen=True, slots=True)
Expand All @@ -11,3 +14,22 @@ class Workspace:

name: str
description: str | None = None

def to_dict(self) -> dict[str, str | None]:
return {"name": self.name, "description": self.description}

@classmethod
def from_dict(cls, payload: dict[str, Any]) -> "Workspace":
return cls(name=payload["name"], description=payload.get("description"))

def to_proto(self) -> ProtoWorkspace:
workspace = ProtoWorkspace()
workspace.name = self.name
if self.description is not None:
workspace.description = self.description
return workspace

@classmethod
def from_proto(cls, proto: ProtoWorkspace) -> "Workspace":
description = proto.description if proto.HasField("description") else None
return cls(name=proto.name, description=description)
8 changes: 8 additions & 0 deletions mlflow/environment_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ def get(self):
#: (default: ``None``)
MLFLOW_REGISTRY_URI = _EnvironmentVariable("MLFLOW_REGISTRY_URI", str, None)

#: Specifies the workspace provider backend URI.
#: Defaults to the tracking URI when unset.
MLFLOW_WORKSPACE_STORE_URI = _EnvironmentVariable("MLFLOW_WORKSPACE_STORE_URI", str, None)

#: Specifies the ``dfs_tmpdir`` parameter to use for ``mlflow.spark.save_model``,
#: ``mlflow.spark.log_model`` and ``mlflow.spark.load_model``. See
#: https://www.mlflow.org/docs/latest/python_api/mlflow.spark.html#mlflow.spark.save_model
Expand Down Expand Up @@ -435,6 +439,10 @@ def get(self):
"MLFLOW_ENABLE_DBFS_FUSE_ARTIFACT_REPO", True
)

#: Enables workspace-aware multi-tenancy features on the MLflow server.
#: (default: ``False``)
MLFLOW_ENABLE_WORKSPACES = _BooleanEnvironmentVariable("MLFLOW_ENABLE_WORKSPACES", False)

#: Specifies whether or not to use UC Volume FUSE mount to store artifacts on Databricks
#: (default: ``True``)
MLFLOW_ENABLE_UC_VOLUME_FUSE_ARTIFACT_REPO = _BooleanEnvironmentVariable(
Expand Down
Loading
Loading