mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Add launch type to ecs task (#49081)
* adds fargate launch_type to ecs_task module * White space changes * fix documentation for running ecs task on fargate * remove extraneous example from ecs_task * White space changes * Adds changelog fragment * Pluralize minor_changes in changelog fragment * Add Stop and Start task permissions
This commit is contained in:
parent
539cab89e1
commit
b979b26a74
5 changed files with 84 additions and 9 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- adds launch type to ecs task to support fargate launch type.
|
|
@ -41,6 +41,8 @@
|
||||||
"ecs:List*",
|
"ecs:List*",
|
||||||
"ecs:RegisterTaskDefinition",
|
"ecs:RegisterTaskDefinition",
|
||||||
"ecs:RunTask",
|
"ecs:RunTask",
|
||||||
|
"ecs:StartTask",
|
||||||
|
"ecs:StopTask",
|
||||||
"ecs:UpdateService",
|
"ecs:UpdateService",
|
||||||
"elasticloadbalancing:Describe*",
|
"elasticloadbalancing:Describe*",
|
||||||
"iam:AttachRolePolicy",
|
"iam:AttachRolePolicy",
|
||||||
|
|
|
@ -60,6 +60,12 @@ options:
|
||||||
- I(network_configuration) has two keys, I(subnets), a list of subnet IDs to which the task is attached and I(security_groups),
|
- I(network_configuration) has two keys, I(subnets), a list of subnet IDs to which the task is attached and I(security_groups),
|
||||||
a list of group names or group IDs for the task
|
a list of group names or group IDs for the task
|
||||||
version_added: 2.6
|
version_added: 2.6
|
||||||
|
launch_type:
|
||||||
|
description:
|
||||||
|
- The launch type on which to run your service
|
||||||
|
required: false
|
||||||
|
version_added: 2.8
|
||||||
|
choices: ["EC2", "FARGATE"]
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- aws
|
- aws
|
||||||
- ec2
|
- ec2
|
||||||
|
@ -95,6 +101,22 @@ EXAMPLES = '''
|
||||||
- my_security_group
|
- my_security_group
|
||||||
register: task_output
|
register: task_output
|
||||||
|
|
||||||
|
- name: RUN a task on Fargate
|
||||||
|
ecs_task:
|
||||||
|
operation: run
|
||||||
|
cluster: console-sample-app-static-cluster
|
||||||
|
task_definition: console-sample-app-static-taskdef
|
||||||
|
task: "arn:aws:ecs:us-west-2:172139249013:task/3f8353d1-29a8-4689-bbf6-ad79937ffe8a"
|
||||||
|
started_by: ansible_user
|
||||||
|
launch_type: FARGATE
|
||||||
|
network_configuration:
|
||||||
|
subnets:
|
||||||
|
- subnet-abcd1234
|
||||||
|
security_groups:
|
||||||
|
- sg-aaaa1111
|
||||||
|
- my_security_group
|
||||||
|
register: task_output
|
||||||
|
|
||||||
- name: Stop a task
|
- name: Stop a task
|
||||||
ecs_task:
|
ecs_task:
|
||||||
operation: stop
|
operation: stop
|
||||||
|
@ -160,6 +182,10 @@ task:
|
||||||
description: The timestamp of when the task was stopped.
|
description: The timestamp of when the task was stopped.
|
||||||
returned: only when details is true
|
returned: only when details is true
|
||||||
type: str
|
type: str
|
||||||
|
launchType:
|
||||||
|
description: The launch type on which to run your task.
|
||||||
|
returned: always
|
||||||
|
type: str
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from ansible.module_utils.aws.core import AnsibleAWSModule
|
from ansible.module_utils.aws.core import AnsibleAWSModule
|
||||||
|
@ -208,13 +234,15 @@ class EcsExecManager:
|
||||||
return c
|
return c
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def run_task(self, cluster, task_definition, overrides, count, startedBy):
|
def run_task(self, cluster, task_definition, overrides, count, startedBy, launch_type):
|
||||||
if overrides is None:
|
if overrides is None:
|
||||||
overrides = dict()
|
overrides = dict()
|
||||||
params = dict(cluster=cluster, taskDefinition=task_definition,
|
params = dict(cluster=cluster, taskDefinition=task_definition,
|
||||||
overrides=overrides, count=count, startedBy=startedBy)
|
overrides=overrides, count=count, startedBy=startedBy)
|
||||||
if self.module.params['network_configuration']:
|
if self.module.params['network_configuration']:
|
||||||
params['networkConfiguration'] = self.format_network_configuration(self.module.params['network_configuration'])
|
params['networkConfiguration'] = self.format_network_configuration(self.module.params['network_configuration'])
|
||||||
|
if launch_type:
|
||||||
|
params['launchType'] = launch_type
|
||||||
try:
|
try:
|
||||||
response = self.ecs.run_task(**params)
|
response = self.ecs.run_task(**params)
|
||||||
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
|
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
|
||||||
|
@ -247,6 +275,13 @@ class EcsExecManager:
|
||||||
response = self.ecs.stop_task(cluster=cluster, task=task)
|
response = self.ecs.stop_task(cluster=cluster, task=task)
|
||||||
return response['task']
|
return response['task']
|
||||||
|
|
||||||
|
def ecs_api_handles_launch_type(self):
|
||||||
|
from distutils.version import LooseVersion
|
||||||
|
# There doesn't seem to be a nice way to inspect botocore to look
|
||||||
|
# for attributes (and networkConfiguration is not an explicit argument
|
||||||
|
# to e.g. ecs.run_task, it's just passed as a keyword argument)
|
||||||
|
return LooseVersion(botocore.__version__) >= LooseVersion('1.8.4')
|
||||||
|
|
||||||
def ecs_api_handles_network_configuration(self):
|
def ecs_api_handles_network_configuration(self):
|
||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
# There doesn't seem to be a nice way to inspect botocore to look
|
# There doesn't seem to be a nice way to inspect botocore to look
|
||||||
|
@ -266,10 +301,12 @@ def main():
|
||||||
task=dict(required=False, type='str'), # P*
|
task=dict(required=False, type='str'), # P*
|
||||||
container_instances=dict(required=False, type='list'), # S*
|
container_instances=dict(required=False, type='list'), # S*
|
||||||
started_by=dict(required=False, type='str'), # R S
|
started_by=dict(required=False, type='str'), # R S
|
||||||
network_configuration=dict(required=False, type='dict')
|
network_configuration=dict(required=False, type='dict'),
|
||||||
|
launch_type=dict(required=False, choices=['EC2', 'FARGATE'])
|
||||||
))
|
))
|
||||||
|
|
||||||
module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True)
|
module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True,
|
||||||
|
required_if=[('launch_type', 'FARGATE', ['network_configuration'])])
|
||||||
|
|
||||||
# Validate Inputs
|
# Validate Inputs
|
||||||
if module.params['operation'] == 'run':
|
if module.params['operation'] == 'run':
|
||||||
|
@ -295,8 +332,13 @@ def main():
|
||||||
status_type = "STOPPED"
|
status_type = "STOPPED"
|
||||||
|
|
||||||
service_mgr = EcsExecManager(module)
|
service_mgr = EcsExecManager(module)
|
||||||
|
|
||||||
if module.params['network_configuration'] and not service_mgr.ecs_api_handles_network_configuration():
|
if module.params['network_configuration'] and not service_mgr.ecs_api_handles_network_configuration():
|
||||||
module.fail_json(msg='botocore needs to be version 1.7.44 or higher to use network configuration')
|
module.fail_json(msg='botocore needs to be version 1.7.44 or higher to use network configuration')
|
||||||
|
|
||||||
|
if module.params['launch_type'] and not service_mgr.ecs_api_handles_launch_type():
|
||||||
|
module.fail_json(msg='botocore needs to be version 1.8.4 or higher to use launch type')
|
||||||
|
|
||||||
existing = service_mgr.list_tasks(module.params['cluster'], task_to_list, status_type)
|
existing = service_mgr.list_tasks(module.params['cluster'], task_to_list, status_type)
|
||||||
|
|
||||||
results = dict(changed=False)
|
results = dict(changed=False)
|
||||||
|
@ -311,7 +353,8 @@ def main():
|
||||||
module.params['task_definition'],
|
module.params['task_definition'],
|
||||||
module.params['overrides'],
|
module.params['overrides'],
|
||||||
module.params['count'],
|
module.params['count'],
|
||||||
module.params['started_by'])
|
module.params['started_by'],
|
||||||
|
module.params['launch_type'])
|
||||||
results['changed'] = True
|
results['changed'] = True
|
||||||
|
|
||||||
elif module.params['operation'] == 'start':
|
elif module.params['operation'] == 'start':
|
||||||
|
|
|
@ -5,7 +5,10 @@
|
||||||
"Sid": "",
|
"Sid": "",
|
||||||
"Effect": "Allow",
|
"Effect": "Allow",
|
||||||
"Principal": {
|
"Principal": {
|
||||||
"Service": "ecs.amazonaws.com"
|
"Service": [
|
||||||
|
"ecs.amazonaws.com",
|
||||||
|
"ecs-tasks.amazonaws.com"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"Action": "sts:AssumeRole"
|
"Action": "sts:AssumeRole"
|
||||||
}
|
}
|
||||||
|
|
|
@ -664,7 +664,7 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- ecs_fargate_task_definition_bridged_with_host_port is failed
|
- ecs_fargate_task_definition_bridged_with_host_port is failed
|
||||||
- 'ecs_fargate_task_definition_bridged_with_host_port.msg == "To use FARGATE launch type, network_mode must be awsvpc"'
|
- 'ecs_fargate_task_definition_bridged_with_host_port.msg == "To use FARGATE launch type, network_mode must be awsvpc"'
|
||||||
|
|
||||||
- name: create Fargate VPC-networked task definition without CPU or Memory (expected to Fail)
|
- name: create Fargate VPC-networked task definition without CPU or Memory (expected to Fail)
|
||||||
ecs_taskdefinition:
|
ecs_taskdefinition:
|
||||||
|
@ -681,7 +681,7 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- ecs_fargate_task_definition_vpc_no_mem is failed
|
- ecs_fargate_task_definition_vpc_no_mem is failed
|
||||||
- 'ecs_fargate_task_definition_vpc_no_mem.msg == "launch_type is FARGATE but all of the following are missing: cpu, memory"'
|
- 'ecs_fargate_task_definition_vpc_no_mem.msg == "launch_type is FARGATE but all of the following are missing: cpu, memory"'
|
||||||
|
|
||||||
- name: create Fargate VPC-networked task definition with CPU or Memory and execution role
|
- name: create Fargate VPC-networked task definition with CPU or Memory and execution role
|
||||||
ecs_taskdefinition:
|
ecs_taskdefinition:
|
||||||
|
@ -715,13 +715,13 @@
|
||||||
<<: *aws_connection_info
|
<<: *aws_connection_info
|
||||||
register: ecs_fargate_service_network_without_awsvpc
|
register: ecs_fargate_service_network_without_awsvpc
|
||||||
ignore_errors: yes
|
ignore_errors: yes
|
||||||
|
|
||||||
- name: assert that using Fargate ECS service fails
|
- name: assert that using Fargate ECS service fails
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- ecs_fargate_service_network_without_awsvpc is failed
|
- ecs_fargate_service_network_without_awsvpc is failed
|
||||||
|
|
||||||
- name: create fargate ECS service with network config
|
- name: create fargate ECS service with network config
|
||||||
ecs_service:
|
ecs_service:
|
||||||
state: present
|
state: present
|
||||||
name: "{{ ecs_service_name }}4"
|
name: "{{ ecs_service_name }}4"
|
||||||
|
@ -738,6 +738,22 @@
|
||||||
<<: *aws_connection_info
|
<<: *aws_connection_info
|
||||||
register: ecs_fargate_service_network_with_awsvpc
|
register: ecs_fargate_service_network_with_awsvpc
|
||||||
|
|
||||||
|
- name: create fargate ECS task with run task
|
||||||
|
ecs_task:
|
||||||
|
operation: run
|
||||||
|
cluster: "{{ ecs_cluster_name }}"
|
||||||
|
task_definition: "{{ ecs_task_name }}-vpc"
|
||||||
|
launch_type: FARGATE
|
||||||
|
count: 1
|
||||||
|
network_configuration:
|
||||||
|
subnets: "{{ setup_subnet.results | json_query('[].subnet.id') }}"
|
||||||
|
security_groups:
|
||||||
|
- '{{ setup_sg.group_id }}'
|
||||||
|
assign_public_ip: true
|
||||||
|
started_by: ansible_user
|
||||||
|
<<: *aws_connection_info
|
||||||
|
register: fargate_run_task_output
|
||||||
|
|
||||||
- name: assert that public IP assignment is enabled
|
- name: assert that public IP assignment is enabled
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
|
@ -879,6 +895,15 @@
|
||||||
ignore_errors: yes
|
ignore_errors: yes
|
||||||
register: ecs_service_scale_down
|
register: ecs_service_scale_down
|
||||||
|
|
||||||
|
- name: stop Fargate ECS task
|
||||||
|
ecs_task:
|
||||||
|
task: "{{ fargate_run_task_output.task[0].taskArn }}"
|
||||||
|
task_definition: "{{ ecs_task_name }}-vpc"
|
||||||
|
operation: stop
|
||||||
|
cluster: "{{ ecs_cluster_name }}"
|
||||||
|
<<: *aws_connection_info
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
- name: pause to allow services to scale down
|
- name: pause to allow services to scale down
|
||||||
pause:
|
pause:
|
||||||
seconds: 60
|
seconds: 60
|
||||||
|
|
Loading…
Reference in a new issue