This also implements the ecs.list_tags_for_resources, although the resources it checks for are currently only the task definitions
		
			
				
	
	
		
			2360 lines
		
	
	
		
			82 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			2360 lines
		
	
	
		
			82 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from __future__ import unicode_literals
 | |
| 
 | |
| from copy import deepcopy
 | |
| 
 | |
| from botocore.exceptions import ClientError
 | |
| import boto3
 | |
| import sure  # noqa
 | |
| import json
 | |
| from moto.ec2 import utils as ec2_utils
 | |
| from uuid import UUID
 | |
| 
 | |
| from moto import mock_cloudformation, mock_elbv2
 | |
| from moto import mock_ecs
 | |
| from moto import mock_ec2
 | |
| from nose.tools import assert_raises
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_create_cluster():
 | |
|     client = boto3.client('ecs', region_name='us-east-1')
 | |
|     response = client.create_cluster(
 | |
|         clusterName='test_ecs_cluster'
 | |
|     )
 | |
|     response['cluster']['clusterName'].should.equal('test_ecs_cluster')
 | |
|     response['cluster']['clusterArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:cluster/test_ecs_cluster')
 | |
|     response['cluster']['status'].should.equal('ACTIVE')
 | |
|     response['cluster']['registeredContainerInstancesCount'].should.equal(0)
 | |
|     response['cluster']['runningTasksCount'].should.equal(0)
 | |
|     response['cluster']['pendingTasksCount'].should.equal(0)
 | |
|     response['cluster']['activeServicesCount'].should.equal(0)
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_list_clusters():
 | |
|     client = boto3.client('ecs', region_name='us-east-1')
 | |
|     _ = client.create_cluster(
 | |
|         clusterName='test_cluster0'
 | |
|     )
 | |
|     _ = client.create_cluster(
 | |
|         clusterName='test_cluster1'
 | |
|     )
 | |
|     response = client.list_clusters()
 | |
|     response['clusterArns'].should.contain(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:cluster/test_cluster0')
 | |
|     response['clusterArns'].should.contain(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:cluster/test_cluster1')
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_describe_clusters():
 | |
|     client = boto3.client('ecs', region_name='us-east-1')
 | |
|     response = client.describe_clusters(clusters=["some-cluster"])
 | |
|     response['failures'].should.contain({
 | |
|         'arn': 'arn:aws:ecs:us-east-1:012345678910:cluster/some-cluster',
 | |
|         'reason': 'MISSING'
 | |
|     })
 | |
| 
 | |
| @mock_ecs
 | |
| def test_delete_cluster():
 | |
|     client = boto3.client('ecs', region_name='us-east-1')
 | |
|     _ = client.create_cluster(
 | |
|         clusterName='test_ecs_cluster'
 | |
|     )
 | |
|     response = client.delete_cluster(cluster='test_ecs_cluster')
 | |
|     response['cluster']['clusterName'].should.equal('test_ecs_cluster')
 | |
|     response['cluster']['clusterArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:cluster/test_ecs_cluster')
 | |
|     response['cluster']['status'].should.equal('ACTIVE')
 | |
|     response['cluster']['registeredContainerInstancesCount'].should.equal(0)
 | |
|     response['cluster']['runningTasksCount'].should.equal(0)
 | |
|     response['cluster']['pendingTasksCount'].should.equal(0)
 | |
|     response['cluster']['activeServicesCount'].should.equal(0)
 | |
| 
 | |
|     response = client.list_clusters()
 | |
|     len(response['clusterArns']).should.equal(0)
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_register_task_definition():
 | |
|     client = boto3.client('ecs', region_name='us-east-1')
 | |
|     response = 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'}
 | |
|             }
 | |
|         ],
 | |
|         tags=[
 | |
|             {'key': 'createdBy', 'value': 'moto-unittest'},
 | |
|             {'key': 'foo', 'value': 'bar'},
 | |
|         ]
 | |
|     )
 | |
|     type(response['taskDefinition']).should.be(dict)
 | |
|     response['taskDefinition']['revision'].should.equal(1)
 | |
|     response['taskDefinition']['taskDefinitionArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:1')
 | |
|     response['taskDefinition']['containerDefinitions'][
 | |
|         0]['name'].should.equal('hello_world')
 | |
|     response['taskDefinition']['containerDefinitions'][0][
 | |
|         'image'].should.equal('docker/hello-world:latest')
 | |
|     response['taskDefinition']['containerDefinitions'][
 | |
|         0]['cpu'].should.equal(1024)
 | |
|     response['taskDefinition']['containerDefinitions'][
 | |
|         0]['memory'].should.equal(400)
 | |
|     response['taskDefinition']['containerDefinitions'][
 | |
|         0]['essential'].should.equal(True)
 | |
|     response['taskDefinition']['containerDefinitions'][0][
 | |
|         'environment'][0]['name'].should.equal('AWS_ACCESS_KEY_ID')
 | |
|     response['taskDefinition']['containerDefinitions'][0][
 | |
|         'environment'][0]['value'].should.equal('SOME_ACCESS_KEY')
 | |
|     response['taskDefinition']['containerDefinitions'][0][
 | |
|         'logConfiguration']['logDriver'].should.equal('json-file')
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_list_task_definitions():
 | |
|     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'}
 | |
|             }
 | |
|         ]
 | |
|     )
 | |
|     response = client.list_task_definitions()
 | |
|     len(response['taskDefinitionArns']).should.equal(2)
 | |
|     response['taskDefinitionArns'][0].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:1')
 | |
|     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')
 | |
|     _ = 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'}
 | |
|             }
 | |
|         ]
 | |
|     )
 | |
|     response = client.deregister_task_definition(
 | |
|         taskDefinition='test_ecs_task:1'
 | |
|     )
 | |
|     type(response['taskDefinition']).should.be(dict)
 | |
|     response['taskDefinition']['taskDefinitionArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:1')
 | |
|     response['taskDefinition']['containerDefinitions'][
 | |
|         0]['name'].should.equal('hello_world')
 | |
|     response['taskDefinition']['containerDefinitions'][0][
 | |
|         'image'].should.equal('docker/hello-world:latest')
 | |
|     response['taskDefinition']['containerDefinitions'][
 | |
|         0]['cpu'].should.equal(1024)
 | |
|     response['taskDefinition']['containerDefinitions'][
 | |
|         0]['memory'].should.equal(400)
 | |
|     response['taskDefinition']['containerDefinitions'][
 | |
|         0]['essential'].should.equal(True)
 | |
|     response['taskDefinition']['containerDefinitions'][0][
 | |
|         'environment'][0]['name'].should.equal('AWS_ACCESS_KEY_ID')
 | |
|     response['taskDefinition']['containerDefinitions'][0][
 | |
|         'environment'][0]['value'].should.equal('SOME_ACCESS_KEY')
 | |
|     response['taskDefinition']['containerDefinitions'][0][
 | |
|         'logConfiguration']['logDriver'].should.equal('json-file')
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_create_service():
 | |
|     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'}
 | |
|             }
 | |
|         ]
 | |
|     )
 | |
|     response = client.create_service(
 | |
|         cluster='test_ecs_cluster',
 | |
|         serviceName='test_ecs_service',
 | |
|         taskDefinition='test_ecs_task',
 | |
|         desiredCount=2
 | |
|     )
 | |
|     response['service']['clusterArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:cluster/test_ecs_cluster')
 | |
|     response['service']['desiredCount'].should.equal(2)
 | |
|     len(response['service']['events']).should.equal(0)
 | |
|     len(response['service']['loadBalancers']).should.equal(0)
 | |
|     response['service']['pendingCount'].should.equal(0)
 | |
|     response['service']['runningCount'].should.equal(0)
 | |
|     response['service']['serviceArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:service/test_ecs_service')
 | |
|     response['service']['serviceName'].should.equal('test_ecs_service')
 | |
|     response['service']['status'].should.equal('ACTIVE')
 | |
|     response['service']['taskDefinition'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:1')
 | |
|     response['service']['schedulingStrategy'].should.equal('REPLICA')
 | |
| 
 | |
| @mock_ecs
 | |
| def test_create_service_scheduling_strategy():
 | |
|     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'}
 | |
|             }
 | |
|         ]
 | |
|     )
 | |
|     response = client.create_service(
 | |
|         cluster='test_ecs_cluster',
 | |
|         serviceName='test_ecs_service',
 | |
|         taskDefinition='test_ecs_task',
 | |
|         desiredCount=2,
 | |
|         schedulingStrategy='DAEMON',
 | |
|     )
 | |
|     response['service']['clusterArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:cluster/test_ecs_cluster')
 | |
|     response['service']['desiredCount'].should.equal(2)
 | |
|     len(response['service']['events']).should.equal(0)
 | |
|     len(response['service']['loadBalancers']).should.equal(0)
 | |
|     response['service']['pendingCount'].should.equal(0)
 | |
|     response['service']['runningCount'].should.equal(0)
 | |
|     response['service']['serviceArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:service/test_ecs_service')
 | |
|     response['service']['serviceName'].should.equal('test_ecs_service')
 | |
|     response['service']['status'].should.equal('ACTIVE')
 | |
|     response['service']['taskDefinition'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:1')
 | |
|     response['service']['schedulingStrategy'].should.equal('DAEMON')
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_list_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',
 | |
|         schedulingStrategy='REPLICA',
 | |
|         desiredCount=2
 | |
|     )
 | |
|     _ = client.create_service(
 | |
|         cluster='test_ecs_cluster',
 | |
|         serviceName='test_ecs_service2',
 | |
|         taskDefinition='test_ecs_task',
 | |
|         schedulingStrategy='DAEMON',
 | |
|         desiredCount=2
 | |
|     )
 | |
|     unfiltered_response = client.list_services(
 | |
|         cluster='test_ecs_cluster'
 | |
|     )
 | |
|     len(unfiltered_response['serviceArns']).should.equal(2)
 | |
|     unfiltered_response['serviceArns'][0].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:service/test_ecs_service1')
 | |
|     unfiltered_response['serviceArns'][1].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:service/test_ecs_service2')
 | |
| 
 | |
|     filtered_response = client.list_services(
 | |
|         cluster='test_ecs_cluster',
 | |
|         schedulingStrategy='REPLICA'
 | |
|     )
 | |
|     len(filtered_response['serviceArns']).should.equal(1)
 | |
|     filtered_response['serviceArns'][0].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:service/test_ecs_service1')
 | |
| 
 | |
| @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',
 | |
|                   'arn:aws:ecs:us-east-1:012345678910:service/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')
 | |
| 
 | |
|     response['services'][0]['deployments'][0]['desiredCount'].should.equal(2)
 | |
|     response['services'][0]['deployments'][0]['pendingCount'].should.equal(2)
 | |
|     response['services'][0]['deployments'][0]['runningCount'].should.equal(0)
 | |
|     response['services'][0]['deployments'][0]['status'].should.equal('PRIMARY')
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_describe_services_scheduling_strategy():
 | |
|     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,
 | |
|         schedulingStrategy='DAEMON'
 | |
|     )
 | |
|     _ = 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',
 | |
|                   'arn:aws:ecs:us-east-1:012345678910:service/test_ecs_service2',
 | |
|                   'test_ecs_service3']
 | |
|     )
 | |
|     len(response['services']).should.equal(3)
 | |
|     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')
 | |
| 
 | |
|     response['services'][0]['deployments'][0]['desiredCount'].should.equal(2)
 | |
|     response['services'][0]['deployments'][0]['pendingCount'].should.equal(2)
 | |
|     response['services'][0]['deployments'][0]['runningCount'].should.equal(0)
 | |
|     response['services'][0]['deployments'][0]['status'].should.equal('PRIMARY')
 | |
| 
 | |
|     response['services'][0]['schedulingStrategy'].should.equal('REPLICA')
 | |
|     response['services'][1]['schedulingStrategy'].should.equal('DAEMON')
 | |
|     response['services'][2]['schedulingStrategy'].should.equal('REPLICA')
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_update_service():
 | |
|     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'}
 | |
|             }
 | |
|         ]
 | |
|     )
 | |
|     response = client.create_service(
 | |
|         cluster='test_ecs_cluster',
 | |
|         serviceName='test_ecs_service',
 | |
|         taskDefinition='test_ecs_task',
 | |
|         desiredCount=2
 | |
|     )
 | |
|     response['service']['desiredCount'].should.equal(2)
 | |
| 
 | |
|     response = client.update_service(
 | |
|         cluster='test_ecs_cluster',
 | |
|         service='test_ecs_service',
 | |
|         taskDefinition='test_ecs_task',
 | |
|         desiredCount=0
 | |
|     )
 | |
|     response['service']['desiredCount'].should.equal(0)
 | |
|     response['service']['schedulingStrategy'].should.equal('REPLICA')
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_update_missing_service():
 | |
|     client = boto3.client('ecs', region_name='us-east-1')
 | |
|     _ = client.create_cluster(
 | |
|         clusterName='test_ecs_cluster'
 | |
|     )
 | |
| 
 | |
|     client.update_service.when.called_with(
 | |
|         cluster='test_ecs_cluster',
 | |
|         service='test_ecs_service',
 | |
|         taskDefinition='test_ecs_task',
 | |
|         desiredCount=0
 | |
|     ).should.throw(ClientError)
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_delete_service():
 | |
|     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_service',
 | |
|         taskDefinition='test_ecs_task',
 | |
|         desiredCount=2
 | |
|     )
 | |
|     _ = client.update_service(
 | |
|         cluster='test_ecs_cluster',
 | |
|         service='test_ecs_service',
 | |
|         desiredCount=0
 | |
|     )
 | |
|     response = client.delete_service(
 | |
|         cluster='test_ecs_cluster',
 | |
|         service='test_ecs_service'
 | |
|     )
 | |
|     response['service']['clusterArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:cluster/test_ecs_cluster')
 | |
|     response['service']['desiredCount'].should.equal(0)
 | |
|     len(response['service']['events']).should.equal(0)
 | |
|     len(response['service']['loadBalancers']).should.equal(0)
 | |
|     response['service']['pendingCount'].should.equal(0)
 | |
|     response['service']['runningCount'].should.equal(0)
 | |
|     response['service']['serviceArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:service/test_ecs_service')
 | |
|     response['service']['serviceName'].should.equal('test_ecs_service')
 | |
|     response['service']['status'].should.equal('ACTIVE')
 | |
|     response['service']['schedulingStrategy'].should.equal('REPLICA')
 | |
|     response['service']['taskDefinition'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:1')
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_update_non_existant_service():
 | |
|     client = boto3.client('ecs', region_name='us-east-1')
 | |
|     try:
 | |
|         client.update_service(
 | |
|             cluster="my-clustet",
 | |
|             service="my-service",
 | |
|             desiredCount=0,
 | |
|         )
 | |
|     except ClientError as exc:
 | |
|         error_code = exc.response['Error']['Code']
 | |
|         error_code.should.equal('ServiceNotFoundException')
 | |
|     else:
 | |
|         raise Exception("Didn't raise ClientError")
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_register_container_instance():
 | |
|     ecs_client = boto3.client('ecs', region_name='us-east-1')
 | |
|     ec2 = boto3.resource('ec2', region_name='us-east-1')
 | |
| 
 | |
|     test_cluster_name = 'test_ecs_cluster'
 | |
| 
 | |
|     _ = ecs_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)
 | |
|     )
 | |
| 
 | |
|     response = ecs_client.register_container_instance(
 | |
|         cluster=test_cluster_name,
 | |
|         instanceIdentityDocument=instance_id_document
 | |
|     )
 | |
| 
 | |
|     response['containerInstance'][
 | |
|         'ec2InstanceId'].should.equal(test_instance.id)
 | |
|     full_arn = response['containerInstance']['containerInstanceArn']
 | |
|     arn_part = full_arn.split('/')
 | |
|     arn_part[0].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:container-instance')
 | |
|     arn_part[1].should.equal(str(UUID(arn_part[1])))
 | |
|     response['containerInstance']['status'].should.equal('ACTIVE')
 | |
|     len(response['containerInstance']['registeredResources']).should.equal(4)
 | |
|     len(response['containerInstance']['remainingResources']).should.equal(4)
 | |
|     response['containerInstance']['agentConnected'].should.equal(True)
 | |
|     response['containerInstance']['versionInfo'][
 | |
|         'agentVersion'].should.equal('1.0.0')
 | |
|     response['containerInstance']['versionInfo'][
 | |
|         'agentHash'].should.equal('4023248')
 | |
|     response['containerInstance']['versionInfo'][
 | |
|         'dockerVersion'].should.equal('DockerVersion: 1.5.0')
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_deregister_container_instance():
 | |
|     ecs_client = boto3.client('ecs', region_name='us-east-1')
 | |
|     ec2 = boto3.resource('ec2', region_name='us-east-1')
 | |
| 
 | |
|     test_cluster_name = 'test_ecs_cluster'
 | |
| 
 | |
|     _ = ecs_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)
 | |
|     )
 | |
| 
 | |
|     response = ecs_client.register_container_instance(
 | |
|         cluster=test_cluster_name,
 | |
|         instanceIdentityDocument=instance_id_document
 | |
|     )
 | |
|     container_instance_id = response['containerInstance']['containerInstanceArn']
 | |
|     response = ecs_client.deregister_container_instance(
 | |
|         cluster=test_cluster_name,
 | |
|         containerInstance=container_instance_id
 | |
|     )
 | |
|     container_instances_response = ecs_client.list_container_instances(
 | |
|         cluster=test_cluster_name
 | |
|     )
 | |
|     len(container_instances_response['containerInstanceArns']).should.equal(0)
 | |
| 
 | |
|     response = ecs_client.register_container_instance(
 | |
|         cluster=test_cluster_name,
 | |
|         instanceIdentityDocument=instance_id_document
 | |
|     )
 | |
|     container_instance_id = response['containerInstance']['containerInstanceArn']
 | |
|     _ = ecs_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'}
 | |
|             }
 | |
|         ]
 | |
|     )
 | |
| 
 | |
|     response = ecs_client.start_task(
 | |
|         cluster='test_ecs_cluster',
 | |
|         taskDefinition='test_ecs_task',
 | |
|         overrides={},
 | |
|         containerInstances=[container_instance_id],
 | |
|         startedBy='moto'
 | |
|     )
 | |
|     with assert_raises(Exception) as e:
 | |
|         ecs_client.deregister_container_instance(
 | |
|             cluster=test_cluster_name,
 | |
|             containerInstance=container_instance_id
 | |
|         ).should.have.raised(Exception)
 | |
|     container_instances_response = ecs_client.list_container_instances(
 | |
|         cluster=test_cluster_name
 | |
|     )
 | |
|     len(container_instances_response['containerInstanceArns']).should.equal(1)
 | |
|     ecs_client.deregister_container_instance(
 | |
|         cluster=test_cluster_name,
 | |
|         containerInstance=container_instance_id,
 | |
|         force=True
 | |
|     )
 | |
|     container_instances_response = ecs_client.list_container_instances(
 | |
|         cluster=test_cluster_name
 | |
|     )
 | |
|     len(container_instances_response['containerInstanceArns']).should.equal(0)
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_list_container_instances():
 | |
|     ecs_client = boto3.client('ecs', region_name='us-east-1')
 | |
|     ec2 = boto3.resource('ec2', region_name='us-east-1')
 | |
| 
 | |
|     test_cluster_name = 'test_ecs_cluster'
 | |
|     _ = ecs_client.create_cluster(
 | |
|         clusterName=test_cluster_name
 | |
|     )
 | |
| 
 | |
|     instance_to_create = 3
 | |
|     test_instance_arns = []
 | |
|     for i in range(0, instance_to_create):
 | |
|         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)
 | |
|         )
 | |
| 
 | |
|         response = ecs_client.register_container_instance(
 | |
|             cluster=test_cluster_name,
 | |
|             instanceIdentityDocument=instance_id_document)
 | |
| 
 | |
|         test_instance_arns.append(response['containerInstance'][
 | |
|                                       'containerInstanceArn'])
 | |
| 
 | |
|     response = ecs_client.list_container_instances(cluster=test_cluster_name)
 | |
| 
 | |
|     len(response['containerInstanceArns']).should.equal(instance_to_create)
 | |
|     for arn in test_instance_arns:
 | |
|         response['containerInstanceArns'].should.contain(arn)
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_describe_container_instances():
 | |
|     ecs_client = boto3.client('ecs', region_name='us-east-1')
 | |
|     ec2 = boto3.resource('ec2', region_name='us-east-1')
 | |
| 
 | |
|     test_cluster_name = 'test_ecs_cluster'
 | |
|     _ = ecs_client.create_cluster(
 | |
|         clusterName=test_cluster_name
 | |
|     )
 | |
| 
 | |
|     instance_to_create = 3
 | |
|     test_instance_arns = []
 | |
|     for i in range(0, instance_to_create):
 | |
|         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)
 | |
|         )
 | |
| 
 | |
|         response = ecs_client.register_container_instance(
 | |
|             cluster=test_cluster_name,
 | |
|             instanceIdentityDocument=instance_id_document)
 | |
| 
 | |
|         test_instance_arns.append(response['containerInstance'][
 | |
|                                       'containerInstanceArn'])
 | |
| 
 | |
|     test_instance_ids = list(
 | |
|         map((lambda x: x.split('/')[1]), test_instance_arns))
 | |
|     response = ecs_client.describe_container_instances(
 | |
|         cluster=test_cluster_name, containerInstances=test_instance_ids)
 | |
|     len(response['failures']).should.equal(0)
 | |
|     len(response['containerInstances']).should.equal(instance_to_create)
 | |
|     response_arns = [ci['containerInstanceArn']
 | |
|                      for ci in response['containerInstances']]
 | |
|     for arn in test_instance_arns:
 | |
|         response_arns.should.contain(arn)
 | |
|     for instance in response['containerInstances']:
 | |
|         instance.keys().should.contain('runningTasksCount')
 | |
|         instance.keys().should.contain('pendingTasksCount')
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_update_container_instances_state():
 | |
|     ecs_client = boto3.client('ecs', region_name='us-east-1')
 | |
|     ec2 = boto3.resource('ec2', region_name='us-east-1')
 | |
| 
 | |
|     test_cluster_name = 'test_ecs_cluster'
 | |
|     _ = ecs_client.create_cluster(
 | |
|         clusterName=test_cluster_name
 | |
|     )
 | |
| 
 | |
|     instance_to_create = 3
 | |
|     test_instance_arns = []
 | |
|     for i in range(0, instance_to_create):
 | |
|         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)
 | |
|         )
 | |
| 
 | |
|         response = ecs_client.register_container_instance(
 | |
|             cluster=test_cluster_name,
 | |
|             instanceIdentityDocument=instance_id_document)
 | |
| 
 | |
|         test_instance_arns.append(response['containerInstance']['containerInstanceArn'])
 | |
| 
 | |
|     test_instance_ids = list(map((lambda x: x.split('/')[1]), test_instance_arns))
 | |
|     response = ecs_client.update_container_instances_state(cluster=test_cluster_name,
 | |
|                                                            containerInstances=test_instance_ids,
 | |
|                                                            status='DRAINING')
 | |
|     len(response['failures']).should.equal(0)
 | |
|     len(response['containerInstances']).should.equal(instance_to_create)
 | |
|     response_statuses = [ci['status'] for ci in response['containerInstances']]
 | |
|     for status in response_statuses:
 | |
|         status.should.equal('DRAINING')
 | |
|     response = ecs_client.update_container_instances_state(cluster=test_cluster_name,
 | |
|                                                            containerInstances=test_instance_ids,
 | |
|                                                            status='DRAINING')
 | |
|     len(response['failures']).should.equal(0)
 | |
|     len(response['containerInstances']).should.equal(instance_to_create)
 | |
|     response_statuses = [ci['status'] for ci in response['containerInstances']]
 | |
|     for status in response_statuses:
 | |
|         status.should.equal('DRAINING')
 | |
|     response = ecs_client.update_container_instances_state(cluster=test_cluster_name,
 | |
|                                                            containerInstances=test_instance_ids,
 | |
|                                                            status='ACTIVE')
 | |
|     len(response['failures']).should.equal(0)
 | |
|     len(response['containerInstances']).should.equal(instance_to_create)
 | |
|     response_statuses = [ci['status'] for ci in response['containerInstances']]
 | |
|     for status in response_statuses:
 | |
|         status.should.equal('ACTIVE')
 | |
|     ecs_client.update_container_instances_state.when.called_with(cluster=test_cluster_name,
 | |
|                                                                  containerInstances=test_instance_ids,
 | |
|                                                                  status='test_status').should.throw(Exception)
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_update_container_instances_state_by_arn():
 | |
|     ecs_client = boto3.client('ecs', region_name='us-east-1')
 | |
|     ec2 = boto3.resource('ec2', region_name='us-east-1')
 | |
| 
 | |
|     test_cluster_name = 'test_ecs_cluster'
 | |
|     _ = ecs_client.create_cluster(
 | |
|         clusterName=test_cluster_name
 | |
|     )
 | |
| 
 | |
|     instance_to_create = 3
 | |
|     test_instance_arns = []
 | |
|     for i in range(0, instance_to_create):
 | |
|         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)
 | |
|         )
 | |
| 
 | |
|         response = ecs_client.register_container_instance(
 | |
|             cluster=test_cluster_name,
 | |
|             instanceIdentityDocument=instance_id_document)
 | |
| 
 | |
|         test_instance_arns.append(response['containerInstance']['containerInstanceArn'])
 | |
| 
 | |
|     response = ecs_client.update_container_instances_state(cluster=test_cluster_name,
 | |
|                                                            containerInstances=test_instance_arns,
 | |
|                                                            status='DRAINING')
 | |
|     len(response['failures']).should.equal(0)
 | |
|     len(response['containerInstances']).should.equal(instance_to_create)
 | |
|     response_statuses = [ci['status'] for ci in response['containerInstances']]
 | |
|     for status in response_statuses:
 | |
|         status.should.equal('DRAINING')
 | |
|     response = ecs_client.update_container_instances_state(cluster=test_cluster_name,
 | |
|                                                            containerInstances=test_instance_arns,
 | |
|                                                            status='DRAINING')
 | |
|     len(response['failures']).should.equal(0)
 | |
|     len(response['containerInstances']).should.equal(instance_to_create)
 | |
|     response_statuses = [ci['status'] for ci in response['containerInstances']]
 | |
|     for status in response_statuses:
 | |
|         status.should.equal('DRAINING')
 | |
|     response = ecs_client.update_container_instances_state(cluster=test_cluster_name,
 | |
|                                                            containerInstances=test_instance_arns,
 | |
|                                                            status='ACTIVE')
 | |
|     len(response['failures']).should.equal(0)
 | |
|     len(response['containerInstances']).should.equal(instance_to_create)
 | |
|     response_statuses = [ci['status'] for ci in response['containerInstances']]
 | |
|     for status in response_statuses:
 | |
|         status.should.equal('ACTIVE')
 | |
|     ecs_client.update_container_instances_state.when.called_with(cluster=test_cluster_name,
 | |
|                                                                  containerInstances=test_instance_arns,
 | |
|                                                                  status='test_status').should.throw(Exception)
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_run_task():
 | |
|     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)
 | |
|     )
 | |
| 
 | |
|     response = 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',
 | |
|                 'cpu': 1024,
 | |
|                 'memory': 400,
 | |
|                 'essential': True,
 | |
|                 'environment': [{
 | |
|                     'name': 'AWS_ACCESS_KEY_ID',
 | |
|                     'value': 'SOME_ACCESS_KEY'
 | |
|                 }],
 | |
|                 'logConfiguration': {'logDriver': 'json-file'}
 | |
|             }
 | |
|         ]
 | |
|     )
 | |
|     response = client.run_task(
 | |
|         cluster='test_ecs_cluster',
 | |
|         overrides={},
 | |
|         taskDefinition='test_ecs_task',
 | |
|         count=2,
 | |
|         startedBy='moto'
 | |
|     )
 | |
|     len(response['tasks']).should.equal(2)
 | |
|     response['tasks'][0]['taskArn'].should.contain(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:task/')
 | |
|     response['tasks'][0]['clusterArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:cluster/test_ecs_cluster')
 | |
|     response['tasks'][0]['taskDefinitionArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:1')
 | |
|     response['tasks'][0]['containerInstanceArn'].should.contain(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:container-instance/')
 | |
|     response['tasks'][0]['overrides'].should.equal({})
 | |
|     response['tasks'][0]['lastStatus'].should.equal("RUNNING")
 | |
|     response['tasks'][0]['desiredStatus'].should.equal("RUNNING")
 | |
|     response['tasks'][0]['startedBy'].should.equal("moto")
 | |
|     response['tasks'][0]['stoppedReason'].should.equal("")
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_start_task():
 | |
|     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)
 | |
|     )
 | |
| 
 | |
|     response = client.register_container_instance(
 | |
|         cluster=test_cluster_name,
 | |
|         instanceIdentityDocument=instance_id_document
 | |
|     )
 | |
| 
 | |
|     container_instances = client.list_container_instances(
 | |
|         cluster=test_cluster_name)
 | |
|     container_instance_id = container_instances[
 | |
|         'containerInstanceArns'][0].split('/')[-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'}
 | |
|             }
 | |
|         ]
 | |
|     )
 | |
| 
 | |
|     response = client.start_task(
 | |
|         cluster='test_ecs_cluster',
 | |
|         taskDefinition='test_ecs_task',
 | |
|         overrides={},
 | |
|         containerInstances=[container_instance_id],
 | |
|         startedBy='moto'
 | |
|     )
 | |
| 
 | |
|     len(response['tasks']).should.equal(1)
 | |
|     response['tasks'][0]['taskArn'].should.contain(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:task/')
 | |
|     response['tasks'][0]['clusterArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:cluster/test_ecs_cluster')
 | |
|     response['tasks'][0]['taskDefinitionArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:1')
 | |
|     response['tasks'][0]['containerInstanceArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:container-instance/{0}'.format(container_instance_id))
 | |
|     response['tasks'][0]['overrides'].should.equal({})
 | |
|     response['tasks'][0]['lastStatus'].should.equal("RUNNING")
 | |
|     response['tasks'][0]['desiredStatus'].should.equal("RUNNING")
 | |
|     response['tasks'][0]['startedBy'].should.equal("moto")
 | |
|     response['tasks'][0]['stoppedReason'].should.equal("")
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_list_tasks():
 | |
|     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
 | |
|     )
 | |
| 
 | |
|     container_instances = client.list_container_instances(
 | |
|         cluster=test_cluster_name)
 | |
|     container_instance_id = container_instances[
 | |
|         'containerInstanceArns'][0].split('/')[-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.start_task(
 | |
|         cluster='test_ecs_cluster',
 | |
|         taskDefinition='test_ecs_task',
 | |
|         overrides={},
 | |
|         containerInstances=[container_instance_id],
 | |
|         startedBy='foo'
 | |
|     )
 | |
| 
 | |
|     _ = client.start_task(
 | |
|         cluster='test_ecs_cluster',
 | |
|         taskDefinition='test_ecs_task',
 | |
|         overrides={},
 | |
|         containerInstances=[container_instance_id],
 | |
|         startedBy='bar'
 | |
|     )
 | |
| 
 | |
|     assert len(client.list_tasks()['taskArns']).should.equal(2)
 | |
|     assert len(client.list_tasks(cluster='test_ecs_cluster')
 | |
|                ['taskArns']).should.equal(2)
 | |
|     assert len(client.list_tasks(startedBy='foo')['taskArns']).should.equal(1)
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_describe_tasks():
 | |
|     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)
 | |
|     )
 | |
| 
 | |
|     response = 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',
 | |
|                 'cpu': 1024,
 | |
|                 'memory': 400,
 | |
|                 'essential': True,
 | |
|                 'environment': [{
 | |
|                     'name': 'AWS_ACCESS_KEY_ID',
 | |
|                     'value': 'SOME_ACCESS_KEY'
 | |
|                 }],
 | |
|                 'logConfiguration': {'logDriver': 'json-file'}
 | |
|             }
 | |
|         ]
 | |
|     )
 | |
|     tasks_arns = [
 | |
|         task['taskArn'] for task in client.run_task(
 | |
|             cluster='test_ecs_cluster',
 | |
|             overrides={},
 | |
|             taskDefinition='test_ecs_task',
 | |
|             count=2,
 | |
|             startedBy='moto'
 | |
|         )['tasks']
 | |
|     ]
 | |
|     response = client.describe_tasks(
 | |
|         cluster='test_ecs_cluster',
 | |
|         tasks=tasks_arns
 | |
|     )
 | |
| 
 | |
|     len(response['tasks']).should.equal(2)
 | |
|     set([response['tasks'][0]['taskArn'], response['tasks']
 | |
|     [1]['taskArn']]).should.equal(set(tasks_arns))
 | |
| 
 | |
|     # Test we can pass task ids instead of ARNs
 | |
|     response = client.describe_tasks(
 | |
|         cluster='test_ecs_cluster',
 | |
|         tasks=[tasks_arns[0].split("/")[-1]]
 | |
|     )
 | |
|     len(response['tasks']).should.equal(1)
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def describe_task_definition():
 | |
|     client = boto3.client('ecs', region_name='us-east-1')
 | |
|     container_definition = {
 | |
|         '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'}
 | |
|     }
 | |
|     task_definition = client.register_task_definition(
 | |
|         family='test_ecs_task',
 | |
|         containerDefinitions=[container_definition]
 | |
|     )
 | |
|     family = task_definition['family']
 | |
|     task = client.describe_task_definition(taskDefinition=family)
 | |
|     task['containerDefinitions'][0].should.equal(container_definition)
 | |
|     task['taskDefinitionArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task2:1')
 | |
|     task['volumes'].should.equal([])
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_stop_task():
 | |
|     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',
 | |
|                 'cpu': 1024,
 | |
|                 'memory': 400,
 | |
|                 'essential': True,
 | |
|                 'environment': [{
 | |
|                     'name': 'AWS_ACCESS_KEY_ID',
 | |
|                     'value': 'SOME_ACCESS_KEY'
 | |
|                 }],
 | |
|                 'logConfiguration': {'logDriver': 'json-file'}
 | |
|             }
 | |
|         ]
 | |
|     )
 | |
|     run_response = client.run_task(
 | |
|         cluster='test_ecs_cluster',
 | |
|         overrides={},
 | |
|         taskDefinition='test_ecs_task',
 | |
|         count=1,
 | |
|         startedBy='moto'
 | |
|     )
 | |
|     stop_response = client.stop_task(
 | |
|         cluster='test_ecs_cluster',
 | |
|         task=run_response['tasks'][0].get('taskArn'),
 | |
|         reason='moto testing'
 | |
|     )
 | |
| 
 | |
|     stop_response['task']['taskArn'].should.equal(
 | |
|         run_response['tasks'][0].get('taskArn'))
 | |
|     stop_response['task']['lastStatus'].should.equal('STOPPED')
 | |
|     stop_response['task']['desiredStatus'].should.equal('STOPPED')
 | |
|     stop_response['task']['stoppedReason'].should.equal('moto testing')
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_resource_reservation_and_release():
 | |
|     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',
 | |
|                 'cpu': 1024,
 | |
|                 'memory': 400,
 | |
|                 'essential': True,
 | |
|                 'environment': [{
 | |
|                     'name': 'AWS_ACCESS_KEY_ID',
 | |
|                     'value': 'SOME_ACCESS_KEY'
 | |
|                 }],
 | |
|                 'logConfiguration': {'logDriver': 'json-file'},
 | |
|                 'portMappings': [
 | |
|                     {
 | |
|                         'hostPort': 80,
 | |
|                         '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'] - 1024)
 | |
|     remaining_resources['MEMORY'].should.equal(registered_resources['MEMORY'] - 400)
 | |
|     registered_resources['PORTS'].append('80')
 | |
|     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_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
 | |
| def test_create_cluster_through_cloudformation():
 | |
|     template = {
 | |
|         "AWSTemplateFormatVersion": "2010-09-09",
 | |
|         "Description": "ECS Cluster Test CloudFormation",
 | |
|         "Resources": {
 | |
|             "testCluster": {
 | |
|                 "Type": "AWS::ECS::Cluster",
 | |
|                 "Properties": {
 | |
|                     "ClusterName": "testcluster"
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     template_json = json.dumps(template)
 | |
| 
 | |
|     ecs_conn = boto3.client('ecs', region_name='us-west-1')
 | |
|     resp = ecs_conn.list_clusters()
 | |
|     len(resp['clusterArns']).should.equal(0)
 | |
| 
 | |
|     cfn_conn = boto3.client('cloudformation', region_name='us-west-1')
 | |
|     cfn_conn.create_stack(
 | |
|         StackName="test_stack",
 | |
|         TemplateBody=template_json,
 | |
|     )
 | |
| 
 | |
|     resp = ecs_conn.list_clusters()
 | |
|     len(resp['clusterArns']).should.equal(1)
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| @mock_cloudformation
 | |
| def test_create_cluster_through_cloudformation_no_name():
 | |
|     # cloudformation should create a cluster name for you if you do not provide it
 | |
|     # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-cluster.html#cfn-ecs-cluster-clustername
 | |
|     template = {
 | |
|         "AWSTemplateFormatVersion": "2010-09-09",
 | |
|         "Description": "ECS Cluster Test CloudFormation",
 | |
|         "Resources": {
 | |
|             "testCluster": {
 | |
|                 "Type": "AWS::ECS::Cluster",
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     template_json = json.dumps(template)
 | |
|     cfn_conn = boto3.client('cloudformation', region_name='us-west-1')
 | |
|     cfn_conn.create_stack(
 | |
|         StackName="test_stack",
 | |
|         TemplateBody=template_json,
 | |
|     )
 | |
| 
 | |
|     ecs_conn = boto3.client('ecs', region_name='us-west-1')
 | |
|     resp = ecs_conn.list_clusters()
 | |
|     len(resp['clusterArns']).should.equal(1)
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| @mock_cloudformation
 | |
| def test_update_cluster_name_through_cloudformation_should_trigger_a_replacement():
 | |
|     template1 = {
 | |
|         "AWSTemplateFormatVersion": "2010-09-09",
 | |
|         "Description": "ECS Cluster Test CloudFormation",
 | |
|         "Resources": {
 | |
|             "testCluster": {
 | |
|                 "Type": "AWS::ECS::Cluster",
 | |
|                 "Properties": {
 | |
|                     "ClusterName": "testcluster1"
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     template2 = deepcopy(template1)
 | |
|     template2['Resources']['testCluster'][
 | |
|         'Properties']['ClusterName'] = 'testcluster2'
 | |
|     template1_json = json.dumps(template1)
 | |
|     cfn_conn = boto3.client('cloudformation', region_name='us-west-1')
 | |
|     stack_resp = cfn_conn.create_stack(
 | |
|         StackName="test_stack",
 | |
|         TemplateBody=template1_json,
 | |
|     )
 | |
| 
 | |
|     template2_json = json.dumps(template2)
 | |
|     cfn_conn.update_stack(
 | |
|         StackName=stack_resp['StackId'],
 | |
|         TemplateBody=template2_json
 | |
|     )
 | |
|     ecs_conn = boto3.client('ecs', region_name='us-west-1')
 | |
|     resp = ecs_conn.list_clusters()
 | |
|     len(resp['clusterArns']).should.equal(1)
 | |
|     resp['clusterArns'][0].endswith('testcluster2').should.be.true
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| @mock_cloudformation
 | |
| def test_create_task_definition_through_cloudformation():
 | |
|     template = {
 | |
|         "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",
 | |
|                             "Cpu": "200",
 | |
|                             "Memory": "500",
 | |
|                             "Essential": "true"
 | |
|                         }
 | |
|                     ],
 | |
|                     "Volumes": [],
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     template_json = json.dumps(template)
 | |
|     cfn_conn = boto3.client('cloudformation', region_name='us-west-1')
 | |
|     stack_name = 'test_stack'
 | |
|     cfn_conn.create_stack(
 | |
|         StackName=stack_name,
 | |
|         TemplateBody=template_json,
 | |
|     )
 | |
| 
 | |
|     ecs_conn = boto3.client('ecs', region_name='us-west-1')
 | |
|     resp = ecs_conn.list_task_definitions()
 | |
|     len(resp['taskDefinitionArns']).should.equal(1)
 | |
|     task_definition_arn = resp['taskDefinitionArns'][0]
 | |
| 
 | |
|     task_definition_details = cfn_conn.describe_stack_resource(
 | |
|         StackName=stack_name,LogicalResourceId='testTaskDefinition')['StackResourceDetail']
 | |
|     task_definition_details['PhysicalResourceId'].should.equal(task_definition_arn)
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_task_definitions_unable_to_be_placed():
 | |
|     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)
 | |
|     )
 | |
| 
 | |
|     response = 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',
 | |
|                 'cpu': 5000,
 | |
|                 'memory': 40000,
 | |
|                 'essential': True,
 | |
|                 'environment': [{
 | |
|                     'name': 'AWS_ACCESS_KEY_ID',
 | |
|                     'value': 'SOME_ACCESS_KEY'
 | |
|                 }],
 | |
|                 'logConfiguration': {'logDriver': 'json-file'}
 | |
|             }
 | |
|         ]
 | |
|     )
 | |
|     response = client.run_task(
 | |
|         cluster='test_ecs_cluster',
 | |
|         overrides={},
 | |
|         taskDefinition='test_ecs_task',
 | |
|         count=2,
 | |
|         startedBy='moto'
 | |
|     )
 | |
|     len(response['tasks']).should.equal(0)
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_task_definitions_with_port_clash():
 | |
|     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)
 | |
|     )
 | |
| 
 | |
|     response = 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',
 | |
|                 'cpu': 256,
 | |
|                 'memory': 512,
 | |
|                 'essential': True,
 | |
|                 'environment': [{
 | |
|                     'name': 'AWS_ACCESS_KEY_ID',
 | |
|                     'value': 'SOME_ACCESS_KEY'
 | |
|                 }],
 | |
|                 'logConfiguration': {'logDriver': 'json-file'},
 | |
|                 'portMappings': [
 | |
|                     {
 | |
|                         'hostPort': 80,
 | |
|                         'containerPort': 8080
 | |
|                     }
 | |
|                 ]
 | |
|             }
 | |
|         ]
 | |
|     )
 | |
|     response = client.run_task(
 | |
|         cluster='test_ecs_cluster',
 | |
|         overrides={},
 | |
|         taskDefinition='test_ecs_task',
 | |
|         count=2,
 | |
|         startedBy='moto'
 | |
|     )
 | |
|     len(response['tasks']).should.equal(1)
 | |
|     response['tasks'][0]['taskArn'].should.contain(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:task/')
 | |
|     response['tasks'][0]['clusterArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:cluster/test_ecs_cluster')
 | |
|     response['tasks'][0]['taskDefinitionArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:1')
 | |
|     response['tasks'][0]['containerInstanceArn'].should.contain(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:container-instance/')
 | |
|     response['tasks'][0]['overrides'].should.equal({})
 | |
|     response['tasks'][0]['lastStatus'].should.equal("RUNNING")
 | |
|     response['tasks'][0]['desiredStatus'].should.equal("RUNNING")
 | |
|     response['tasks'][0]['startedBy'].should.equal("moto")
 | |
|     response['tasks'][0]['stoppedReason'].should.equal("")
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| @mock_cloudformation
 | |
| def test_update_task_definition_family_through_cloudformation_should_trigger_a_replacement():
 | |
|     template1 = {
 | |
|         "AWSTemplateFormatVersion": "2010-09-09",
 | |
|         "Description": "ECS Cluster Test CloudFormation",
 | |
|         "Resources": {
 | |
|             "testTaskDefinition": {
 | |
|                 "Type": "AWS::ECS::TaskDefinition",
 | |
|                 "Properties": {
 | |
|                     "Family": "testTaskDefinition1",
 | |
|                     "ContainerDefinitions": [
 | |
|                         {
 | |
|                             "Name": "ecs-sample",
 | |
|                             "Image": "amazon/amazon-ecs-sample",
 | |
|                             "Cpu": "200",
 | |
|                             "Memory": "500",
 | |
|                             "Essential": "true"
 | |
|                         }
 | |
|                     ],
 | |
|                     "Volumes": [],
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     template1_json = json.dumps(template1)
 | |
|     cfn_conn = boto3.client('cloudformation', region_name='us-west-1')
 | |
|     cfn_conn.create_stack(
 | |
|         StackName="test_stack",
 | |
|         TemplateBody=template1_json,
 | |
|     )
 | |
| 
 | |
|     template2 = deepcopy(template1)
 | |
|     template2['Resources']['testTaskDefinition'][
 | |
|         'Properties']['Family'] = 'testTaskDefinition2'
 | |
|     template2_json = json.dumps(template2)
 | |
|     cfn_conn.update_stack(
 | |
|         StackName="test_stack",
 | |
|         TemplateBody=template2_json,
 | |
|     )
 | |
| 
 | |
|     ecs_conn = boto3.client('ecs', region_name='us-west-1')
 | |
|     resp = ecs_conn.list_task_definitions(familyPrefix='testTaskDefinition')
 | |
|     len(resp['taskDefinitionArns']).should.equal(1)
 | |
|     resp['taskDefinitionArns'][0].endswith(
 | |
|         'testTaskDefinition2:1').should.be.true
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| @mock_cloudformation
 | |
| def test_create_service_through_cloudformation():
 | |
|     template = {
 | |
|         "AWSTemplateFormatVersion": "2010-09-09",
 | |
|         "Description": "ECS Cluster Test CloudFormation",
 | |
|         "Resources": {
 | |
|             "testCluster": {
 | |
|                 "Type": "AWS::ECS::Cluster",
 | |
|                 "Properties": {
 | |
|                     "ClusterName": "testcluster"
 | |
|                 }
 | |
|             },
 | |
|             "testTaskDefinition": {
 | |
|                 "Type": "AWS::ECS::TaskDefinition",
 | |
|                 "Properties": {
 | |
|                     "ContainerDefinitions": [
 | |
|                         {
 | |
|                             "Name": "ecs-sample",
 | |
|                             "Image": "amazon/amazon-ecs-sample",
 | |
|                             "Cpu": "200",
 | |
|                             "Memory": "500",
 | |
|                             "Essential": "true"
 | |
|                         }
 | |
|                     ],
 | |
|                     "Volumes": [],
 | |
|                 }
 | |
|             },
 | |
|             "testService": {
 | |
|                 "Type": "AWS::ECS::Service",
 | |
|                 "Properties": {
 | |
|                     "Cluster": {"Ref": "testCluster"},
 | |
|                     "DesiredCount": 10,
 | |
|                     "TaskDefinition": {"Ref": "testTaskDefinition"},
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     template_json = json.dumps(template)
 | |
|     cfn_conn = boto3.client('cloudformation', region_name='us-west-1')
 | |
|     cfn_conn.create_stack(
 | |
|         StackName="test_stack",
 | |
|         TemplateBody=template_json,
 | |
|     )
 | |
| 
 | |
|     ecs_conn = boto3.client('ecs', region_name='us-west-1')
 | |
|     resp = ecs_conn.list_services(cluster='testcluster')
 | |
|     len(resp['serviceArns']).should.equal(1)
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| @mock_cloudformation
 | |
| def test_update_service_through_cloudformation_should_trigger_replacement():
 | |
|     template1 = {
 | |
|         "AWSTemplateFormatVersion": "2010-09-09",
 | |
|         "Description": "ECS Cluster Test CloudFormation",
 | |
|         "Resources": {
 | |
|             "testCluster": {
 | |
|                 "Type": "AWS::ECS::Cluster",
 | |
|                 "Properties": {
 | |
|                     "ClusterName": "testcluster"
 | |
|                 }
 | |
|             },
 | |
|             "testTaskDefinition": {
 | |
|                 "Type": "AWS::ECS::TaskDefinition",
 | |
|                 "Properties": {
 | |
|                     "ContainerDefinitions": [
 | |
|                         {
 | |
|                             "Name": "ecs-sample",
 | |
|                             "Image": "amazon/amazon-ecs-sample",
 | |
|                             "Cpu": "200",
 | |
|                             "Memory": "500",
 | |
|                             "Essential": "true"
 | |
|                         }
 | |
|                     ],
 | |
|                     "Volumes": [],
 | |
|                 }
 | |
|             },
 | |
|             "testService": {
 | |
|                 "Type": "AWS::ECS::Service",
 | |
|                 "Properties": {
 | |
|                     "Cluster": {"Ref": "testCluster"},
 | |
|                     "TaskDefinition": {"Ref": "testTaskDefinition"},
 | |
|                     "DesiredCount": 10,
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     template_json1 = json.dumps(template1)
 | |
|     cfn_conn = boto3.client('cloudformation', region_name='us-west-1')
 | |
|     cfn_conn.create_stack(
 | |
|         StackName="test_stack",
 | |
|         TemplateBody=template_json1,
 | |
|     )
 | |
|     template2 = deepcopy(template1)
 | |
|     template2['Resources']['testService']['Properties']['DesiredCount'] = 5
 | |
|     template2_json = json.dumps(template2)
 | |
|     cfn_conn.update_stack(
 | |
|         StackName="test_stack",
 | |
|         TemplateBody=template2_json,
 | |
|     )
 | |
| 
 | |
|     ecs_conn = boto3.client('ecs', region_name='us-west-1')
 | |
|     resp = ecs_conn.list_services(cluster='testcluster')
 | |
|     len(resp['serviceArns']).should.equal(1)
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_attributes():
 | |
|     # Combined put, list delete attributes into the same test due to the amount of setup
 | |
|     ecs_client = boto3.client('ecs', region_name='us-east-1')
 | |
|     ec2 = boto3.resource('ec2', region_name='us-east-1')
 | |
| 
 | |
|     test_cluster_name = 'test_ecs_cluster'
 | |
| 
 | |
|     _ = ecs_client.create_cluster(
 | |
|         clusterName=test_cluster_name
 | |
|     )
 | |
| 
 | |
|     instances = []
 | |
|     test_instance = ec2.create_instances(
 | |
|         ImageId="ami-1234abcd",
 | |
|         MinCount=1,
 | |
|         MaxCount=1,
 | |
|     )[0]
 | |
|     instances.append(test_instance)
 | |
| 
 | |
|     instance_id_document = json.dumps(
 | |
|         ec2_utils.generate_instance_identity_document(test_instance)
 | |
|     )
 | |
| 
 | |
|     response = ecs_client.register_container_instance(
 | |
|         cluster=test_cluster_name,
 | |
|         instanceIdentityDocument=instance_id_document
 | |
|     )
 | |
| 
 | |
|     response['containerInstance'][
 | |
|         'ec2InstanceId'].should.equal(test_instance.id)
 | |
|     full_arn1 = response['containerInstance']['containerInstanceArn']
 | |
| 
 | |
|     test_instance = ec2.create_instances(
 | |
|         ImageId="ami-1234abcd",
 | |
|         MinCount=1,
 | |
|         MaxCount=1,
 | |
|     )[0]
 | |
|     instances.append(test_instance)
 | |
| 
 | |
|     instance_id_document = json.dumps(
 | |
|         ec2_utils.generate_instance_identity_document(test_instance)
 | |
|     )
 | |
| 
 | |
|     response = ecs_client.register_container_instance(
 | |
|         cluster=test_cluster_name,
 | |
|         instanceIdentityDocument=instance_id_document
 | |
|     )
 | |
| 
 | |
|     response['containerInstance'][
 | |
|         'ec2InstanceId'].should.equal(test_instance.id)
 | |
|     full_arn2 = response['containerInstance']['containerInstanceArn']
 | |
|     partial_arn2 = full_arn2.rsplit('/', 1)[-1]
 | |
| 
 | |
|     full_arn2.should_not.equal(full_arn1)  # uuid1 isnt unique enough when the pc is fast ;-)
 | |
| 
 | |
|     # Ok set instance 1 with 1 attribute, instance 2 with another, and all of them with a 3rd.
 | |
|     ecs_client.put_attributes(
 | |
|         cluster=test_cluster_name,
 | |
|         attributes=[
 | |
|             {'name': 'env', 'value': 'prod'},
 | |
|             {'name': 'attr1', 'value': 'instance1', 'targetId': full_arn1},
 | |
|             {'name': 'attr1', 'value': 'instance2', 'targetId': partial_arn2,
 | |
|              'targetType': 'container-instance'}
 | |
|         ]
 | |
|     )
 | |
| 
 | |
|     resp = ecs_client.list_attributes(
 | |
|         cluster=test_cluster_name,
 | |
|         targetType='container-instance'
 | |
|     )
 | |
|     attrs = resp['attributes']
 | |
| 
 | |
|     NUM_CUSTOM_ATTRIBUTES = 4  # 2 specific to individual machines and 1 global, going to both machines (2 + 1*2)
 | |
|     NUM_DEFAULT_ATTRIBUTES = 4
 | |
|     len(attrs).should.equal(NUM_CUSTOM_ATTRIBUTES + (NUM_DEFAULT_ATTRIBUTES * len(instances)))
 | |
| 
 | |
|     # Tests that the attrs have been set properly
 | |
|     len(list(filter(lambda item: item['name'] == 'env', attrs))).should.equal(2)
 | |
|     len(list(
 | |
|         filter(lambda item: item['name'] == 'attr1' and item['value'] == 'instance1', attrs))).should.equal(1)
 | |
| 
 | |
|     ecs_client.delete_attributes(
 | |
|         cluster=test_cluster_name,
 | |
|         attributes=[
 | |
|             {'name': 'attr1', 'value': 'instance2', 'targetId': partial_arn2,
 | |
|              'targetType': 'container-instance'}
 | |
|         ]
 | |
|     )
 | |
|     NUM_CUSTOM_ATTRIBUTES -= 1
 | |
| 
 | |
|     resp = ecs_client.list_attributes(
 | |
|         cluster=test_cluster_name,
 | |
|         targetType='container-instance'
 | |
|     )
 | |
|     attrs = resp['attributes']
 | |
|     len(attrs).should.equal(NUM_CUSTOM_ATTRIBUTES + (NUM_DEFAULT_ATTRIBUTES * len(instances)))
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_poll_endpoint():
 | |
|     # Combined put, list delete attributes into the same test due to the amount of setup
 | |
|     ecs_client = boto3.client('ecs', region_name='us-east-1')
 | |
| 
 | |
|     # Just a placeholder until someone actually wants useless data, just testing it doesnt raise an exception
 | |
|     resp = ecs_client.discover_poll_endpoint(cluster='blah', containerInstance='blah')
 | |
|     resp.should.contain('endpoint')
 | |
|     resp.should.contain('telemetryEndpoint')
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_list_task_definition_families():
 | |
|     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='alt_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'}
 | |
|             }
 | |
|         ]
 | |
|     )
 | |
| 
 | |
|     resp1 = client.list_task_definition_families()
 | |
|     resp2 = client.list_task_definition_families(familyPrefix='alt')
 | |
| 
 | |
|     len(resp1['families']).should.equal(2)
 | |
|     len(resp2['families']).should.equal(1)
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_default_container_instance_attributes():
 | |
|     ecs_client = boto3.client('ecs', region_name='us-east-1')
 | |
|     ec2 = boto3.resource('ec2', region_name='us-east-1')
 | |
| 
 | |
|     test_cluster_name = 'test_ecs_cluster'
 | |
| 
 | |
|     # Create cluster and EC2 instance
 | |
|     _ = ecs_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)
 | |
|     )
 | |
| 
 | |
|     # Register container instance
 | |
|     response = ecs_client.register_container_instance(
 | |
|         cluster=test_cluster_name,
 | |
|         instanceIdentityDocument=instance_id_document
 | |
|     )
 | |
| 
 | |
|     response['containerInstance'][
 | |
|         'ec2InstanceId'].should.equal(test_instance.id)
 | |
|     full_arn = response['containerInstance']['containerInstanceArn']
 | |
|     container_instance_id = full_arn.rsplit('/', 1)[-1]
 | |
| 
 | |
|     default_attributes = response['containerInstance']['attributes']
 | |
|     assert len(default_attributes) == 4
 | |
|     expected_result = [
 | |
|         {'name': 'ecs.availability-zone', 'value': test_instance.placement['AvailabilityZone']},
 | |
|         {'name': 'ecs.ami-id', 'value': test_instance.image_id},
 | |
|         {'name': 'ecs.instance-type', 'value': test_instance.instance_type},
 | |
|         {'name': 'ecs.os-type', 'value': test_instance.platform or 'linux'}
 | |
|     ]
 | |
|     assert sorted(default_attributes, key=lambda item: item['name']) == sorted(expected_result,
 | |
|                                                                                key=lambda item: item['name'])
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| @mock_ecs
 | |
| def test_describe_container_instances_with_attributes():
 | |
|     ecs_client = boto3.client('ecs', region_name='us-east-1')
 | |
|     ec2 = boto3.resource('ec2', region_name='us-east-1')
 | |
| 
 | |
|     test_cluster_name = 'test_ecs_cluster'
 | |
| 
 | |
|     # Create cluster and EC2 instance
 | |
|     _ = ecs_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)
 | |
|     )
 | |
| 
 | |
|     # Register container instance
 | |
|     response = ecs_client.register_container_instance(
 | |
|         cluster=test_cluster_name,
 | |
|         instanceIdentityDocument=instance_id_document
 | |
|     )
 | |
| 
 | |
|     response['containerInstance'][
 | |
|         'ec2InstanceId'].should.equal(test_instance.id)
 | |
|     full_arn = response['containerInstance']['containerInstanceArn']
 | |
|     container_instance_id = full_arn.rsplit('/', 1)[-1]
 | |
|     default_attributes = response['containerInstance']['attributes']
 | |
| 
 | |
|     # Set attributes on container instance, one without a value
 | |
|     attributes = [
 | |
|         {'name': 'env', 'value': 'prod'},
 | |
|         {'name': 'attr1', 'value': 'instance1', 'targetId': container_instance_id,
 | |
|          'targetType': 'container-instance'},
 | |
|         {'name': 'attr_without_value'}
 | |
|     ]
 | |
|     ecs_client.put_attributes(
 | |
|         cluster=test_cluster_name,
 | |
|         attributes=attributes
 | |
|     )
 | |
| 
 | |
|     # Describe container instance, should have attributes previously set
 | |
|     described_instance = ecs_client.describe_container_instances(cluster=test_cluster_name,
 | |
|                                                                  containerInstances=[container_instance_id])
 | |
| 
 | |
|     assert len(described_instance['containerInstances']) == 1
 | |
|     assert isinstance(described_instance['containerInstances'][0]['attributes'], list)
 | |
| 
 | |
|     # Remove additional info passed to put_attributes
 | |
|     cleaned_attributes = []
 | |
|     for attribute in attributes:
 | |
|         attribute.pop('targetId', None)
 | |
|         attribute.pop('targetType', None)
 | |
|         cleaned_attributes.append(attribute)
 | |
|     described_attributes = sorted(described_instance['containerInstances'][0]['attributes'],
 | |
|                                   key=lambda item: item['name'])
 | |
|     expected_attributes = sorted(default_attributes + cleaned_attributes, key=lambda item: item['name'])
 | |
|     assert described_attributes == expected_attributes
 | |
| 
 | |
| 
 | |
| def _fetch_container_instance_resources(container_instance_description):
 | |
|     remaining_resources = {}
 | |
|     registered_resources = {}
 | |
|     remaining_resources_list = container_instance_description['remainingResources']
 | |
|     registered_resources_list = container_instance_description['registeredResources']
 | |
|     remaining_resources['CPU'] = [x['integerValue'] for x in remaining_resources_list if x['name'] == 'CPU'][
 | |
|         0]
 | |
|     remaining_resources['MEMORY'] = \
 | |
|     [x['integerValue'] for x in remaining_resources_list if x['name'] == 'MEMORY'][0]
 | |
|     remaining_resources['PORTS'] = \
 | |
|     [x['stringSetValue'] for x in remaining_resources_list if x['name'] == 'PORTS'][0]
 | |
|     registered_resources['CPU'] = \
 | |
|     [x['integerValue'] for x in registered_resources_list if x['name'] == 'CPU'][0]
 | |
|     registered_resources['MEMORY'] = \
 | |
|     [x['integerValue'] for x in registered_resources_list if x['name'] == 'MEMORY'][0]
 | |
|     registered_resources['PORTS'] = \
 | |
|     [x['stringSetValue'] for x in registered_resources_list if x['name'] == 'PORTS'][0]
 | |
|     return remaining_resources, registered_resources
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_create_service_load_balancing():
 | |
|     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'}
 | |
|             }
 | |
|         ]
 | |
|     )
 | |
|     response = client.create_service(
 | |
|         cluster='test_ecs_cluster',
 | |
|         serviceName='test_ecs_service',
 | |
|         taskDefinition='test_ecs_task',
 | |
|         desiredCount=2,
 | |
|         loadBalancers=[
 | |
|             {
 | |
|                 'targetGroupArn': 'test_target_group_arn',
 | |
|                 'loadBalancerName': 'test_load_balancer_name',
 | |
|                 'containerName': 'test_container_name',
 | |
|                 'containerPort': 123
 | |
|             }
 | |
|         ]
 | |
|     )
 | |
|     response['service']['clusterArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:cluster/test_ecs_cluster')
 | |
|     response['service']['desiredCount'].should.equal(2)
 | |
|     len(response['service']['events']).should.equal(0)
 | |
|     len(response['service']['loadBalancers']).should.equal(1)
 | |
|     response['service']['loadBalancers'][0]['targetGroupArn'].should.equal(
 | |
|         'test_target_group_arn')
 | |
|     response['service']['loadBalancers'][0]['loadBalancerName'].should.equal(
 | |
|         'test_load_balancer_name')
 | |
|     response['service']['loadBalancers'][0]['containerName'].should.equal(
 | |
|         'test_container_name')
 | |
|     response['service']['loadBalancers'][0]['containerPort'].should.equal(123)
 | |
|     response['service']['pendingCount'].should.equal(0)
 | |
|     response['service']['runningCount'].should.equal(0)
 | |
|     response['service']['serviceArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:service/test_ecs_service')
 | |
|     response['service']['serviceName'].should.equal('test_ecs_service')
 | |
|     response['service']['status'].should.equal('ACTIVE')
 | |
|     response['service']['taskDefinition'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:1')
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_list_tags_for_resource():
 | |
|     client = boto3.client('ecs', region_name='us-east-1')
 | |
|     response = 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'}
 | |
|             }
 | |
|         ],
 | |
|         tags=[
 | |
|             {'key': 'createdBy', 'value': 'moto-unittest'},
 | |
|             {'key': 'foo', 'value': 'bar'},
 | |
|         ]
 | |
|     )
 | |
|     type(response['taskDefinition']).should.be(dict)
 | |
|     response['taskDefinition']['revision'].should.equal(1)
 | |
|     response['taskDefinition']['taskDefinitionArn'].should.equal(
 | |
|         'arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:1')
 | |
| 
 | |
|     task_definition_arn = response['taskDefinition']['taskDefinitionArn']
 | |
|     response = client.list_tags_for_resource(resourceArn=task_definition_arn)
 | |
| 
 | |
|     type(response['tags']).should.be(list)
 | |
|     response['tags'].should.equal([
 | |
|         {'key': 'createdBy', 'value': 'moto-unittest'},
 | |
|         {'key': 'foo', 'value': 'bar'},
 | |
|     ])
 | |
| 
 | |
| 
 | |
| @mock_ecs
 | |
| def test_list_tags_for_resource_unknown():
 | |
|     client = boto3.client('ecs', region_name='us-east-1')
 | |
|     task_definition_arn = 'arn:aws:ecs:us-east-1:012345678910:task-definition/unknown:1'
 | |
|     try:
 | |
|         client.list_tags_for_resource(resourceArn=task_definition_arn)
 | |
|     except ClientError as err:
 | |
|         err.response['Error']['Code'].should.equal('ClientException')
 |