From 1f46543ae263d3e6e53e8432771ff2abe816b48e Mon Sep 17 00:00:00 2001 From: William Richard Date: Wed, 4 Apr 2018 16:01:01 -0400 Subject: [PATCH] ECS CPU, memory hard limits and host ports are all optional. http://boto3.readthedocs.io/en/latest/reference/services/ecs.html#ECS.Client.register_task_definition --- moto/ecs/models.py | 8 ++-- tests/test_ecs/test_ecs_boto3.py | 81 ++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/moto/ecs/models.py b/moto/ecs/models.py index 998975650..0c07ce107 100644 --- a/moto/ecs/models.py +++ b/moto/ecs/models.py @@ -502,10 +502,12 @@ class EC2ContainerServiceBackend(BaseBackend): def _calculate_task_resource_requirements(task_definition): resource_requirements = {"CPU": 0, "MEMORY": 0, "PORTS": [], "PORTS_UDP": []} for container_definition in task_definition.container_definitions: - resource_requirements["CPU"] += container_definition.get('cpu') - resource_requirements["MEMORY"] += container_definition.get("memory") + resource_requirements["CPU"] += container_definition.get('cpu', 0) + resource_requirements["MEMORY"] += container_definition.get( + "memory", container_definition.get('memoryReservation')) for port_mapping in container_definition.get("portMappings", []): - resource_requirements["PORTS"].append(port_mapping.get('hostPort')) + if 'hostPort' in port_mapping: + resource_requirements["PORTS"].append(port_mapping.get('hostPort')) return resource_requirements @staticmethod diff --git a/tests/test_ecs/test_ecs_boto3.py b/tests/test_ecs/test_ecs_boto3.py index 5fcc297aa..7f6b835be 100644 --- a/tests/test_ecs/test_ecs_boto3.py +++ b/tests/test_ecs/test_ecs_boto3.py @@ -1229,6 +1229,87 @@ def test_resource_reservation_and_release(): remaining_resources['PORTS'].should.equal(registered_resources['PORTS']) container_instance_description['runningTasksCount'].should.equal(0) +@mock_ec2 +@mock_ecs +def test_resource_reservation_and_release_memory_reservation(): + client = boto3.client('ecs', region_name='us-east-1') + ec2 = boto3.resource('ec2', region_name='us-east-1') + + test_cluster_name = 'test_ecs_cluster' + + _ = client.create_cluster( + clusterName=test_cluster_name + ) + + test_instance = ec2.create_instances( + ImageId="ami-1234abcd", + MinCount=1, + MaxCount=1, + )[0] + + instance_id_document = json.dumps( + ec2_utils.generate_instance_identity_document(test_instance) + ) + + _ = client.register_container_instance( + cluster=test_cluster_name, + instanceIdentityDocument=instance_id_document + ) + + _ = client.register_task_definition( + family='test_ecs_task', + containerDefinitions=[ + { + 'name': 'hello_world', + 'image': 'docker/hello-world:latest', + 'memoryReservation': 400, + 'essential': True, + 'environment': [{ + 'name': 'AWS_ACCESS_KEY_ID', + 'value': 'SOME_ACCESS_KEY' + }], + 'logConfiguration': {'logDriver': 'json-file'}, + 'portMappings': [ + { + 'containerPort': 8080 + } + ] + } + ] + ) + run_response = client.run_task( + cluster='test_ecs_cluster', + overrides={}, + taskDefinition='test_ecs_task', + count=1, + startedBy='moto' + ) + container_instance_arn = run_response['tasks'][0].get('containerInstanceArn') + container_instance_description = client.describe_container_instances( + cluster='test_ecs_cluster', + containerInstances=[container_instance_arn] + )['containerInstances'][0] + remaining_resources, registered_resources = _fetch_container_instance_resources(container_instance_description) + remaining_resources['CPU'].should.equal(registered_resources['CPU']) + remaining_resources['MEMORY'].should.equal(registered_resources['MEMORY'] - 400) + remaining_resources['PORTS'].should.equal(registered_resources['PORTS']) + container_instance_description['runningTasksCount'].should.equal(1) + client.stop_task( + cluster='test_ecs_cluster', + task=run_response['tasks'][0].get('taskArn'), + reason='moto testing' + ) + container_instance_description = client.describe_container_instances( + cluster='test_ecs_cluster', + containerInstances=[container_instance_arn] + )['containerInstances'][0] + remaining_resources, registered_resources = _fetch_container_instance_resources(container_instance_description) + remaining_resources['CPU'].should.equal(registered_resources['CPU']) + remaining_resources['MEMORY'].should.equal(registered_resources['MEMORY']) + remaining_resources['PORTS'].should.equal(registered_resources['PORTS']) + container_instance_description['runningTasksCount'].should.equal(0) + + @mock_ecs @mock_cloudformation