diff --git a/sagemaker-serve/src/sagemaker/serve/model_builder.py b/sagemaker-serve/src/sagemaker/serve/model_builder.py index 10a29fa5f8..4086784a9f 100644 --- a/sagemaker-serve/src/sagemaker/serve/model_builder.py +++ b/sagemaker-serve/src/sagemaker/serve/model_builder.py @@ -4247,25 +4247,20 @@ def _deploy_core_endpoint(self, **kwargs): explainer_config_dict = explainer_config._to_request_dict() if update_endpoint: + # Use a unique config name: the model name is reused across updates, and + # endpoint config names cannot be reused. endpoint_config_name = self.sagemaker_session.create_endpoint_config( - name=self.model_name, - model_name=self.model_name, - initial_instance_count=initial_instance_count, - instance_type=instance_type, - accelerator_type=accelerator_type, + name=unique_name_from_base(self.model_name), + production_variants=[production_variant], tags=tags, kms_key=kms_key, data_capture_config_dict=data_capture_config_dict, - volume_size=volume_size, - model_data_download_timeout=model_data_download_timeout, - container_startup_health_check_timeout=container_startup_health_check_timeout, - explainer_config_dict=explainer_config_dict, async_inference_config_dict=async_inference_config_dict, - serverless_inference_config_dict=serverless_inference_config_dict, - routing_config=routing_config, - inference_ami_version=inference_ami_version, + explainer_config_dict=explainer_config_dict, + ) + self.sagemaker_session.update_endpoint( + self.endpoint_name, endpoint_config_name, wait=wait ) - self.sagemaker_session.update_endpoint(self.endpoint_name, endpoint_config_name) else: self.sagemaker_session.endpoint_from_production_variants( name=self.endpoint_name, diff --git a/sagemaker-serve/tests/unit/test_model_builder_deploy.py b/sagemaker-serve/tests/unit/test_model_builder_deploy.py index d255f42b1e..4be42a5954 100644 --- a/sagemaker-serve/tests/unit/test_model_builder_deploy.py +++ b/sagemaker-serve/tests/unit/test_model_builder_deploy.py @@ -3,6 +3,7 @@ Focuses on increasing coverage for deploy-related functionality. """ +import inspect import unittest from unittest.mock import Mock, patch @@ -10,6 +11,7 @@ from sagemaker.serve.utils.types import ModelServer from sagemaker.serve.mode.function_pointers import Mode from sagemaker.core.resources import Model, Endpoint +from sagemaker.core.helper.session_helper import Session from sagemaker.core.enums import EndpointType from sagemaker.core.inference_config import ( ResourceRequirements, @@ -299,6 +301,41 @@ def test_deploy_core_endpoint_invalid_async_config_raises_error(self): self.assertIn("AsyncInferenceConfig object", str(context.exception)) + @patch("sagemaker.serve.model_builder.Endpoint.get") + def test_deploy_core_endpoint_update_endpoint_creates_config_from_variants( + self, mock_endpoint_get + ): + """update_endpoint=True must call Session.create_endpoint_config with its real signature.""" + builder = ModelBuilder( + model=Mock(), + role_arn="arn:aws:iam::123456789012:role/TestRole", + sagemaker_session=self.mock_session, + ) + builder.built_model = Mock() + builder.model_name = "demo-model" + self.mock_session.create_endpoint_config.return_value = "demo-model-config" + + builder._deploy_core_endpoint( + endpoint_name="demo-endpoint", + instance_type="ml.g5.xlarge", + initial_instance_count=1, + wait=False, + update_endpoint=True, + ) + + call_kwargs = self.mock_session.create_endpoint_config.call_args.kwargs + inspect.signature(Session.create_endpoint_config).bind(None, **call_kwargs) + self.assertTrue(call_kwargs["name"].startswith("demo-model")) + self.assertNotEqual(call_kwargs["name"], "demo-model") + [variant] = call_kwargs["production_variants"] + self.assertEqual(variant["ModelName"], "demo-model") + self.assertEqual(variant["InstanceType"], "ml.g5.xlarge") + self.assertEqual(variant["InitialInstanceCount"], 1) + self.mock_session.update_endpoint.assert_called_once_with( + "demo-endpoint", "demo-model-config", wait=False + ) + self.mock_session.endpoint_from_production_variants.assert_not_called() + def test_deploy_core_endpoint_invalid_serverless_config_raises_error(self): """Test _deploy_core_endpoint raises error for invalid serverless config.""" builder = ModelBuilder(