Skip to content

Commit d9bd1e1

Browse files
authored
Improve code coverage for depployment entity (Azure#39403)
* add unit tests for OnlineDeployment rest to entity conversion * add unit tests for onlinedeployment entity _get_arm_resource_and_params * move unit tests online_deployment_from_rest_object to right class * add unit tests for get arm resource for kubenets deployment * add unit tests for onlinedeployment entity set scale settings * add unit tests for to_dict method * code formatting * change comment to run tests * Update assets.json * Revert "Update assets.json" This reverts commit 3aee0c6. * disable failing tests * disable failing tests * enable failing tests and update recordings * add unit tests for OnlineDeployment merge * fix unit test * add unit tests for to_rest_object * update unit tests for resource settings * update unit tests for resource settings * add unit tests for online deployment settings * add unit tests for batch deployment * code formatting * add unit tests batch endpoint deployment * add unit tests for batch deployment * add unit tests for batch job * add unit tests for batch job * add unit tests for model deployment class * code formatting * remove unwanted tests * add unit tests for pipeline_component_batch_deployment.py * clean json rest response file * clean json rest response file
1 parent 377c15e commit d9bd1e1

14 files changed

+1368
-7
lines changed

sdk/ml/azure-ai-ml/azure/ai/ml/entities/_deployment/online_deployment.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def _from_rest_object(cls, deployment: RestOnlineDeploymentData) -> RestOnlineDe
215215
if deployment.properties.endpoint_compute_type == EndpointComputeType.MANAGED:
216216
return ManagedOnlineDeployment._from_rest_object(deployment)
217217

218-
msg = f"Unsupported online endpoint type {deployment.properties.type}."
218+
msg = f"Unsupported online endpoint type {deployment.properties.endpoint_compute_type}."
219219
raise DeploymentException(
220220
message=msg,
221221
target=ErrorTarget.ONLINE_DEPLOYMENT,

sdk/ml/azure-ai-ml/azure/ai/ml/entities/_deployment/scale_settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def _from_rest_object( # pylint: disable=arguments-renamed
5454
if settings.scale_type == "TargetUtilization":
5555
return TargetUtilizationScaleSettings._from_rest_object(settings)
5656

57-
msg = f"Unsupported online scale setting type {settings.type}."
57+
msg = f"Unsupported online scale setting type {settings.scale_type}."
5858
raise DeploymentException(
5959
message=msg,
6060
target=ErrorTarget.ONLINE_DEPLOYMENT,
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import pytest
2+
3+
from azure.ai.ml.entities import BatchJob
4+
from azure.ai.ml._restclient.v2020_09_01_dataplanepreview.models import BatchJobResource, BatchJob as BatchJobRest
5+
6+
7+
@pytest.mark.unittest
8+
class TestBatchJob:
9+
def test_batch_job_to_dict(self):
10+
batch_job = BatchJob(
11+
id="id",
12+
name="name",
13+
type="type",
14+
status="status",
15+
)
16+
batch_job_dict = batch_job._to_dict()
17+
assert batch_job_dict == {
18+
"id": "id",
19+
"name": "name",
20+
"type": "type",
21+
"status": "status",
22+
}
23+
24+
def test_batch_job_to_rest(self):
25+
batch_jon_rest = BatchJobResource.deserialize(
26+
{"id": "id", "name": "name", "type": "type", "properties": {"status": "status"}}
27+
)
28+
batch_job = BatchJob._from_rest_object(batch_jon_rest)
29+
assert batch_job.id == "id"
30+
assert batch_job.name == "name"
31+
assert batch_job.type == "type"
32+
assert batch_job.status == "status"

sdk/ml/azure-ai-ml/tests/batch_online_common/unittests/test_deployment_entity.py

Lines changed: 804 additions & 5 deletions
Large diffs are not rendered by default.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import pytest
2+
from azure.ai.ml.entities import ModelBatchDeployment
3+
from azure.ai.ml.entities._load_functions import load_model_batch_deployment
4+
from azure.ai.ml.constants._deployment import BatchDeploymentOutputAction
5+
from azure.ai.ml._restclient.v2022_05_01.models import BatchOutputAction
6+
from azure.ai.ml.exceptions import ValidationException
7+
8+
9+
@pytest.mark.unittest
10+
class TestModelBatchDeployment:
11+
MODEL_BATCH_DEPLOYMNET = "./tests/test_configs/deployments/batch/model_batch_deployment.yaml"
12+
13+
def test_to_rest_object(self) -> None:
14+
deployment = load_model_batch_deployment(
15+
TestModelBatchDeployment.MODEL_BATCH_DEPLOYMNET, params_override=[{"endpoint_name": "some-en-name"}]
16+
)
17+
rest_deployment = deployment._to_rest_object(location="eastus")
18+
assert rest_deployment.location == "eastus"
19+
assert rest_deployment.properties.description == deployment.description
20+
assert rest_deployment.properties.environment_id == deployment.environment
21+
assert rest_deployment.properties.model.asset_id.name == "model-1"
22+
assert rest_deployment.properties.code_configuration.code_id == deployment.code_configuration.code
23+
assert (
24+
rest_deployment.properties.code_configuration.scoring_script == deployment.code_configuration.scoring_script
25+
)
26+
assert rest_deployment.properties.output_file_name == deployment.settings.output_file_name
27+
assert str(rest_deployment.properties.output_action) == "BatchOutputAction.APPEND_ROW"
28+
assert rest_deployment.properties.resources.instance_count == deployment.resources.instance_count
29+
assert rest_deployment.properties.retry_settings.max_retries == deployment.settings.retry_settings.max_retries
30+
assert (
31+
rest_deployment.properties.max_concurrency_per_instance == deployment.settings.max_concurrency_per_instance
32+
)
33+
assert rest_deployment.properties.environment_variables == deployment.settings.environment_variables
34+
assert rest_deployment.properties.compute == deployment.compute
35+
assert rest_deployment.properties.properties == deployment.properties
36+
assert rest_deployment.tags == deployment.tags
37+
38+
def test_output_action_yaml_to_rest(self):
39+
assert (
40+
ModelBatchDeployment._yaml_output_action_to_rest_output_action(BatchDeploymentOutputAction.APPEND_ROW)
41+
== BatchOutputAction.APPEND_ROW
42+
)
43+
assert (
44+
ModelBatchDeployment._yaml_output_action_to_rest_output_action(BatchDeploymentOutputAction.SUMMARY_ONLY)
45+
== BatchOutputAction.SUMMARY_ONLY
46+
)
47+
48+
def test_validation_fails_if_output_file_name_and_summary_output_action(self) -> None:
49+
deployment = load_model_batch_deployment(TestModelBatchDeployment.MODEL_BATCH_DEPLOYMNET)
50+
deployment.settings.output_action = BatchDeploymentOutputAction.SUMMARY_ONLY
51+
deployment.settings.output_file_name = "some_file_name"
52+
with pytest.raises(ValidationException) as ex:
53+
deployment._to_rest_object(location="westus")
54+
assert "When output_action is set to summary_only, the output_file_name need not to be specified." == str(
55+
ex.value
56+
)
57+
58+
def test_to_dict(self) -> None:
59+
deployment = load_model_batch_deployment(TestModelBatchDeployment.MODEL_BATCH_DEPLOYMNET)
60+
deployment_dict = deployment._to_dict()
61+
assert deployment_dict["name"] == deployment.name
62+
assert deployment_dict["endpoint_name"] == deployment.endpoint_name
63+
assert deployment_dict["model"]["name"] == deployment.model.name
64+
assert deployment_dict["compute"] == "azureml:cpu-cluster"
65+
assert deployment_dict["resources"]["instance_count"] == deployment.resources.instance_count
66+
assert deployment_dict["settings"]["error_threshold"] == deployment.settings.error_threshold
67+
assert deployment_dict["settings"]["output_action"] == "append_row"
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import pytest
2+
import json
3+
from azure.ai.ml.entities._deployment.pipeline_component_batch_deployment import (
4+
PipelineComponentBatchDeployment,
5+
)
6+
from azure.ai.ml.entities import PipelineComponent
7+
from azure.ai.ml.entities._load_functions import (
8+
load_pipeline_component_batch_deployment,
9+
)
10+
from azure.ai.ml._restclient.v2024_01_01_preview.models import (
11+
BatchDeployment as RestBatchDeployment,
12+
IdAssetReference,
13+
BatchPipelineComponentDeploymentConfiguration as RestBatchPipelineComponentDeploymentConfiguration,
14+
)
15+
from azure.ai.ml._restclient.v2024_01_01_preview.models import (
16+
BatchDeploymentProperties as RestBatchDeploymentProperties,
17+
)
18+
19+
20+
@pytest.mark.unittest
21+
class TestPipelineComponentBatchDeployment:
22+
HELLO_BATCH_DEPLOYMENT = "tests/test_configs/deployments/batch/pipeline_component_batch_deployment.yml"
23+
HELLO_BATCH_DEPLOYMENT_REST = "tests/test_configs/deployments/batch/batch_pipeline_component_rest.json"
24+
25+
def test_to_rest_object(self) -> None:
26+
pipeline_component = load_pipeline_component_batch_deployment(
27+
TestPipelineComponentBatchDeployment.HELLO_BATCH_DEPLOYMENT
28+
)
29+
pipeline_component_rest = pipeline_component._to_rest_object(location="eastus")
30+
assert pipeline_component_rest.properties.deployment_configuration.settings == pipeline_component.settings
31+
assert (
32+
pipeline_component_rest.properties.deployment_configuration.component_id.asset_id
33+
== pipeline_component.component
34+
)
35+
assert pipeline_component_rest.properties.description == pipeline_component.description
36+
assert pipeline_component_rest.tags == pipeline_component.tags
37+
assert pipeline_component_rest.location == "eastus"
38+
39+
def test_to_rest_object_for_component_obj(self) -> None:
40+
pipeline_component = load_pipeline_component_batch_deployment(
41+
TestPipelineComponentBatchDeployment.HELLO_BATCH_DEPLOYMENT
42+
)
43+
44+
pipeline_component.component = PipelineComponent(
45+
id=pipeline_component.component,
46+
name="test_component",
47+
description="component description",
48+
tags={"tag1": "tag_value"},
49+
)
50+
pipeline_component_rest = pipeline_component._to_rest_object(location="eastus")
51+
52+
assert pipeline_component_rest.properties.deployment_configuration.settings == pipeline_component.settings
53+
assert (
54+
pipeline_component_rest.properties.deployment_configuration.component_id.asset_id
55+
== pipeline_component.component.id
56+
)
57+
assert pipeline_component_rest.properties.deployment_configuration.tags == pipeline_component.component.tags
58+
assert (
59+
pipeline_component_rest.properties.deployment_configuration.description
60+
== pipeline_component.component.description
61+
)
62+
assert pipeline_component_rest.properties.description == pipeline_component.description
63+
assert pipeline_component_rest.tags == pipeline_component.tags
64+
assert pipeline_component_rest.location == "eastus"
65+
66+
def test_to_dict(self) -> None:
67+
pipeline_component = load_pipeline_component_batch_deployment(
68+
TestPipelineComponentBatchDeployment.HELLO_BATCH_DEPLOYMENT,
69+
params_override=[{"endpoint_name": "azureml:hello_batch2@latest"}],
70+
)
71+
pipeline_component_dict = pipeline_component._to_dict()
72+
assert pipeline_component_dict["name"] == pipeline_component.name
73+
assert pipeline_component_dict["tags"] == pipeline_component.tags
74+
assert pipeline_component_dict["description"] == pipeline_component.description
75+
assert pipeline_component_dict["endpoint_name"] == "azureml:hello_batch2@latest"
76+
assert pipeline_component_dict["component"] == "azureml:hello_batch@latest"
77+
assert pipeline_component_dict["settings"] == pipeline_component.settings
78+
79+
def test_from_rest_object(self) -> None:
80+
81+
with open(TestPipelineComponentBatchDeployment.HELLO_BATCH_DEPLOYMENT_REST, "r") as file:
82+
pipeline_component_rest = RestBatchDeployment.from_dict(json.load(file))
83+
pipeline_component_rest.properties.additional_properties = {
84+
"deploymentConfiguration": {
85+
"componentId": {"assetId": "azureml:hello_batch@latest"},
86+
"settings": {"componentId": "azureml:hello_batch@latest"},
87+
}
88+
}
89+
pipeline_component_from_rest = PipelineComponentBatchDeployment._from_rest_object(pipeline_component_rest)
90+
assert pipeline_component_from_rest.component == "azureml:hello_batch@latest"
91+
assert (
92+
pipeline_component_from_rest.settings["componentId"]
93+
== pipeline_component_rest.properties.additional_properties["deploymentConfiguration"]["componentId"][
94+
"assetId"
95+
]
96+
)
97+
assert (
98+
pipeline_component_from_rest.component
99+
== pipeline_component_rest.properties.additional_properties["deploymentConfiguration"]["componentId"][
100+
"assetId"
101+
]
102+
)
103+
assert pipeline_component_from_rest.endpoint_name == "achauhan-endpoint-name"
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"id": "/subscriptions/sub-id/resourceGroups/some-res-group/providers/Microsoft.MachineLearningServices/workspaces/some-ws/batchEndpoints/achauhan-endpoint-name/deployments/hello-world-1",
3+
"name": "hello-world-1",
4+
"type": "Microsoft.MachineLearningServices/workspaces/batchEndpoints/deployments",
5+
"properties": {
6+
"description": "some description",
7+
"properties": {
8+
"AzureAsyncOperationUri": "azure-operation"
9+
},
10+
"codeConfiguration": {
11+
"codeId": "/subscriptions/sub-id/resourceGroups/some-rg/providers/Microsoft.MachineLearningServices/workspaces/some-ws/onlineEndpoints/some-endpoint/deployments/blue",
12+
"scoringScript": "score.py"
13+
},
14+
"environmentId": "/subscriptions/sub-id/resourceGroups/some-rg/providers/Microsoft.MachineLearningServices/workspaces/some-ws/onlineEndpoints/some-endpoint/deployments/blue",
15+
"environmentVariables": {},
16+
"compute": "/subscriptions/sub-id/resourceGroups/some-rg/providers/Microsoft.MachineLearningServices/workspaces/some-ws/onlineEndpoints/some-endpoint/deployments/blue",
17+
"errorThreshold": -1,
18+
"retrySettings": {
19+
"maxRetries": 3,
20+
"timeout": "PT30S"
21+
},
22+
"miniBatchSize": 10,
23+
"loggingLevel": "Info",
24+
"model": {
25+
"referenceType": "Id",
26+
"assetId": "/subscriptions/sub-id/resourceGroups/some-rg/providers/Microsoft.MachineLearningServices/workspaces/some-ws/onlineEndpoints/some-endpoint/deployments/blue"
27+
},
28+
"maxConcurrencyPerInstance": 1,
29+
"outputAction": "AppendRow",
30+
"outputFileName": "predictions.csv",
31+
"resources": {
32+
"instanceCount": 1,
33+
"instanceType": null,
34+
"locations": null,
35+
"properties": null
36+
},
37+
"provisioningState": "Succeeded"
38+
},
39+
"systemData": {
40+
"createdAt": "2025-02-01T17:51:56.513702+00:00",
41+
"createdBy": "some-one"
42+
},
43+
"tags": {
44+
"tag1": "value1"
45+
},
46+
"location": "eastus",
47+
"identity": {
48+
"type": "SystemAssigned",
49+
"userAssignedIdentities": {
50+
"key": {
51+
"principalId": "some-principalId",
52+
"clientId": "some-clientId"
53+
}
54+
}
55+
}
56+
}

sdk/ml/azure-ai-ml/tests/test_configs/deployments/batch/batch_deployment_mlflow.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@ max_concurrency_per_instance: 5
1414
compute: "azureml:testCompute"
1515
resources:
1616
instance_count: 2
17+
tags:
18+
tag1: value1
19+
tag2: value2
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"id": "/subscriptions/sub-id/resourceGroups/some-res-group/providers/Microsoft.MachineLearningServices/workspaces/some-ws/batchEndpoints/achauhan-endpoint-name/deployments/hello-world-1",
3+
"name":"hello-batch",
4+
"description":"A batch pipeline component",
5+
"properties":{
6+
"deploymentConfiguration":{
7+
"settings": {
8+
"default_compute": "batch-cluster"
9+
},
10+
"tags": {
11+
"tag1": "value1"
12+
},
13+
"componentId": "azureml:hello_batch@latest"
14+
}
15+
}
16+
17+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
$schema: https://azuremlschemas.azureedge.net/latest/pipelineComponentBatchDeployment.schema.json
2+
name: hello-batch-dpl
3+
endpoint_name: hello-pipeline-batch
4+
description: "Batch deployment description"
5+
type: pipeline
6+
component: azureml:hello_batch@latest
7+
settings:
8+
default_compute: batch-cluster
9+
tags:
10+
tag1: value1
11+
tag2: value2
12+

0 commit comments

Comments
 (0)