moto/tests/test_ecs/test_ecs_boto3.py
Steve Pulec 080e3c5f5d
Merge pull request #1537 from william-richard/cloudformation-ecs-cluster-name-optional
If Properies isn't set, cloudformation will just use default values
2018-04-12 18:52:16 -04:00

2018 lines
68 KiB
Python

from __future__ import unicode_literals
from copy import deepcopy
import boto3
import sure # noqa
import json
from moto.ec2 import utils as ec2_utils
from uuid import UUID
from moto import mock_cloudformation
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_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'}
}
]
)
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')
@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',
desiredCount=2
)
_ = client.create_service(
cluster='test_ecs_cluster',
serviceName='test_ecs_service2',
taskDefinition='test_ecs_task',
desiredCount=2
)
response = client.list_services(
cluster='test_ecs_cluster'
)
len(response['serviceArns']).should.equal(2)
response['serviceArns'][0].should.equal(
'arn:aws:ecs:us-east-1:012345678910:service/test_ecs_service1')
response['serviceArns'][1].should.equal(
'arn:aws:ecs:us-east-1:012345678910:service/test_ecs_service2')
@mock_ecs
def test_describe_services():
client = boto3.client('ecs', region_name='us-east-1')
_ = client.create_cluster(
clusterName='test_ecs_cluster'
)
_ = client.register_task_definition(
family='test_ecs_task',
containerDefinitions=[
{
'name': 'hello_world',
'image': 'docker/hello-world:latest',
'cpu': 1024,
'memory': 400,
'essential': True,
'environment': [{
'name': 'AWS_ACCESS_KEY_ID',
'value': 'SOME_ACCESS_KEY'
}],
'logConfiguration': {'logDriver': 'json-file'}
}
]
)
_ = client.create_service(
cluster='test_ecs_cluster',
serviceName='test_ecs_service1',
taskDefinition='test_ecs_task',
desiredCount=2
)
_ = client.create_service(
cluster='test_ecs_cluster',
serviceName='test_ecs_service2',
taskDefinition='test_ecs_task',
desiredCount=2
)
_ = client.create_service(
cluster='test_ecs_cluster',
serviceName='test_ecs_service3',
taskDefinition='test_ecs_task',
desiredCount=2
)
response = client.describe_services(
cluster='test_ecs_cluster',
services=['test_ecs_service1',
'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_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)
@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']['taskDefinition'].should.equal(
'arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:1')
@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_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))
@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