Add Fargate support for ECS modules

Fargate instances do not require memory and cpu descriptors. EC2 instances
 do require descriptions. https://botocore.readthedocs.io/en/latest/reference/services/ecs.html#ECS.Client.describe_task_definition

Fargate requires that cpu and memory be defined at task definition level.
EC2 launch requires them to be defined at the container level.

Fargate requires the use of awsvpc for the networking_mode. Also updated,
the documentation regarding where and when memory/cpu needs to the assigned.

The task_definition variable for the awspvc configuration colided with
the ecs_service for the bridge network. This would cause the test to fail.

Add testing for fargate

Add examples for fargate and ec2
This commit is contained in:
Michael Mayer 2018-05-24 11:29:20 -07:00 committed by Will Thames
parent 8eb9cc3217
commit fbcd6f8a65
5 changed files with 307 additions and 37 deletions

View file

@ -77,21 +77,20 @@ options:
description:
- The launch type on which to run your task
required: false
version_added: 2.5
version_added: 2.7
choices: ["EC2", "FARGATE"]
default: "EC2"
cpu:
description:
- The number of cpu units used by the task. If using the EC2 launch type, this field is optional and any value can be used.
- The number of cpu units used by the task. If using the EC2 launch type, this field is optional and any value can be used.
If using the Fargate launch type, this field is required and you must use one of [256, 512, 1024, 2048, 4096]
required: false
version_added: 2.5
version_added: 2.7
memory:
description:
- The amount (in MiB) of memory used by the task. If using the EC2 launch type, this field is optional and any value can be used.
- The amount (in MiB) of memory used by the task. If using the EC2 launch type, this field is optional and any value can be used.
If using the Fargate launch type, this field is required and is limited by the cpu
required: false
version_added: 2.5
version_added: 2.7
extends_documentation_fragment:
- aws
- ec2
@ -137,6 +136,36 @@ EXAMPLES = '''
family: test-cluster-taskdef
state: present
register: task_output
- name: Create task definition
ecs_taskdefinition:
family: nginx
containers:
- name: nginx
essential: true
image: "nginx"
portMappings:
- containerPort: 8080
hostPort: 8080
cpu: 512
memory: 1GB
state: present
- name: Create task definition
ecs_taskdefinition:
family: nginx
containers:
- name: nginx
essential: true
image: "nginx"
portMappings:
- containerPort: 8080
hostPort: 8080
launch_type: FARGATE
cpu: 512
memory: 1GB
state: present
network_mode: awsvpc
'''
RETURN = '''
taskdefinition:
@ -198,13 +227,14 @@ class EcsTaskManager:
taskRoleArn=task_role_arn,
networkMode=network_mode,
containerDefinitions=container_definitions,
volumes=volumes,
requiresCompatibilities=launch_type
volumes=volumes
)
if cpu:
params['cpu'] = cpu
if memory:
params['memory'] = memory
if launch_type:
params['requiresCompatibilities'] = [launch_type]
try:
response = self.ecs.register_task_definition(**params)
@ -249,9 +279,14 @@ class EcsTaskManager:
response = self.ecs.deregister_task_definition(taskDefinition=taskArn)
return response['taskDefinition']
def ecs_api_supports_requirescompatibilities(self):
from distutils.version import LooseVersion
# Checking to make sure botocore is greater than a specific version.
# Support for requiresCompatibilities is only available in versions beyond 1.8.4
return LooseVersion(botocore.__version__) >= LooseVersion('1.8.4')
def main():
argument_spec = ec2_argument_spec()
argument_spec.update(dict(
state=dict(required=True, choices=['present', 'absent']),
@ -263,12 +298,15 @@ def main():
network_mode=dict(required=False, default='bridge', choices=['bridge', 'host', 'none', 'awsvpc'], type='str'),
task_role_arn=dict(required=False, default='', type='str'),
volumes=dict(required=False, type='list'),
launch_type=dict(required=False, choices=['EC2', 'FARGATE'], default='EC2'),
cpu=dict(required=False, type='str'),
launch_type=dict(required=False, choices=['EC2', 'FARGATE']),
cpu=dict(),
memory=dict(required=False, type='str')
))
module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True,
required_if=[('launch_type', 'FARGATE', ['cpu', 'memory'])]
)
if not HAS_BOTO3:
module.fail_json(msg='boto3 is required.')
@ -277,6 +315,10 @@ def main():
task_mgr = EcsTaskManager(module)
results = dict(changed=False)
if module.params['launch_type']:
if not task_mgr.ecs_api_supports_requirescompatibilities():
module.fail_json(msg='botocore needs to be version 1.8.4 or higher to use launch_type')
for container in module.params.get('containers', []):
for environment in container.get('environment', []):
environment['value'] = to_text(environment['value'])
@ -288,12 +330,10 @@ def main():
if 'family' not in module.params or not module.params['family']:
module.fail_json(msg="To use task definitions, a family must be specified")
network_mode = module.params['network_mode']
launch_type = module.params['launch_type']
if launch_type == 'EC2' and ('cpu' not in module.params or not module.params['cpu']):
module.fail_json(msg="To use FARGATE launch type, cpu must be specified")
if launch_type == 'EC2' and ('memory' not in module.params or not module.params['memory']):
module.fail_json(msg="To use FARGATE launch type, memory must be specified")
if launch_type == 'FARGATE' and network_mode != 'awsvpc':
module.fail_json(msg="To use FARGATE launch type, network_mode must be awsvpc")
family = module.params['family']
existing_definitions_in_family = task_mgr.describe_task_definitions(module.params['family'])