diff --git a/moto/ecs/models.py b/moto/ecs/models.py index c256d940f338..302fa2efd271 100644 --- a/moto/ecs/models.py +++ b/moto/ecs/models.py @@ -299,10 +299,14 @@ def create_from_cloudformation_json( # type: ignore[misc] properties.get("ContainerDefinitions", []), pascal_to_camelcase ) volumes = remap_nested_keys(properties.get("Volumes", []), pascal_to_camelcase) + memory = properties.get("Memory") ecs_backend = ecs_backends[account_id][region_name] return ecs_backend.register_task_definition( - family=family, container_definitions=container_definitions, volumes=volumes + family=family, + container_definitions=container_definitions, + volumes=volumes, + memory=memory, ) @classmethod @@ -320,6 +324,7 @@ def update_from_cloudformation_json( # type: ignore[misc] ) container_definitions = properties["ContainerDefinitions"] volumes = properties.get("Volumes") + memory = properties.get("Memory") if ( original_resource.family != family or original_resource.container_definitions != container_definitions @@ -333,6 +338,7 @@ def update_from_cloudformation_json( # type: ignore[misc] family=family, container_definitions=container_definitions, volumes=volumes, + memory=memory, ) else: # no-op when nothing changed between old and new resources diff --git a/tests/test_ecs/test_ecs_cloudformation.py b/tests/test_ecs/test_ecs_cloudformation.py index 292bb3d60c1c..6617b937787a 100644 --- a/tests/test_ecs/test_ecs_cloudformation.py +++ b/tests/test_ecs/test_ecs_cloudformation.py @@ -2,6 +2,7 @@ from copy import deepcopy import boto3 +import pytest from moto import mock_aws from moto.core.utils import pascal_to_camelcase, remap_nested_keys @@ -366,3 +367,79 @@ def test_create_task_definition_through_cloudformation(): assert task_definition["volumes"] == expected_properties["volumes"] for key, value in expected_properties["containerDefinitions"][0].items(): assert task_definition["containerDefinitions"][0][key] == value + + +@mock_aws +def test_cloudformation_container_definition_validation(): + cfn_conn = boto3.client("cloudformation", region_name="us-west-1") + + # No task memory, no container memory + invalid_definition = { + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "ECS Cluster Test CloudFormation", + "Resources": { + "testTaskDefinition": { + "Type": "AWS::ECS::TaskDefinition", + "Properties": { + "ContainerDefinitions": [ + { + "Name": "ecs-sample", + "Image": "amazon/amazon-ecs-sample", + } + ], + }, + } + }, + } + invalid_json = json.dumps(invalid_definition) + with pytest.raises(Exception): + cfn_conn.create_stack(StackName="invalid-stack", TemplateBody=invalid_json) + + # No task memory, has container memory + valid_definition = { + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "ECS Cluster Test CloudFormation", + "Resources": { + "testTaskDefinition": { + "Type": "AWS::ECS::TaskDefinition", + "Properties": { + "ContainerDefinitions": [ + { + "Name": "ecs-sample", + "Image": "amazon/amazon-ecs-sample", + "Memory": 1024, + } + ], + }, + } + }, + } + valid_json = json.dumps(valid_definition) + name = "valid-stack-container-memory" + cfn_conn.create_stack(StackName=name, TemplateBody=valid_json) + cfn_conn.update_stack(StackName=name, TemplateBody=valid_json) + + # Has task memory, no container memory + valid_definition = { + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "ECS Cluster Test CloudFormation", + "Resources": { + "testTaskDefinition": { + "Type": "AWS::ECS::TaskDefinition", + "Properties": { + "Memory": 1024, + "ContainerDefinitions": [ + { + "Name": "ecs-sample", + "Image": "amazon/amazon-ecs-sample", + } + ], + }, + } + }, + } + + valid_json = json.dumps(valid_definition) + name = "valid-stack-task-memory" + cfn_conn.create_stack(StackName=name, TemplateBody=valid_json) + cfn_conn.update_stack(StackName=name, TemplateBody=valid_json)