commit
3a2eedc03c
@ -73,6 +73,8 @@ It gets even better! Moto isn't just S3. Here's the status of the other AWS serv
|
|||||||
| - Security Groups | | core endpoints done |
|
| - Security Groups | | core endpoints done |
|
||||||
| - Tags | | all endpoints done |
|
| - Tags | | all endpoints done |
|
||||||
|------------------------------------------------------------------------------|
|
|------------------------------------------------------------------------------|
|
||||||
|
| ECS | @mock_ecs | basic endpoints done |
|
||||||
|
|------------------------------------------------------------------------------|
|
||||||
| ELB | @mock_elb | core endpoints done |
|
| ELB | @mock_elb | core endpoints done |
|
||||||
|------------------------------------------------------------------------------|
|
|------------------------------------------------------------------------------|
|
||||||
| EMR | @mock_emr | core endpoints done |
|
| EMR | @mock_emr | core endpoints done |
|
||||||
|
@ -12,6 +12,7 @@ from .datapipeline import mock_datapipeline # flake8: noqa
|
|||||||
from .dynamodb import mock_dynamodb # flake8: noqa
|
from .dynamodb import mock_dynamodb # flake8: noqa
|
||||||
from .dynamodb2 import mock_dynamodb2 # flake8: noqa
|
from .dynamodb2 import mock_dynamodb2 # flake8: noqa
|
||||||
from .ec2 import mock_ec2 # flake8: noqa
|
from .ec2 import mock_ec2 # flake8: noqa
|
||||||
|
from .ecs import mock_ecs # flake8: noqa
|
||||||
from .elb import mock_elb # flake8: noqa
|
from .elb import mock_elb # flake8: noqa
|
||||||
from .emr import mock_emr # flake8: noqa
|
from .emr import mock_emr # flake8: noqa
|
||||||
from .glacier import mock_glacier # flake8: noqa
|
from .glacier import mock_glacier # flake8: noqa
|
||||||
|
@ -10,6 +10,10 @@ class AutoScalingResponse(BaseResponse):
|
|||||||
def autoscaling_backend(self):
|
def autoscaling_backend(self):
|
||||||
return autoscaling_backends[self.region]
|
return autoscaling_backends[self.region]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def boto3_request(self):
|
||||||
|
return 'Boto3' in self.headers.get('User-Agent', [])
|
||||||
|
|
||||||
def create_launch_configuration(self):
|
def create_launch_configuration(self):
|
||||||
instance_monitoring_string = self._get_param('InstanceMonitoring.Enabled')
|
instance_monitoring_string = self._get_param('InstanceMonitoring.Enabled')
|
||||||
if instance_monitoring_string == 'true':
|
if instance_monitoring_string == 'true':
|
||||||
@ -68,6 +72,11 @@ class AutoScalingResponse(BaseResponse):
|
|||||||
def describe_auto_scaling_groups(self):
|
def describe_auto_scaling_groups(self):
|
||||||
names = self._get_multi_param("AutoScalingGroupNames.member")
|
names = self._get_multi_param("AutoScalingGroupNames.member")
|
||||||
groups = self.autoscaling_backend.describe_autoscaling_groups(names)
|
groups = self.autoscaling_backend.describe_autoscaling_groups(names)
|
||||||
|
if self.boto3_request:
|
||||||
|
for group in groups:
|
||||||
|
if group.health_check_period is None:
|
||||||
|
group.health_check_period = 300
|
||||||
|
self.autoscaling_backend.autoscaling_groups[group.name] = group
|
||||||
template = self.response_template(DESCRIBE_AUTOSCALING_GROUPS_TEMPLATE)
|
template = self.response_template(DESCRIBE_AUTOSCALING_GROUPS_TEMPLATE)
|
||||||
return template.render(groups=groups)
|
return template.render(groups=groups)
|
||||||
|
|
||||||
|
11
moto/ecs/__init__.py
Normal file
11
moto/ecs/__init__.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
from .models import ecs_backends
|
||||||
|
from ..core.models import MockAWS
|
||||||
|
|
||||||
|
ecs_backend = ecs_backends['us-east-1']
|
||||||
|
|
||||||
|
def mock_ecs(func=None):
|
||||||
|
if func:
|
||||||
|
return MockAWS(ecs_backends)(func)
|
||||||
|
else:
|
||||||
|
return MockAWS(ecs_backends)
|
204
moto/ecs/models.py
Normal file
204
moto/ecs/models.py
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from moto.core import BaseBackend
|
||||||
|
from moto.ec2 import ec2_backends
|
||||||
|
|
||||||
|
|
||||||
|
class BaseObject(object):
|
||||||
|
def camelCase(self, key):
|
||||||
|
words = []
|
||||||
|
for i, word in enumerate(key.split('_')):
|
||||||
|
if i > 0:
|
||||||
|
words.append(word.title())
|
||||||
|
else:
|
||||||
|
words.append(word)
|
||||||
|
return ''.join(words)
|
||||||
|
|
||||||
|
def gen_response_object(self):
|
||||||
|
response_object = self.__dict__.copy()
|
||||||
|
for key, value in response_object.items():
|
||||||
|
if '_' in key:
|
||||||
|
response_object[self.camelCase(key)] = value
|
||||||
|
del response_object[key]
|
||||||
|
return response_object
|
||||||
|
|
||||||
|
@property
|
||||||
|
def response_object(self):
|
||||||
|
return self.gen_response_object()
|
||||||
|
|
||||||
|
|
||||||
|
class Cluster(BaseObject):
|
||||||
|
def __init__(self, cluster_name):
|
||||||
|
self.active_services_count = 0
|
||||||
|
self.arn = 'arn:aws:ecs:us-east-1:012345678910:cluster/{0}'.format(cluster_name)
|
||||||
|
self.name = cluster_name
|
||||||
|
self.pending_tasks_count = 0
|
||||||
|
self.registered_container_instances_count = 0
|
||||||
|
self.running_tasks_count = 0
|
||||||
|
self.status = 'ACTIVE'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def response_object(self):
|
||||||
|
response_object = self.gen_response_object()
|
||||||
|
response_object['clusterArn'] = self.arn
|
||||||
|
response_object['clusterName'] = self.name
|
||||||
|
del response_object['arn'], response_object['name']
|
||||||
|
return response_object
|
||||||
|
|
||||||
|
|
||||||
|
class TaskDefinition(BaseObject):
|
||||||
|
def __init__(self, family, revision, container_definitions, volumes=None):
|
||||||
|
self.family = family
|
||||||
|
self.arn = 'arn:aws:ecs:us-east-1:012345678910:task-definition/{0}:{1}'.format(family, revision)
|
||||||
|
self.container_definitions = container_definitions
|
||||||
|
if volumes is not None:
|
||||||
|
self.volumes = volumes
|
||||||
|
|
||||||
|
@property
|
||||||
|
def response_object(self):
|
||||||
|
response_object = self.gen_response_object()
|
||||||
|
response_object['taskDefinitionArn'] = response_object['arn']
|
||||||
|
del response_object['arn']
|
||||||
|
return response_object
|
||||||
|
|
||||||
|
|
||||||
|
class Service(BaseObject):
|
||||||
|
def __init__(self, cluster, service_name, task_definition, desired_count):
|
||||||
|
self.cluster_arn = cluster.arn
|
||||||
|
self.arn = 'arn:aws:ecs:us-east-1:012345678910:service/{0}'.format(service_name)
|
||||||
|
self.name = service_name
|
||||||
|
self.status = 'ACTIVE'
|
||||||
|
self.running_count = 0
|
||||||
|
self.task_definition = task_definition.arn
|
||||||
|
self.desired_count = desired_count
|
||||||
|
self.events = []
|
||||||
|
self.load_balancers = []
|
||||||
|
self.pending_count = 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def response_object(self):
|
||||||
|
response_object = self.gen_response_object()
|
||||||
|
del response_object['name'], response_object['arn']
|
||||||
|
response_object['serviceName'] = self.name
|
||||||
|
response_object['serviceArn'] = self.arn
|
||||||
|
return response_object
|
||||||
|
|
||||||
|
|
||||||
|
class EC2ContainerServiceBackend(BaseBackend):
|
||||||
|
def __init__(self):
|
||||||
|
self.clusters = {}
|
||||||
|
self.task_definitions = {}
|
||||||
|
self.services = {}
|
||||||
|
|
||||||
|
def fetch_task_definition(self, task_definition_str):
|
||||||
|
task_definition_components = task_definition_str.split(':')
|
||||||
|
if len(task_definition_components) == 2:
|
||||||
|
family, revision = task_definition_components
|
||||||
|
revision = int(revision)
|
||||||
|
else:
|
||||||
|
family = task_definition_components[0]
|
||||||
|
revision = -1
|
||||||
|
if family in self.task_definitions and 0 < revision <= len(self.task_definitions[family]):
|
||||||
|
return self.task_definitions[family][revision - 1]
|
||||||
|
elif family in self.task_definitions and revision == -1:
|
||||||
|
return self.task_definitions[family][revision]
|
||||||
|
else:
|
||||||
|
raise Exception("{0} is not a task_definition".format(task_definition_str))
|
||||||
|
|
||||||
|
def create_cluster(self, cluster_name):
|
||||||
|
cluster = Cluster(cluster_name)
|
||||||
|
self.clusters[cluster_name] = cluster
|
||||||
|
return cluster
|
||||||
|
|
||||||
|
def list_clusters(self):
|
||||||
|
"""
|
||||||
|
maxSize and pagination not implemented
|
||||||
|
"""
|
||||||
|
return [cluster.arn for cluster in self.clusters.values()]
|
||||||
|
|
||||||
|
def delete_cluster(self, cluster_str):
|
||||||
|
cluster_name = cluster_str.split('/')[-1]
|
||||||
|
if cluster_name in self.clusters:
|
||||||
|
return self.clusters.pop(cluster_name)
|
||||||
|
else:
|
||||||
|
raise Exception("{0} is not a cluster".format(cluster_name))
|
||||||
|
|
||||||
|
def register_task_definition(self, family, container_definitions, volumes):
|
||||||
|
if family in self.task_definitions:
|
||||||
|
revision = len(self.task_definitions[family]) + 1
|
||||||
|
else:
|
||||||
|
self.task_definitions[family] = []
|
||||||
|
revision = 1
|
||||||
|
task_definition = TaskDefinition(family, revision, container_definitions, volumes)
|
||||||
|
self.task_definitions[family].append(task_definition)
|
||||||
|
|
||||||
|
return task_definition
|
||||||
|
|
||||||
|
def list_task_definitions(self):
|
||||||
|
"""
|
||||||
|
Filtering not implemented
|
||||||
|
"""
|
||||||
|
task_arns = []
|
||||||
|
for task_definition_list in self.task_definitions.values():
|
||||||
|
task_arns.extend([task_definition.arn for task_definition in task_definition_list])
|
||||||
|
return task_arns
|
||||||
|
|
||||||
|
def deregister_task_definition(self, task_definition_str):
|
||||||
|
task_definition_name = task_definition_str.split('/')[-1]
|
||||||
|
family, revision = task_definition_name.split(':')
|
||||||
|
revision = int(revision)
|
||||||
|
if family in self.task_definitions and 0 < revision <= len(self.task_definitions[family]):
|
||||||
|
return self.task_definitions[family].pop(revision - 1)
|
||||||
|
else:
|
||||||
|
raise Exception("{0} is not a task_definition".format(task_definition_name))
|
||||||
|
|
||||||
|
def create_service(self, cluster_str, service_name, task_definition_str, desired_count):
|
||||||
|
cluster_name = cluster_str.split('/')[-1]
|
||||||
|
if cluster_name in self.clusters:
|
||||||
|
cluster = self.clusters[cluster_name]
|
||||||
|
else:
|
||||||
|
raise Exception("{0} is not a cluster".format(cluster_name))
|
||||||
|
task_definition = self.fetch_task_definition(task_definition_str)
|
||||||
|
desired_count = desired_count if desired_count is not None else 0
|
||||||
|
service = Service(cluster, service_name, task_definition, desired_count)
|
||||||
|
cluster_service_pair = '{0}:{1}'.format(cluster_name, service_name)
|
||||||
|
self.services[cluster_service_pair] = service
|
||||||
|
return service
|
||||||
|
|
||||||
|
def list_services(self, cluster_str):
|
||||||
|
cluster_name = cluster_str.split('/')[-1]
|
||||||
|
service_arns = []
|
||||||
|
for key, value in self.services.items():
|
||||||
|
if cluster_name + ':' in key:
|
||||||
|
service_arns.append(self.services[key].arn)
|
||||||
|
return sorted(service_arns)
|
||||||
|
|
||||||
|
def update_service(self, cluster_str, service_name, task_definition_str, desired_count):
|
||||||
|
cluster_name = cluster_str.split('/')[-1]
|
||||||
|
cluster_service_pair = '{0}:{1}'.format(cluster_name, service_name)
|
||||||
|
if cluster_service_pair in self.services:
|
||||||
|
if task_definition_str is not None:
|
||||||
|
task_definition = self.fetch_task_definition(task_definition_str)
|
||||||
|
self.services[cluster_service_pair].task_definition = task_definition
|
||||||
|
if desired_count is not None:
|
||||||
|
self.services[cluster_service_pair].desired_count = desired_count
|
||||||
|
return self.services[cluster_service_pair]
|
||||||
|
else:
|
||||||
|
raise Exception("cluster {0} or service {1} does not exist".format(cluster_name, service_name))
|
||||||
|
|
||||||
|
def delete_service(self, cluster_name, service_name):
|
||||||
|
cluster_service_pair = '{0}:{1}'.format(cluster_name, service_name)
|
||||||
|
if cluster_service_pair in self.services:
|
||||||
|
service = self.services[cluster_service_pair]
|
||||||
|
if service.desired_count > 0:
|
||||||
|
raise Exception("Service must have desiredCount=0")
|
||||||
|
else:
|
||||||
|
return self.services.pop(cluster_service_pair)
|
||||||
|
else:
|
||||||
|
raise Exception("cluster {0} or service {1} does not exist".format(cluster_name, service_name))
|
||||||
|
|
||||||
|
|
||||||
|
ecs_backends = {}
|
||||||
|
for region, ec2_backend in ec2_backends.items():
|
||||||
|
ecs_backends[region] = EC2ContainerServiceBackend()
|
102
moto/ecs/responses.py
Normal file
102
moto/ecs/responses.py
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import json
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from moto.core.responses import BaseResponse
|
||||||
|
from .models import ecs_backends
|
||||||
|
|
||||||
|
|
||||||
|
class EC2ContainerServiceResponse(BaseResponse):
|
||||||
|
@property
|
||||||
|
def ecs_backend(self):
|
||||||
|
return ecs_backends[self.region]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def request_params(self):
|
||||||
|
try:
|
||||||
|
return json.loads(self.body.decode())
|
||||||
|
except ValueError:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def _get_param(self, param):
|
||||||
|
return self.request_params.get(param, None)
|
||||||
|
|
||||||
|
def create_cluster(self):
|
||||||
|
cluster_name = self._get_param('clusterName')
|
||||||
|
cluster = self.ecs_backend.create_cluster(cluster_name)
|
||||||
|
return json.dumps({
|
||||||
|
'cluster': cluster.response_object
|
||||||
|
})
|
||||||
|
|
||||||
|
def list_clusters(self):
|
||||||
|
cluster_arns = self.ecs_backend.list_clusters()
|
||||||
|
return json.dumps({
|
||||||
|
'clusterArns': cluster_arns,
|
||||||
|
'nextToken': str(uuid.uuid1())
|
||||||
|
})
|
||||||
|
|
||||||
|
def delete_cluster(self):
|
||||||
|
cluster_str = self._get_param('cluster')
|
||||||
|
cluster = self.ecs_backend.delete_cluster(cluster_str)
|
||||||
|
return json.dumps({
|
||||||
|
'cluster': cluster.response_object
|
||||||
|
})
|
||||||
|
|
||||||
|
def register_task_definition(self):
|
||||||
|
family = self._get_param('family')
|
||||||
|
container_definitions = self._get_param('containerDefinitions')
|
||||||
|
volumes = self._get_param('volumes')
|
||||||
|
task_definition = self.ecs_backend.register_task_definition(family, container_definitions, volumes)
|
||||||
|
return json.dumps({
|
||||||
|
'taskDefinition': task_definition.response_object
|
||||||
|
})
|
||||||
|
|
||||||
|
def list_task_definitions(self):
|
||||||
|
task_definition_arns = self.ecs_backend.list_task_definitions()
|
||||||
|
return json.dumps({
|
||||||
|
'taskDefinitionArns': task_definition_arns,
|
||||||
|
'nextToken': str(uuid.uuid1())
|
||||||
|
})
|
||||||
|
|
||||||
|
def deregister_task_definition(self):
|
||||||
|
task_definition_str = self._get_param('taskDefinition')
|
||||||
|
task_definition = self.ecs_backend.deregister_task_definition(task_definition_str)
|
||||||
|
return json.dumps({
|
||||||
|
'taskDefinition': task_definition.response_object
|
||||||
|
})
|
||||||
|
|
||||||
|
def create_service(self):
|
||||||
|
cluster_str = self._get_param('cluster')
|
||||||
|
service_name = self._get_param('serviceName')
|
||||||
|
task_definition_str = self._get_param('taskDefinition')
|
||||||
|
desired_count = self._get_int_param('desiredCount')
|
||||||
|
service = self.ecs_backend.create_service(cluster_str, service_name, task_definition_str, desired_count)
|
||||||
|
return json.dumps({
|
||||||
|
'service': service.response_object
|
||||||
|
})
|
||||||
|
|
||||||
|
def list_services(self):
|
||||||
|
cluster_str = self._get_param('cluster')
|
||||||
|
service_arns = self.ecs_backend.list_services(cluster_str)
|
||||||
|
return json.dumps({
|
||||||
|
'serviceArns': service_arns,
|
||||||
|
'nextToken': str(uuid.uuid1())
|
||||||
|
})
|
||||||
|
|
||||||
|
def update_service(self):
|
||||||
|
cluster_str = self._get_param('cluster')
|
||||||
|
service_name = self._get_param('service')
|
||||||
|
task_definition = self._get_param('taskDefinition')
|
||||||
|
desired_count = self._get_int_param('desiredCount')
|
||||||
|
service = self.ecs_backend.update_service(cluster_str, service_name, task_definition, desired_count)
|
||||||
|
return json.dumps({
|
||||||
|
'service': service.response_object
|
||||||
|
})
|
||||||
|
|
||||||
|
def delete_service(self):
|
||||||
|
service_name = self._get_param('service')
|
||||||
|
cluster_name = self._get_param('cluster')
|
||||||
|
service = self.ecs_backend.delete_service(cluster_name, service_name)
|
||||||
|
return json.dumps({
|
||||||
|
'service': service.response_object
|
||||||
|
})
|
10
moto/ecs/urls.py
Normal file
10
moto/ecs/urls.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
from .responses import EC2ContainerServiceResponse
|
||||||
|
|
||||||
|
url_bases = [
|
||||||
|
"https?://ecs.(.+).amazonaws.com",
|
||||||
|
]
|
||||||
|
|
||||||
|
url_paths = {
|
||||||
|
'{0}/$': EC2ContainerServiceResponse.dispatch,
|
||||||
|
}
|
41
tests/test_autoscaling/test_autoscaling_boto3.py
Normal file
41
tests/test_autoscaling/test_autoscaling_boto3.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import boto3
|
||||||
|
import sure # noqa
|
||||||
|
|
||||||
|
from moto import mock_autoscaling
|
||||||
|
|
||||||
|
|
||||||
|
@mock_autoscaling
|
||||||
|
def test_create_autoscaling_group():
|
||||||
|
client = boto3.client('autoscaling', region_name='us-east-1')
|
||||||
|
_ = client.create_launch_configuration(
|
||||||
|
LaunchConfigurationName='test_launch_configuration'
|
||||||
|
)
|
||||||
|
response = client.create_auto_scaling_group(
|
||||||
|
AutoScalingGroupName='test_asg',
|
||||||
|
LaunchConfigurationName='test_launch_configuration',
|
||||||
|
MinSize=0,
|
||||||
|
MaxSize=20,
|
||||||
|
DesiredCapacity=5
|
||||||
|
)
|
||||||
|
response['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_autoscaling
|
||||||
|
def test_describe_autoscaling_groups():
|
||||||
|
client = boto3.client('autoscaling', region_name='us-east-1')
|
||||||
|
_ = client.create_launch_configuration(
|
||||||
|
LaunchConfigurationName='test_launch_configuration'
|
||||||
|
)
|
||||||
|
_ = client.create_auto_scaling_group(
|
||||||
|
AutoScalingGroupName='test_asg',
|
||||||
|
LaunchConfigurationName='test_launch_configuration',
|
||||||
|
MinSize=0,
|
||||||
|
MaxSize=20,
|
||||||
|
DesiredCapacity=5
|
||||||
|
)
|
||||||
|
response = client.describe_auto_scaling_groups(
|
||||||
|
AutoScalingGroupNames=["test_asg"]
|
||||||
|
)
|
||||||
|
response['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
||||||
|
response['AutoScalingGroups'][0]['AutoScalingGroupName'].should.equal('test_asg')
|
23
tests/test_autoscaling/test_launch_configurations_boto3.py
Normal file
23
tests/test_autoscaling/test_launch_configurations_boto3.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
import sure # noqa
|
||||||
|
|
||||||
|
from moto import mock_autoscaling
|
||||||
|
|
||||||
|
|
||||||
|
@mock_autoscaling
|
||||||
|
def test_create_launch_configuration():
|
||||||
|
client = boto3.client('autoscaling', region_name='us-east-1')
|
||||||
|
response = client.create_launch_configuration(
|
||||||
|
LaunchConfigurationName='tester',
|
||||||
|
ImageId='ami-abcd1234',
|
||||||
|
InstanceType='t1.micro',
|
||||||
|
KeyName='the_keys',
|
||||||
|
SecurityGroups=["default", "default2"],
|
||||||
|
UserData="This is some user_data",
|
||||||
|
InstanceMonitoring={'Enabled': True},
|
||||||
|
IamInstanceProfile='arn:aws:iam::123456789012:instance-profile/testing',
|
||||||
|
SpotPrice='0.1'
|
||||||
|
)
|
||||||
|
response['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
336
tests/test_ecs/test_ecs_boto3.py
Normal file
336
tests/test_ecs/test_ecs_boto3.py
Normal file
@ -0,0 +1,336 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import boto3
|
||||||
|
import sure # noqa
|
||||||
|
|
||||||
|
from moto import mock_ecs
|
||||||
|
|
||||||
|
|
||||||
|
@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']['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_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_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',
|
||||||
|
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')
|
Loading…
x
Reference in New Issue
Block a user