Skip to content
Open
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
50 changes: 33 additions & 17 deletions llmops/common/deployment/kubernetes_endpoint.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
This module creates Kubernetes managed endpoint as flow deployment process.
This module creates Kubernetes managed endpoint as flow deployment process if it does not already exist.

Args:
--base_path: Base path of the use case. Where flows, data,
Expand Down Expand Up @@ -27,7 +27,7 @@
from llmops.common.logger import llmops_logger
from llmops.common.experiment_cloud_config import ExperimentCloudConfig

logger = llmops_logger("provision_endpoint")
logger = llmops_logger("kubernetes_endpoint")


def create_kubernetes_endpoint(
Expand All @@ -51,6 +51,8 @@ def create_kubernetes_endpoint(
credential=DefaultAzureCredential(),
)

existing_endpoints = ml_client.online_endpoints.list(local=False)

config_file = open(real_config)
endpoint_config = json.load(config_file)

Expand All @@ -61,21 +63,35 @@ def create_kubernetes_endpoint(
endpoint_desc = elem["ENDPOINT_DESC"]
compute_name = elem["COMPUTE_NAME"]

endpoint = KubernetesOnlineEndpoint(
name=endpoint_name,
description=endpoint_desc,
compute=compute_name,
auth_mode="key",
tags={"build_id": build_id} if build_id else {},
properties={
"enforce_access_to_default_secret_stores": True,
},
)

logger.info(f"Creating endpoint {endpoint.name}")
ml_client.online_endpoints.begin_create_or_update(
endpoint=endpoint
).result()
# See if endpoint with name endpoint_name already exists
endpoint = next(
(
e for e in existing_endpoints
if e.name == endpoint_name
),
None)

if endpoint is None:
endpoint = KubernetesOnlineEndpoint(
name=endpoint_name,
description=endpoint_desc,
compute=compute_name,
auth_mode="key",
tags={"build_id": build_id} if build_id else {},
properties={
"enforce_access_to_default_secret_stores": True,
},
)

logger.info(f"Creating endpoint {endpoint.name}")
ml_client.online_endpoints.begin_create_or_update(
endpoint=endpoint
).result()
else:
logger.info(
f"Skipping create as endpoint"
f"{endpoint.name} already exists"
)

logger.info(f"Obtaining endpoint {endpoint.name} identity")
principal_id = ml_client.online_endpoints.get(
Expand Down
35 changes: 33 additions & 2 deletions tests/test_create_kubernetes_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ def _set_required_env_vars():
monkeypatch.setenv("RESOURCE_GROUP_NAME", "TEST_RESOURCE_GROUP_NAME")
monkeypatch.setenv("WORKSPACE_NAME", "TEST_WORKSPACE_NAME")


def test_create_kubernetes_endpoint():
def test_create_kubernetes_endpoint_when_not_exists():
"""Test create_kubernetes_endpoint."""
env_name = "dev"
endpoint_name = "k8s-test-endpoint"
Expand All @@ -32,6 +31,8 @@ def test_create_kubernetes_endpoint():
# Mock the MLClient
ml_client_instance = Mock()
mock_ml_client.return_value = ml_client_instance
ml_client_instance.online_endpoints.list.return_value = []

# Create the endpoint
create_kubernetes_endpoint(env_name, str(RESOURCE_PATH))

Expand Down Expand Up @@ -61,3 +62,33 @@ def test_create_kubernetes_endpoint():
assert created_endpoint.description == endpoint_description
assert created_endpoint.compute == compute_name
assert created_endpoint.auth_mode == "key"

def test_create_kubernetes_endpoint_when_exists():
"""Test create_kubernetes_endpoint."""
env_name = "dev"
endpoint_name = "k8s-test-endpoint"
with patch(
"llmops.common.deployment.kubernetes_endpoint.MLClient"
) as mock_ml_client:
# Mock the MLClient
ml_client_instance = Mock()
mock_ml_client.return_value = ml_client_instance

mock_endpoint = Mock()
mock_endpoint.name = endpoint_name
ml_client_instance.online_endpoints.list.return_value = [
mock_endpoint
]

# Create the endpoint
create_kubernetes_endpoint(env_name, str(RESOURCE_PATH))

# Assert online_endpoints.begin_create_or_update is called once
create_endpoint_calls = (
ml_client_instance.online_endpoints.begin_create_or_update
)

# Endpoint should not be created if it already exists as it would
# set the traffic to zero for existing deployments and there are
# no properties we need to update on the endpoint
assert create_endpoint_calls.call_count == 0