From 17584e9aa4b9ffe8c79f5b93659c8e775cf3cacc Mon Sep 17 00:00:00 2001 From: Robert Sheehy Date: Wed, 23 Nov 2016 18:56:12 -0600 Subject: [PATCH] Add ECS Descriptors (#772) * Add support for "DescribeServices" in ecs mock * Add support for "DescribeTaskDefinition" in ecs * Let ecs responses handle baseobject for services --- moto/ecs/models.py | 23 +++++++ moto/ecs/responses.py | 16 +++++ tests/test_ecs/test_ecs_boto3.py | 113 +++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+) diff --git a/moto/ecs/models.py b/moto/ecs/models.py index 38df07047..3a2ec13ff 100644 --- a/moto/ecs/models.py +++ b/moto/ecs/models.py @@ -217,6 +217,20 @@ class EC2ContainerServiceBackend(BaseBackend): task_arns.extend([task_definition.arn for task_definition in task_definition_list]) return task_arns + def describe_task_definition(self, task_definition_str): + task_definition_name = task_definition_str.split('/')[-1] + if ':' in task_definition_name: + family, revision = task_definition_name.split(':') + revision = int(revision) + else: + family = task_definition_name + revision = len(self.task_definitions.get(family, [])) + + if family in self.task_definitions and 0 < revision <= len(self.task_definitions[family]): + return self.task_definitions[family][revision-1] + else: + raise Exception("{0} is not a task_definition".format(task_definition_name)) + def deregister_task_definition(self, task_definition_str): task_definition_name = task_definition_str.split('/')[-1] family, revision = task_definition_name.split(':') @@ -347,6 +361,15 @@ class EC2ContainerServiceBackend(BaseBackend): service_arns.append(self.services[key].arn) return sorted(service_arns) + def describe_services(self, cluster_str, service_names): + cluster_name = cluster_str.split('/')[-1] + services = [] + for service_name in service_names: + cluster_service_pair = '{0}:{1}'.format(cluster_name, service_name) + if cluster_service_pair in self.services: + services.append(self.services[cluster_service_pair]) + return services + def update_service(self, cluster_str, service_name, task_definition_str, desired_count): cluster_name = cluster_str.split('/')[-1] cluster_service_pair = '{0}:{1}'.format(cluster_name, service_name) diff --git a/moto/ecs/responses.py b/moto/ecs/responses.py index 68bfc0bbd..9be5e0b63 100644 --- a/moto/ecs/responses.py +++ b/moto/ecs/responses.py @@ -70,6 +70,13 @@ class EC2ContainerServiceResponse(BaseResponse): #'nextToken': str(uuid.uuid1()) }) + def describe_task_definition(self): + task_definition_str = self._get_param('taskDefinition') + task_definition = self.ecs_backend.describe_task_definition(task_definition_str) + return json.dumps({ + 'taskDefinition': task_definition.response_object + }) + def deregister_task_definition(self): task_definition_str = self._get_param('taskDefinition') task_definition = self.ecs_backend.deregister_task_definition(task_definition_str) @@ -152,6 +159,15 @@ class EC2ContainerServiceResponse(BaseResponse): # 'nextToken': str(uuid.uuid1()) }) + def describe_services(self): + cluster_str = self._get_param('cluster') + service_names = self._get_param('services') + services = self.ecs_backend.describe_services(cluster_str, service_names) + return json.dumps({ + 'services': [service.response_object for service in services], + 'failures': [] + }) + def update_service(self): cluster_str = self._get_param('cluster') service_name = self._get_param('service') diff --git a/tests/test_ecs/test_ecs_boto3.py b/tests/test_ecs/test_ecs_boto3.py index a4e25cf38..921dea69b 100644 --- a/tests/test_ecs/test_ecs_boto3.py +++ b/tests/test_ecs/test_ecs_boto3.py @@ -132,6 +132,67 @@ def test_list_task_definitions(): response['taskDefinitionArns'][1].should.equal('arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:2') +@mock_ecs +def test_describe_task_definition(): + client = boto3.client('ecs', region_name='us-east-1') + _ = client.register_task_definition( + family='test_ecs_task', + containerDefinitions=[ + { + 'name': 'hello_world', + 'image': 'docker/hello-world:latest', + 'cpu': 1024, + 'memory': 400, + 'essential': True, + 'environment': [{ + 'name': 'AWS_ACCESS_KEY_ID', + 'value': 'SOME_ACCESS_KEY' + }], + 'logConfiguration': {'logDriver': 'json-file'} + } + ] + ) + _ = client.register_task_definition( + family='test_ecs_task', + containerDefinitions=[ + { + 'name': 'hello_world2', + 'image': 'docker/hello-world2:latest', + 'cpu': 1024, + 'memory': 400, + 'essential': True, + 'environment': [{ + 'name': 'AWS_ACCESS_KEY_ID', + 'value': 'SOME_ACCESS_KEY2' + }], + 'logConfiguration': {'logDriver': 'json-file'} + } + ] + ) + _ = client.register_task_definition( + family='test_ecs_task', + containerDefinitions=[ + { + 'name': 'hello_world3', + 'image': 'docker/hello-world3:latest', + 'cpu': 1024, + 'memory': 400, + 'essential': True, + 'environment': [{ + 'name': 'AWS_ACCESS_KEY_ID', + 'value': 'SOME_ACCESS_KEY3' + }], + 'logConfiguration': {'logDriver': 'json-file'} + } + ] + ) + response = client.describe_task_definition(taskDefinition='test_ecs_task') + response['taskDefinition']['taskDefinitionArn'].should.equal('arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:3') + + response = client.describe_task_definition(taskDefinition='test_ecs_task:2') + response['taskDefinition']['taskDefinitionArn'].should.equal('arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:2') + + @mock_ecs def test_deregister_task_definition(): client = boto3.client('ecs', region_name='us-east-1') @@ -251,6 +312,58 @@ def test_list_services(): response['serviceArns'][1].should.equal('arn:aws:ecs:us-east-1:012345678910:service/test_ecs_service2') +@mock_ecs +def test_describe_services(): + client = boto3.client('ecs', region_name='us-east-1') + _ = client.create_cluster( + clusterName='test_ecs_cluster' + ) + _ = client.register_task_definition( + family='test_ecs_task', + containerDefinitions=[ + { + 'name': 'hello_world', + 'image': 'docker/hello-world:latest', + 'cpu': 1024, + 'memory': 400, + 'essential': True, + 'environment': [{ + 'name': 'AWS_ACCESS_KEY_ID', + 'value': 'SOME_ACCESS_KEY' + }], + 'logConfiguration': {'logDriver': 'json-file'} + } + ] + ) + _ = client.create_service( + cluster='test_ecs_cluster', + serviceName='test_ecs_service1', + taskDefinition='test_ecs_task', + desiredCount=2 + ) + _ = client.create_service( + cluster='test_ecs_cluster', + serviceName='test_ecs_service2', + taskDefinition='test_ecs_task', + desiredCount=2 + ) + _ = client.create_service( + cluster='test_ecs_cluster', + serviceName='test_ecs_service3', + taskDefinition='test_ecs_task', + desiredCount=2 + ) + response = client.describe_services( + cluster='test_ecs_cluster', + services=['test_ecs_service1', 'test_ecs_service2'] + ) + len(response['services']).should.equal(2) + response['services'][0]['serviceArn'].should.equal('arn:aws:ecs:us-east-1:012345678910:service/test_ecs_service1') + response['services'][0]['serviceName'].should.equal('test_ecs_service1') + response['services'][1]['serviceArn'].should.equal('arn:aws:ecs:us-east-1:012345678910:service/test_ecs_service2') + response['services'][1]['serviceName'].should.equal('test_ecs_service2') + + @mock_ecs def test_update_service(): client = boto3.client('ecs', region_name='us-east-1')