2023-08-08 10:06:51 +00:00
|
|
|
import re
|
2021-04-09 17:54:00 +00:00
|
|
|
|
2023-08-08 10:06:51 +00:00
|
|
|
import boto3
|
|
|
|
import pytest
|
2023-11-30 15:55:51 +00:00
|
|
|
from botocore.exceptions import ClientError
|
2021-04-09 17:54:00 +00:00
|
|
|
|
|
|
|
from moto import mock_cloudformation, mock_sagemaker
|
2022-08-13 09:49:43 +00:00
|
|
|
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
|
2021-04-16 14:23:05 +00:00
|
|
|
|
|
|
|
from .cloudformation_test_configs import (
|
2021-04-17 12:49:46 +00:00
|
|
|
EndpointConfigTestConfig,
|
|
|
|
EndpointTestConfig,
|
2023-11-30 15:55:51 +00:00
|
|
|
ModelTestConfig,
|
|
|
|
NotebookInstanceLifecycleConfigTestConfig,
|
|
|
|
NotebookInstanceTestConfig,
|
2021-04-16 14:23:05 +00:00
|
|
|
)
|
2021-04-09 17:54:00 +00:00
|
|
|
|
|
|
|
|
2021-04-17 12:49:46 +00:00
|
|
|
def _get_stack_outputs(cf_client, stack_name):
|
|
|
|
"""Returns the outputs for the first entry in describe_stacks."""
|
|
|
|
stack_description = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0]
|
|
|
|
return {
|
|
|
|
output["OutputKey"]: output["OutputValue"]
|
|
|
|
for output in stack_description["Outputs"]
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-04-09 17:54:00 +00:00
|
|
|
@mock_cloudformation
|
2021-04-17 12:49:46 +00:00
|
|
|
@mock_sagemaker
|
2021-04-13 11:03:25 +00:00
|
|
|
@pytest.mark.parametrize(
|
2021-04-16 14:23:05 +00:00
|
|
|
"test_config",
|
2021-04-13 11:03:25 +00:00
|
|
|
[
|
2021-04-16 14:23:05 +00:00
|
|
|
NotebookInstanceTestConfig(),
|
|
|
|
NotebookInstanceLifecycleConfigTestConfig(),
|
|
|
|
ModelTestConfig(),
|
2021-04-17 12:49:46 +00:00
|
|
|
EndpointConfigTestConfig(),
|
|
|
|
EndpointTestConfig(),
|
2021-04-13 11:03:25 +00:00
|
|
|
],
|
|
|
|
)
|
2021-04-16 14:23:05 +00:00
|
|
|
def test_sagemaker_cloudformation_create(test_config):
|
2021-04-09 17:54:00 +00:00
|
|
|
cf = boto3.client("cloudformation", region_name="us-east-1")
|
2021-04-17 12:49:46 +00:00
|
|
|
sm = boto3.client("sagemaker", region_name="us-east-1")
|
|
|
|
|
|
|
|
# Utilize test configuration to set-up any mock SageMaker resources
|
|
|
|
test_config.run_setup_procedure(sm)
|
2021-04-16 14:23:05 +00:00
|
|
|
|
2022-11-17 22:41:08 +00:00
|
|
|
stack_name = f"{test_config.resource_name}_stack"
|
2021-04-16 14:23:05 +00:00
|
|
|
cf.create_stack(
|
|
|
|
StackName=stack_name,
|
|
|
|
TemplateBody=test_config.get_cloudformation_template(include_outputs=False),
|
|
|
|
)
|
2021-04-09 17:54:00 +00:00
|
|
|
|
|
|
|
provisioned_resource = cf.list_stack_resources(StackName=stack_name)[
|
|
|
|
"StackResourceSummaries"
|
|
|
|
][0]
|
2023-08-08 10:06:51 +00:00
|
|
|
assert provisioned_resource["LogicalResourceId"] == test_config.resource_name
|
|
|
|
assert len(provisioned_resource["PhysicalResourceId"]) > 0
|
2021-04-09 17:54:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_cloudformation
|
|
|
|
@mock_sagemaker
|
2021-04-13 11:03:25 +00:00
|
|
|
@pytest.mark.parametrize(
|
2021-04-16 14:23:05 +00:00
|
|
|
"test_config",
|
2021-04-13 11:03:25 +00:00
|
|
|
[
|
2021-04-16 14:23:05 +00:00
|
|
|
NotebookInstanceTestConfig(),
|
|
|
|
NotebookInstanceLifecycleConfigTestConfig(),
|
|
|
|
ModelTestConfig(),
|
2021-04-17 12:49:46 +00:00
|
|
|
EndpointConfigTestConfig(),
|
|
|
|
EndpointTestConfig(),
|
2021-04-13 11:03:25 +00:00
|
|
|
],
|
|
|
|
)
|
2021-04-16 14:23:05 +00:00
|
|
|
def test_sagemaker_cloudformation_get_attr(test_config):
|
2021-04-09 17:54:00 +00:00
|
|
|
cf = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
sm = boto3.client("sagemaker", region_name="us-east-1")
|
|
|
|
|
2021-04-17 12:49:46 +00:00
|
|
|
# Utilize test configuration to set-up any mock SageMaker resources
|
|
|
|
test_config.run_setup_procedure(sm)
|
|
|
|
|
2021-04-13 11:03:25 +00:00
|
|
|
# Create stack and get description for output values
|
2022-11-17 22:41:08 +00:00
|
|
|
stack_name = f"{test_config.resource_name}_stack"
|
2021-04-16 14:23:05 +00:00
|
|
|
cf.create_stack(
|
|
|
|
StackName=stack_name, TemplateBody=test_config.get_cloudformation_template()
|
|
|
|
)
|
2021-04-17 12:49:46 +00:00
|
|
|
outputs = _get_stack_outputs(cf, stack_name)
|
2021-04-09 17:54:00 +00:00
|
|
|
|
2021-04-13 11:03:25 +00:00
|
|
|
# Using the describe function, ensure output ARN matches resource ARN
|
2021-04-16 14:23:05 +00:00
|
|
|
resource_description = getattr(sm, test_config.describe_function_name)(
|
|
|
|
**{test_config.name_parameter: outputs["Name"]}
|
2021-04-09 17:54:00 +00:00
|
|
|
)
|
2023-08-08 10:06:51 +00:00
|
|
|
assert outputs["Arn"] == resource_description[test_config.arn_parameter]
|
2021-04-09 17:54:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_cloudformation
|
|
|
|
@mock_sagemaker
|
2021-04-13 11:03:25 +00:00
|
|
|
@pytest.mark.parametrize(
|
2021-04-16 14:23:05 +00:00
|
|
|
"test_config,error_message",
|
2021-04-13 11:03:25 +00:00
|
|
|
[
|
2021-04-16 14:23:05 +00:00
|
|
|
(NotebookInstanceTestConfig(), "RecordNotFound"),
|
2021-04-13 11:03:25 +00:00
|
|
|
(
|
2021-04-16 14:23:05 +00:00
|
|
|
NotebookInstanceLifecycleConfigTestConfig(),
|
2021-04-13 11:03:25 +00:00
|
|
|
"Notebook Instance Lifecycle Config does not exist",
|
|
|
|
),
|
2021-04-16 14:23:05 +00:00
|
|
|
(ModelTestConfig(), "Could not find model"),
|
2021-04-17 12:49:46 +00:00
|
|
|
(EndpointConfigTestConfig(), "Could not find endpoint configuration"),
|
|
|
|
(EndpointTestConfig(), "Could not find endpoint"),
|
2021-04-13 11:03:25 +00:00
|
|
|
],
|
|
|
|
)
|
2021-04-16 14:23:05 +00:00
|
|
|
def test_sagemaker_cloudformation_notebook_instance_delete(test_config, error_message):
|
2021-04-09 17:54:00 +00:00
|
|
|
cf = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
sm = boto3.client("sagemaker", region_name="us-east-1")
|
|
|
|
|
2021-04-17 12:49:46 +00:00
|
|
|
# Utilize test configuration to set-up any mock SageMaker resources
|
|
|
|
test_config.run_setup_procedure(sm)
|
|
|
|
|
2021-04-13 11:03:25 +00:00
|
|
|
# Create stack and verify existence
|
2022-11-17 22:41:08 +00:00
|
|
|
stack_name = f"{test_config.resource_name}_stack"
|
2021-04-16 14:23:05 +00:00
|
|
|
cf.create_stack(
|
|
|
|
StackName=stack_name, TemplateBody=test_config.get_cloudformation_template()
|
|
|
|
)
|
2021-04-17 12:49:46 +00:00
|
|
|
outputs = _get_stack_outputs(cf, stack_name)
|
|
|
|
|
2021-04-16 14:23:05 +00:00
|
|
|
resource_description = getattr(sm, test_config.describe_function_name)(
|
|
|
|
**{test_config.name_parameter: outputs["Name"]}
|
2021-04-09 17:54:00 +00:00
|
|
|
)
|
2023-08-08 10:06:51 +00:00
|
|
|
assert outputs["Arn"] == resource_description[test_config.arn_parameter]
|
2021-04-09 17:54:00 +00:00
|
|
|
|
2021-04-13 11:03:25 +00:00
|
|
|
# Delete the stack and verify resource has also been deleted
|
2021-04-09 17:54:00 +00:00
|
|
|
cf.delete_stack(StackName=stack_name)
|
|
|
|
with pytest.raises(ClientError) as ce:
|
2021-04-16 14:23:05 +00:00
|
|
|
getattr(sm, test_config.describe_function_name)(
|
|
|
|
**{test_config.name_parameter: outputs["Name"]}
|
|
|
|
)
|
2023-08-08 10:06:51 +00:00
|
|
|
assert error_message in ce.value.response["Error"]["Message"]
|
2021-04-09 17:54:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_cloudformation
|
|
|
|
@mock_sagemaker
|
|
|
|
def test_sagemaker_cloudformation_notebook_instance_update():
|
|
|
|
cf = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
sm = boto3.client("sagemaker", region_name="us-east-1")
|
|
|
|
|
2021-04-16 14:23:05 +00:00
|
|
|
test_config = NotebookInstanceTestConfig()
|
|
|
|
|
2021-04-17 12:49:46 +00:00
|
|
|
# Set up template for stack with two different instance types
|
2022-11-17 22:41:08 +00:00
|
|
|
stack_name = f"{test_config.resource_name}_stack"
|
2021-04-09 17:54:00 +00:00
|
|
|
initial_instance_type = "ml.c4.xlarge"
|
|
|
|
updated_instance_type = "ml.c4.4xlarge"
|
2021-04-16 14:23:05 +00:00
|
|
|
initial_template_json = test_config.get_cloudformation_template(
|
2021-04-09 17:54:00 +00:00
|
|
|
instance_type=initial_instance_type
|
|
|
|
)
|
2021-04-16 14:23:05 +00:00
|
|
|
updated_template_json = test_config.get_cloudformation_template(
|
2021-04-09 17:54:00 +00:00
|
|
|
instance_type=updated_instance_type
|
|
|
|
)
|
|
|
|
|
|
|
|
# Create stack with initial template and check attributes
|
|
|
|
cf.create_stack(StackName=stack_name, TemplateBody=initial_template_json)
|
2021-04-17 12:49:46 +00:00
|
|
|
outputs = _get_stack_outputs(cf, stack_name)
|
|
|
|
|
2021-04-13 11:03:25 +00:00
|
|
|
initial_notebook_name = outputs["Name"]
|
2021-04-16 14:23:05 +00:00
|
|
|
resource_description = getattr(sm, test_config.describe_function_name)(
|
|
|
|
**{test_config.name_parameter: initial_notebook_name}
|
2021-04-09 17:54:00 +00:00
|
|
|
)
|
2023-08-08 10:06:51 +00:00
|
|
|
assert initial_instance_type == resource_description["InstanceType"]
|
2021-04-09 17:54:00 +00:00
|
|
|
|
2021-04-17 12:49:46 +00:00
|
|
|
# Update stack and check attributes
|
2021-04-09 17:54:00 +00:00
|
|
|
cf.update_stack(StackName=stack_name, TemplateBody=updated_template_json)
|
2021-04-17 12:49:46 +00:00
|
|
|
outputs = _get_stack_outputs(cf, stack_name)
|
|
|
|
|
2021-04-13 11:03:25 +00:00
|
|
|
updated_notebook_name = outputs["Name"]
|
2023-08-08 10:06:51 +00:00
|
|
|
assert updated_notebook_name == initial_notebook_name
|
2021-04-09 17:54:00 +00:00
|
|
|
|
2021-04-16 14:23:05 +00:00
|
|
|
resource_description = getattr(sm, test_config.describe_function_name)(
|
|
|
|
**{test_config.name_parameter: updated_notebook_name}
|
2021-04-09 17:54:00 +00:00
|
|
|
)
|
2023-08-08 10:06:51 +00:00
|
|
|
assert updated_instance_type == resource_description["InstanceType"]
|
2021-04-13 11:03:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_cloudformation
|
|
|
|
@mock_sagemaker
|
|
|
|
def test_sagemaker_cloudformation_notebook_instance_lifecycle_config_update():
|
|
|
|
cf = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
sm = boto3.client("sagemaker", region_name="us-east-1")
|
|
|
|
|
2021-04-16 14:23:05 +00:00
|
|
|
test_config = NotebookInstanceLifecycleConfigTestConfig()
|
|
|
|
|
2021-04-17 12:49:46 +00:00
|
|
|
# Set up template for stack with two different OnCreate scripts
|
2022-11-17 22:41:08 +00:00
|
|
|
stack_name = f"{test_config.resource_name}_stack"
|
2021-04-13 11:03:25 +00:00
|
|
|
initial_on_create_script = "echo Hello World"
|
|
|
|
updated_on_create_script = "echo Goodbye World"
|
2021-04-16 14:23:05 +00:00
|
|
|
initial_template_json = test_config.get_cloudformation_template(
|
2021-04-13 11:03:25 +00:00
|
|
|
on_create=initial_on_create_script
|
|
|
|
)
|
2021-04-16 14:23:05 +00:00
|
|
|
updated_template_json = test_config.get_cloudformation_template(
|
2021-04-13 11:03:25 +00:00
|
|
|
on_create=updated_on_create_script
|
|
|
|
)
|
|
|
|
|
|
|
|
# Create stack with initial template and check attributes
|
|
|
|
cf.create_stack(StackName=stack_name, TemplateBody=initial_template_json)
|
2021-04-17 12:49:46 +00:00
|
|
|
outputs = _get_stack_outputs(cf, stack_name)
|
|
|
|
|
2021-04-13 11:03:25 +00:00
|
|
|
initial_config_name = outputs["Name"]
|
2021-04-16 14:23:05 +00:00
|
|
|
resource_description = getattr(sm, test_config.describe_function_name)(
|
|
|
|
**{test_config.name_parameter: initial_config_name}
|
2021-04-13 11:03:25 +00:00
|
|
|
)
|
2023-08-08 10:06:51 +00:00
|
|
|
assert len(resource_description["OnCreate"]) == 1
|
|
|
|
assert initial_on_create_script == resource_description["OnCreate"][0]["Content"]
|
2021-04-13 11:03:25 +00:00
|
|
|
|
2021-04-17 12:49:46 +00:00
|
|
|
# Update stack and check attributes
|
2021-04-13 11:03:25 +00:00
|
|
|
cf.update_stack(StackName=stack_name, TemplateBody=updated_template_json)
|
2021-04-17 12:49:46 +00:00
|
|
|
outputs = _get_stack_outputs(cf, stack_name)
|
|
|
|
|
2021-04-13 11:03:25 +00:00
|
|
|
updated_config_name = outputs["Name"]
|
2023-08-08 10:06:51 +00:00
|
|
|
assert updated_config_name == initial_config_name
|
2021-04-13 11:03:25 +00:00
|
|
|
|
2021-04-16 14:23:05 +00:00
|
|
|
resource_description = getattr(sm, test_config.describe_function_name)(
|
|
|
|
**{test_config.name_parameter: updated_config_name}
|
2021-04-13 11:03:25 +00:00
|
|
|
)
|
2023-08-08 10:06:51 +00:00
|
|
|
assert len(resource_description["OnCreate"]) == 1
|
|
|
|
assert updated_on_create_script == resource_description["OnCreate"][0]["Content"]
|
2021-04-16 14:23:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_cloudformation
|
|
|
|
@mock_sagemaker
|
|
|
|
def test_sagemaker_cloudformation_model_update():
|
|
|
|
cf = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
sm = boto3.client("sagemaker", region_name="us-east-1")
|
|
|
|
|
|
|
|
test_config = ModelTestConfig()
|
|
|
|
|
2021-04-17 12:49:46 +00:00
|
|
|
# Set up template for stack with two different image versions
|
2022-11-17 22:41:08 +00:00
|
|
|
stack_name = f"{test_config.resource_name}_stack"
|
2021-04-16 14:23:05 +00:00
|
|
|
image = "404615174143.dkr.ecr.us-east-2.amazonaws.com/kmeans:{}"
|
|
|
|
initial_image_version = 1
|
|
|
|
updated_image_version = 2
|
|
|
|
initial_template_json = test_config.get_cloudformation_template(
|
|
|
|
image=image.format(initial_image_version)
|
|
|
|
)
|
|
|
|
updated_template_json = test_config.get_cloudformation_template(
|
|
|
|
image=image.format(updated_image_version)
|
|
|
|
)
|
|
|
|
|
|
|
|
# Create stack with initial template and check attributes
|
|
|
|
cf.create_stack(StackName=stack_name, TemplateBody=initial_template_json)
|
2021-04-17 12:49:46 +00:00
|
|
|
outputs = _get_stack_outputs(cf, stack_name)
|
|
|
|
|
|
|
|
initial_model_name = outputs["Name"]
|
2021-04-16 14:23:05 +00:00
|
|
|
resource_description = getattr(sm, test_config.describe_function_name)(
|
2021-04-17 12:49:46 +00:00
|
|
|
**{test_config.name_parameter: initial_model_name}
|
2021-04-16 14:23:05 +00:00
|
|
|
)
|
2023-08-08 10:06:51 +00:00
|
|
|
assert resource_description["PrimaryContainer"]["Image"] == (
|
2021-04-16 14:23:05 +00:00
|
|
|
image.format(initial_image_version)
|
|
|
|
)
|
|
|
|
|
2021-04-17 12:49:46 +00:00
|
|
|
# Update stack and check attributes
|
2021-04-16 14:23:05 +00:00
|
|
|
cf.update_stack(StackName=stack_name, TemplateBody=updated_template_json)
|
2021-04-17 12:49:46 +00:00
|
|
|
outputs = _get_stack_outputs(cf, stack_name)
|
|
|
|
|
|
|
|
updated_model_name = outputs["Name"]
|
2023-08-08 10:06:51 +00:00
|
|
|
assert updated_model_name != initial_model_name
|
2021-04-16 14:23:05 +00:00
|
|
|
|
|
|
|
resource_description = getattr(sm, test_config.describe_function_name)(
|
2021-04-17 12:49:46 +00:00
|
|
|
**{test_config.name_parameter: updated_model_name}
|
2021-04-16 14:23:05 +00:00
|
|
|
)
|
2023-08-08 10:06:51 +00:00
|
|
|
assert resource_description["PrimaryContainer"]["Image"] == (
|
2021-04-16 14:23:05 +00:00
|
|
|
image.format(updated_image_version)
|
2021-04-13 11:03:25 +00:00
|
|
|
)
|
2021-04-17 12:49:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_cloudformation
|
|
|
|
@mock_sagemaker
|
|
|
|
def test_sagemaker_cloudformation_endpoint_config_update():
|
|
|
|
cf = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
sm = boto3.client("sagemaker", region_name="us-east-1")
|
|
|
|
|
|
|
|
test_config = EndpointConfigTestConfig()
|
|
|
|
|
|
|
|
# Utilize test configuration to set-up any mock SageMaker resources
|
|
|
|
test_config.run_setup_procedure(sm)
|
|
|
|
|
|
|
|
# Set up template for stack with two different production variant counts
|
2022-11-17 22:41:08 +00:00
|
|
|
stack_name = f"{test_config.resource_name}_stack"
|
2021-04-17 12:49:46 +00:00
|
|
|
initial_num_production_variants = 1
|
|
|
|
updated_num_production_variants = 2
|
|
|
|
initial_template_json = test_config.get_cloudformation_template(
|
|
|
|
num_production_variants=initial_num_production_variants
|
|
|
|
)
|
|
|
|
updated_template_json = test_config.get_cloudformation_template(
|
|
|
|
num_production_variants=updated_num_production_variants
|
|
|
|
)
|
|
|
|
|
|
|
|
# Create stack with initial template and check attributes
|
|
|
|
cf.create_stack(StackName=stack_name, TemplateBody=initial_template_json)
|
|
|
|
outputs = _get_stack_outputs(cf, stack_name)
|
|
|
|
|
|
|
|
initial_endpoint_config_name = outputs["Name"]
|
|
|
|
resource_description = getattr(sm, test_config.describe_function_name)(
|
|
|
|
**{test_config.name_parameter: initial_endpoint_config_name}
|
|
|
|
)
|
2023-08-08 10:06:51 +00:00
|
|
|
assert len(resource_description["ProductionVariants"]) == (
|
2021-04-17 12:49:46 +00:00
|
|
|
initial_num_production_variants
|
|
|
|
)
|
|
|
|
|
|
|
|
# Update stack and check attributes
|
|
|
|
cf.update_stack(StackName=stack_name, TemplateBody=updated_template_json)
|
|
|
|
outputs = _get_stack_outputs(cf, stack_name)
|
|
|
|
|
|
|
|
updated_endpoint_config_name = outputs["Name"]
|
2023-08-08 10:06:51 +00:00
|
|
|
assert updated_endpoint_config_name != initial_endpoint_config_name
|
2021-04-17 12:49:46 +00:00
|
|
|
|
|
|
|
resource_description = getattr(sm, test_config.describe_function_name)(
|
|
|
|
**{test_config.name_parameter: updated_endpoint_config_name}
|
|
|
|
)
|
2023-08-08 10:06:51 +00:00
|
|
|
assert len(resource_description["ProductionVariants"]) == (
|
2021-04-17 12:49:46 +00:00
|
|
|
updated_num_production_variants
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_cloudformation
|
|
|
|
@mock_sagemaker
|
|
|
|
def test_sagemaker_cloudformation_endpoint_update():
|
|
|
|
cf = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
sm = boto3.client("sagemaker", region_name="us-east-1")
|
|
|
|
|
|
|
|
test_config = EndpointTestConfig()
|
|
|
|
|
|
|
|
# Set up template for stack with two different endpoint config names
|
2022-11-17 22:41:08 +00:00
|
|
|
stack_name = f"{test_config.resource_name}_stack"
|
2021-04-17 12:49:46 +00:00
|
|
|
initial_endpoint_config_name = test_config.resource_name
|
|
|
|
updated_endpoint_config_name = "updated-endpoint-config-name"
|
|
|
|
initial_template_json = test_config.get_cloudformation_template(
|
|
|
|
endpoint_config_name=initial_endpoint_config_name
|
|
|
|
)
|
|
|
|
updated_template_json = test_config.get_cloudformation_template(
|
|
|
|
endpoint_config_name=updated_endpoint_config_name
|
|
|
|
)
|
|
|
|
|
|
|
|
# Create SM resources and stack with initial template and check attributes
|
|
|
|
sm.create_model(
|
|
|
|
ModelName=initial_endpoint_config_name,
|
2022-11-17 22:41:08 +00:00
|
|
|
ExecutionRoleArn=f"arn:aws:iam::{ACCOUNT_ID}:role/FakeRole",
|
2021-04-17 12:49:46 +00:00
|
|
|
PrimaryContainer={
|
|
|
|
"Image": "404615174143.dkr.ecr.us-east-2.amazonaws.com/linear-learner:1",
|
|
|
|
},
|
|
|
|
)
|
|
|
|
sm.create_endpoint_config(
|
|
|
|
EndpointConfigName=initial_endpoint_config_name,
|
|
|
|
ProductionVariants=[
|
|
|
|
{
|
|
|
|
"InitialInstanceCount": 1,
|
|
|
|
"InitialVariantWeight": 1,
|
|
|
|
"InstanceType": "ml.c4.xlarge",
|
|
|
|
"ModelName": initial_endpoint_config_name,
|
|
|
|
"VariantName": "variant-name-1",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
)
|
|
|
|
cf.create_stack(StackName=stack_name, TemplateBody=initial_template_json)
|
|
|
|
outputs = _get_stack_outputs(cf, stack_name)
|
|
|
|
|
|
|
|
initial_endpoint_name = outputs["Name"]
|
|
|
|
resource_description = getattr(sm, test_config.describe_function_name)(
|
|
|
|
**{test_config.name_parameter: initial_endpoint_name}
|
|
|
|
)
|
2023-08-08 10:06:51 +00:00
|
|
|
assert re.match(
|
|
|
|
initial_endpoint_config_name, resource_description["EndpointConfigName"]
|
2021-04-17 12:49:46 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
# Create additional SM resources and update stack
|
|
|
|
sm.create_model(
|
|
|
|
ModelName=updated_endpoint_config_name,
|
2022-11-17 22:41:08 +00:00
|
|
|
ExecutionRoleArn=f"arn:aws:iam::{ACCOUNT_ID}:role/FakeRole",
|
2021-04-17 12:49:46 +00:00
|
|
|
PrimaryContainer={
|
|
|
|
"Image": "404615174143.dkr.ecr.us-east-2.amazonaws.com/linear-learner:1",
|
|
|
|
},
|
|
|
|
)
|
|
|
|
sm.create_endpoint_config(
|
|
|
|
EndpointConfigName=updated_endpoint_config_name,
|
|
|
|
ProductionVariants=[
|
|
|
|
{
|
|
|
|
"InitialInstanceCount": 1,
|
|
|
|
"InitialVariantWeight": 1,
|
|
|
|
"InstanceType": "ml.c4.xlarge",
|
|
|
|
"ModelName": updated_endpoint_config_name,
|
|
|
|
"VariantName": "variant-name-1",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
)
|
|
|
|
cf.update_stack(StackName=stack_name, TemplateBody=updated_template_json)
|
|
|
|
outputs = _get_stack_outputs(cf, stack_name)
|
|
|
|
|
|
|
|
updated_endpoint_name = outputs["Name"]
|
2023-08-08 10:06:51 +00:00
|
|
|
assert updated_endpoint_name == initial_endpoint_name
|
2021-04-17 12:49:46 +00:00
|
|
|
|
|
|
|
resource_description = getattr(sm, test_config.describe_function_name)(
|
|
|
|
**{test_config.name_parameter: updated_endpoint_name}
|
|
|
|
)
|
2023-08-08 10:06:51 +00:00
|
|
|
assert re.match(
|
|
|
|
updated_endpoint_config_name, resource_description["EndpointConfigName"]
|
2021-04-17 12:49:46 +00:00
|
|
|
)
|