diff --git a/cloud/amazon/ecs_taskdefinition.py b/cloud/amazon/ecs_taskdefinition.py
new file mode 100644
index 00000000000..9915e9d8070
--- /dev/null
+++ b/cloud/amazon/ecs_taskdefinition.py
@@ -0,0 +1,215 @@
+#!/usr/bin/python
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see .
+
+DOCUMENTATION = '''
+---
+module: ecs_taskdefinition
+short_description: register a task definition in ecs
+description:
+ - Creates or terminates task definitions
+version_added: "1.9"
+requirements: [ json, boto, botocore, boto3 ]
+options:
+ state:
+ description:
+ - State whether the task definition should exist or be deleted
+ required: true
+ choices=['present', 'absent']
+
+ arn:
+ description:
+ - The arn of the task description to delete
+ required: false
+
+ family:
+ =dict(required=False, type='str' ),
+
+ revision:
+ required: False
+ type: int
+
+ containers:
+ required: False
+ type: list of dicts with container definitions
+
+ volumes:
+ required: False
+ type: list of name
+'''
+
+EXAMPLES = '''
+- name: "Create task definition"
+ ecs_taskdefinition:
+ containers:
+ - name: simple-app
+ cpu: 10
+ essential: true
+ image: "httpd:2.4"
+ memory: 300
+ mountPoints:
+ - containerPath: /usr/local/apache2/htdocs
+ sourceVolume: my-vol
+ portMappings:
+ - containerPort: 80
+ hostPort: 80
+ - name: busybox
+ command:
+ - "/bin/sh -c \"while true; do echo '
Amazon ECS Sample App Amazon ECS Sample App
Congratulations!
Your application is now running on a container in Amazon ECS.
' > top; /bin/date > date ; echo '
' > bottom; cat top date bottom > /usr/local/apache2/htdocs/index.html ; sleep 1; done\""
+ cpu: 10
+ entryPoint:
+ - sh
+ - "-c"
+ essential: false
+ image: busybox
+ memory: 200
+ volumesFrom:
+ - sourceContainer: simple-app
+ volumes:
+ - name: my-vol
+ family: test-cluster-taskdef
+ state: present
+ register: task_output
+'''
+RETURN = '''
+taskdefinition:
+ description: a reflection of the input parameters
+ type: dict inputs plus revision, status, taskDefinitionArn
+'''
+try:
+ import json
+ import boto
+ import botocore
+ HAS_BOTO = True
+except ImportError:
+ HAS_BOTO = False
+
+try:
+ import boto3
+ HAS_BOTO3 = True
+except ImportError:
+ HAS_BOTO3 = False
+
+class EcsTaskManager:
+ """Handles ECS Tasks"""
+
+ def __init__(self, module):
+ self.module = module
+
+ try:
+ region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
+ if not region:
+ module.fail_json(msg="Region must be specified as a parameter, in EC2_REGION or AWS_REGION environment variables or in boto configuration file")
+ self.ecs = boto3_conn(module, conn_type='client', resource='ecs', region=region, endpoint=ec2_url, **aws_connect_kwargs)
+ except boto.exception.NoAuthHandlerFound, e:
+ self.module.fail_json(msg=str(e))
+
+ def describe_task(self, task_name):
+ try:
+ response = self.ecs.describe_task_definition(taskDefinition=task_name)
+ return response['taskDefinition']
+ except botocore.exceptions.ClientError:
+ return None
+
+ def register_task(self, family, container_definitions, volumes):
+ response = self.ecs.register_task_definition(family=family,
+ containerDefinitions=container_definitions, volumes=volumes)
+ return response['taskDefinition']
+
+ def deregister_task(self, taskArn):
+ response = self.ecs.deregister_task_definition(taskDefinition=taskArn)
+ return response['taskDefinition']
+
+def main():
+
+ argument_spec = ec2_argument_spec()
+ argument_spec.update(dict(
+ state=dict(required=True, choices=['present', 'absent'] ),
+ arn=dict(required=False, type='str' ),
+ family=dict(required=False, type='str' ),
+ revision=dict(required=False, type='int' ),
+ containers=dict(required=False, type='list' ),
+ volumes=dict(required=False, type='list' )
+ ))
+
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
+
+ if not HAS_BOTO:
+ module.fail_json(msg='boto is required.')
+
+ if not HAS_BOTO3:
+ module.fail_json(msg='boto3 is required.')
+
+ task_to_describe = None
+ # When deregistering a task, we can specify the ARN OR
+ # the family and revision.
+ if module.params['state'] == 'absent':
+ if 'arn' in module.params and module.params['arn'] is not None:
+ task_to_describe = module.params['arn']
+ elif 'family' in module.params and module.params['family'] is not None and 'revision' in module.params and module.params['revision'] is not None:
+ task_to_describe = module.params['family']+":"+str(module.params['revision'])
+ else:
+ module.fail_json(msg="To use task definitions, an arn or family and revision must be specified")
+ # When registering a task, we can specify the ARN OR
+ # the family and revision.
+ if module.params['state'] == 'present':
+ if not 'family' in module.params:
+ module.fail_json(msg="To use task definitions, a family must be specified")
+ if not 'containers' in module.params:
+ module.fail_json(msg="To use task definitions, a list of containers must be specified")
+ task_to_describe = module.params['family']
+
+ task_mgr = EcsTaskManager(module)
+ existing = task_mgr.describe_task(task_to_describe)
+
+ results = dict(changed=False)
+ if module.params['state'] == 'present':
+ if existing and 'status' in existing and existing['status']=="ACTIVE":
+ results['taskdefinition']=existing
+ else:
+ if not module.check_mode:
+ # doesn't exist. create it.
+ volumes = []
+ if 'volumes' in module.params:
+ volumes = module.params['volumes']
+ if volumes is None:
+ volumes = []
+ results['taskdefinition'] = task_mgr.register_task(module.params['family'],
+ module.params['containers'], volumes)
+ results['changed'] = True
+
+ # delete the cloudtrai
+ elif module.params['state'] == 'absent':
+ if not existing:
+ pass
+ else:
+ # it exists, so we should delete it and mark changed.
+ # return info about the cluster deleted
+ results['taskdefinition'] = existing
+ if 'status' in existing and existing['status']=="INACTIVE":
+ results['changed'] = False
+ else:
+ if not module.check_mode:
+ task_mgr.deregister_task(task_to_describe)
+ results['changed'] = True
+
+ module.exit_json(**results)
+
+# import module snippets
+from ansible.module_utils.basic import *
+from ansible.module_utils.ec2 import *
+
+if __name__ == '__main__':
+ main()
diff --git a/cloud/amazon/ecs_taskdefinition_facts.py b/cloud/amazon/ecs_taskdefinition_facts.py
new file mode 100644
index 00000000000..c351639513f
--- /dev/null
+++ b/cloud/amazon/ecs_taskdefinition_facts.py
@@ -0,0 +1,173 @@
+#!/usr/bin/python
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see .
+
+DOCUMENTATION = '''
+---
+module: ecs_taskdefinition_facts
+short_description: return facts about task definitions in ecs
+description:
+ - Describes or lists task definitions.
+version_added: 1.9
+requirements: [ json, os, boto, botocore, boto3 ]
+options:
+ details:
+ description:
+ - Set this to true if you want detailed information about the tasks.
+ required: false
+ default: false
+ name:
+ description:
+ - When details is true, the name must be provided.
+ required: false
+ family:
+ description:
+ - the name of the family of task definitions to list.
+ required: false
+ max_results:
+ description:
+ - The maximum number of results to return.
+ required: false
+ status:
+ description:
+ - Show only task descriptions of the given status. If omitted, it shows all
+ required: false
+ choices: ['ACTIVE', 'INACTIVE']
+ sort:
+ description:
+ - Sort order of returned list of task definitions
+ required: false
+ choices: ['ASC', 'DESC']
+
+'''
+
+EXAMPLES = '''
+# Note: These examples do not set authentication details, see the AWS Guide for details.
+
+# Basic listing example
+- name: "Get task definitions with details"
+ ecs_taskdefinition_facts:
+ name: test-cluster-tasks
+ details: true
+
+- name: Get task definitions with details
+ ecs_taskdefinition_facts:
+ status: INACTIVE
+ details: true
+ family: test-cluster-rbjgjoaj-task
+ name: "arn:aws:ecs:us-west-2:172139249013:task-definition/test-cluster-rbjgjoaj-task:1"
+'''
+RETURN = '''
+task_definitions:
+ description: array of ARN values for the known task definitions
+ type: array of string or dict if details is true
+ sample: ["arn:aws:ecs:us-west-2:172139249013:task-definition/console-sample-app-static:1"]
+'''
+try:
+ import json, os
+ import boto
+ import botocore
+ # import module snippets
+ from ansible.module_utils.basic import *
+ from ansible.module_utils.ec2 import *
+ HAS_BOTO = True
+except ImportError:
+ HAS_BOTO = False
+
+try:
+ import boto3
+ HAS_BOTO3 = True
+except ImportError:
+ HAS_BOTO3 = False
+
+class EcsTaskManager:
+ """Handles ECS Tasks"""
+
+ def __init__(self, module):
+ self.module = module
+
+ try:
+ # self.ecs = boto3.client('ecs')
+ region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
+ if not region:
+ module.fail_json(msg="Region must be specified as a parameter, in EC2_REGION or AWS_REGION environment variables or in boto configuration file")
+ self.ecs = boto3_conn(module, conn_type='client', resource='ecs', region=region, endpoint=ec2_url, **aws_connect_kwargs)
+ except boto.exception.NoAuthHandlerFound, e:
+ self.module.fail_json(msg=str(e))
+
+ def transmogrify(self, params, field, dictionary, arg_name):
+ if field in params and params[field] is not None:
+ dictionary[arg_name] = params[field]
+
+ def list_taskdefinitions(self, params):
+ fn_args = dict()
+ self.transmogrify(params, 'family', fn_args, 'familyPrefix')
+ self.transmogrify(params, 'max_results', fn_args, 'maxResults')
+ self.transmogrify(params, 'status', fn_args, 'status')
+ self.transmogrify(params, 'sort', fn_args, 'sort')
+ response = self.ecs.list_task_definitions(**fn_args)
+ return dict(task_definitions=response['taskDefinitionArns'])
+
+ def describe_taskdefinition(self, task_definition):
+ try:
+ response = self.ecs.describe_task_definition(taskDefinition=task_definition)
+ except botocore.exceptions.ClientError:
+ response = dict(taskDefinition=[ dict( name=task_definition, status="MISSING")])
+ relevant_response = dict(
+ task_definitions = response['taskDefinition']
+ )
+ return relevant_response
+
+def main():
+
+ argument_spec = ec2_argument_spec()
+ argument_spec.update(dict(
+ details=dict(required= False, type='bool' ),
+ name=dict(required=False, type='str' ),
+ family=dict(required=False, type='str' ),
+ max_results=dict(required=False, type='int' ),
+ status=dict(required=False, choices=['ACTIVE', 'INACTIVE']),
+ sort=dict(required=False, choices=['ASC', 'DESC'])
+ ))
+
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
+
+ if not HAS_BOTO:
+ module.fail_json(msg='boto is required.')
+
+ if not HAS_BOTO3:
+ module.fail_json(msg='boto3 is required.')
+
+ show_details = False
+ if 'details' in module.params and module.params['details']:
+ if 'name' not in module.params or not module.params['name']:
+ module.fail_json(msg="task definition name must be specified for ecs_taskdefinition_facts")
+ show_details = True
+
+ task_mgr = EcsTaskManager(module)
+ if show_details:
+ ecs_facts = task_mgr.describe_taskdefinition(module.params['name'])
+ else:
+ ecs_facts = task_mgr.list_taskdefinitions(module.params)
+ ecs_facts_result = dict(changed=False, ansible_facts=ecs_facts)
+ module.exit_json(**ecs_facts_result)
+
+# import module snippets
+from ansible.module_utils.basic import *
+from ansible.module_utils.ec2 import *
+from ansible.module_utils.urls import *
+
+if __name__ == '__main__':
+ main()