1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

ecs_service: add tasks placement constraints and strategy. (#20503)

ecs_service: documentation fix.

ecs_service: updated version_added.

ecs_service: pep8 fixes.
This commit is contained in:
Andrej Svenke 2017-04-27 09:33:23 +02:00 committed by John R Barker
parent d662f6f0db
commit 3185ec94c5

View file

@ -87,6 +87,16 @@ options:
- Optional parameters that control the deployment_configuration; format is '{"maximum_percent":<integer>, "minimum_healthy_percent":<integer>} - Optional parameters that control the deployment_configuration; format is '{"maximum_percent":<integer>, "minimum_healthy_percent":<integer>}
required: false required: false
version_added: 2.3 version_added: 2.3
placement_constraints:
description:
- The placement constraints for the tasks in the service
required: false
version_added: 2.4
placement_strategy:
description:
- The placement strategy objects to use for tasks in your service. You can specify a maximum of 5 strategy rules per service
required: false
version_added: 2.4
extends_documentation_fragment: extends_documentation_fragment:
- aws - aws
- ec2 - ec2
@ -98,7 +108,7 @@ EXAMPLES = '''
state: present state: present
name: console-test-service name: console-test-service
cluster: new_cluster cluster: new_cluster
task_definition: new_cluster-task:1" task_definition: 'new_cluster-task:1'
desired_count: 0 desired_count: 0
# Basic provisioning example # Basic provisioning example
@ -113,8 +123,9 @@ EXAMPLES = '''
state: absent state: absent
cluster: new_cluster cluster: new_cluster
# With custom deployment configuration # With custom deployment configuration (added in version 2.3), placement constraints and strategy (added in version 2.4)
- ecs_service: - ecs_service:
state: present
name: test-service name: test-service
cluster: test-cluster cluster: test-cluster
task_definition: test-task-definition task_definition: test-task-definition
@ -122,7 +133,12 @@ EXAMPLES = '''
deployment_configuration: deployment_configuration:
minimum_healthy_percent: 75 minimum_healthy_percent: 75
maximum_percent: 150 maximum_percent: 150
state: present placement_constraints:
- type: memberOf
expression: 'attribute:flavor==test'
placement_strategy:
- type: binpack
field: memory
''' '''
RETURN = ''' RETURN = '''
@ -200,9 +216,38 @@ service:
returned: always returned: always
type: int type: int
events: events:
description: lost of service events description: list of service events
returned: always returned: always
type: list of complex type: list of complex
placementConstraints:
description: List of placement constraints objects
returned: always
type: list of complex
contains:
type:
description: The type of constraint. Valid values are distinctInstance and memberOf.
returned: always
type: string
expression:
description: A cluster query language expression to apply to the constraint. Note you cannot specify an expression if the constraint type is
distinctInstance.
returned: always
type: string
placementStrategy:
description: List of placement strategy objects
returned: always
type: list of complex
contains:
type:
description: The type of placement strategy. Valid values are random, spread and binpack.
returned: always
type: string
field:
description: The field to apply the placement strategy against. For the spread placement strategy, valid values are instanceId
(or host, which has the same effect), or any platform or custom attribute that is applied to a container instance,
such as attribute:ecs.availability-zone. For the binpack placement strategy, valid values are CPU and MEMORY.
returned: always
type: string
ansible_facts: ansible_facts:
description: Facts about deleted service. description: Facts about deleted service.
returned: when deleting a service returned: when deleting a service
@ -261,13 +306,11 @@ class EcsServiceManager:
def describe_service(self, cluster_name, service_name): def describe_service(self, cluster_name, service_name):
response = self.ecs.describe_services( response = self.ecs.describe_services(
cluster=cluster_name, cluster=cluster_name,
services=[ services=[service_name])
service_name
])
msg = '' msg = ''
if len(response['failures'])>0: if len(response['failures'])>0:
c = self.find_in_array(response['failures'], service_name, 'arn') c = self.find_in_array(response['failures'], service_name, 'arn')
msg += ", failure reason is "+c['reason'] msg += ", failure reason is " + c['reason']
if c and c['reason']=='MISSING': if c and c['reason']=='MISSING':
return None return None
# fall thru and look through found ones # fall thru and look through found ones
@ -289,8 +332,9 @@ class EcsServiceManager:
return True return True
def create_service(self, service_name, cluster_name, task_definition, def create_service(self, service_name, cluster_name, task_definition, load_balancers,
load_balancers, desired_count, client_token, role, deployment_configuration): desired_count, client_token, role, deployment_configuration,
placement_constraints, placement_strategy):
response = self.ecs.create_service( response = self.ecs.create_service(
cluster=cluster_name, cluster=cluster_name,
serviceName=service_name, serviceName=service_name,
@ -299,7 +343,9 @@ class EcsServiceManager:
desiredCount=desired_count, desiredCount=desired_count,
clientToken=client_token, clientToken=client_token,
role=role, role=role,
deploymentConfiguration=deployment_configuration) deploymentConfiguration=deployment_configuration,
placementConstraints=placement_constraints,
placementStrategy=placement_strategy)
return self.jsonize(response['service']) return self.jsonize(response['service'])
def update_service(self, service_name, cluster_name, task_definition, def update_service(self, service_name, cluster_name, task_definition,
@ -330,8 +376,8 @@ class EcsServiceManager:
def delete_service(self, service, cluster=None): def delete_service(self, service, cluster=None):
return self.ecs.delete_service(cluster=cluster, service=service) return self.ecs.delete_service(cluster=cluster, service=service)
def main():
def main():
argument_spec = ec2_argument_spec() argument_spec = ec2_argument_spec()
argument_spec.update(dict( argument_spec.update(dict(
state=dict(required=True, choices=['present', 'absent', 'deleting']), state=dict(required=True, choices=['present', 'absent', 'deleting']),
@ -344,7 +390,9 @@ def main():
role=dict(required=False, default='', type='str'), role=dict(required=False, default='', type='str'),
delay=dict(required=False, type='int', default=10), delay=dict(required=False, type='int', default=10),
repeat=dict(required=False, type='int', default=10), repeat=dict(required=False, type='int', default=10),
deployment_configuration=dict(required=False, default={}, type='dict') deployment_configuration=dict(required=False, default={}, type='dict'),
placement_constraints=dict(required=False, default=[], type='list'),
placement_strategy=dict(required=False, default=[], type='list')
)) ))
module = AnsibleModule(argument_spec=argument_spec, module = AnsibleModule(argument_spec=argument_spec,
@ -364,14 +412,14 @@ def main():
service_mgr = EcsServiceManager(module) service_mgr = EcsServiceManager(module)
deployment_configuration = map_complex_type(module.params['deployment_configuration'], deployment_configuration = map_complex_type(module.params['deployment_configuration'],
DEPLOYMENT_CONFIGURATION_TYPE_MAP) DEPLOYMENT_CONFIGURATION_TYPE_MAP)
deploymentConfiguration = snake_dict_to_camel_dict(deployment_configuration) deploymentConfiguration = snake_dict_to_camel_dict(deployment_configuration)
try: try:
existing = service_mgr.describe_service(module.params['cluster'], module.params['name']) existing = service_mgr.describe_service(module.params['cluster'], module.params['name'])
except Exception as e: except Exception as e:
module.fail_json(msg="Exception describing service '"+module.params['name']+"' in cluster '"+module.params['cluster']+"': "+str(e)) module.fail_json(msg="Exception describing service '" + module.params['name'] + "' in cluster '" + module.params['cluster'] + "': " + str(e))
results = dict(changed=False) results = dict(changed=False)
if module.params['state'] == 'present': if module.params['state'] == 'present':
@ -388,6 +436,10 @@ def main():
if not matching: if not matching:
if not module.check_mode: if not module.check_mode:
loadBalancers = module.params['load_balancers'] loadBalancers = module.params['load_balancers']
for loadBalancer in loadBalancers:
if 'containerPort' in loadBalancer:
loadBalancer['containerPort'] = int(loadBalancer['containerPort'])
role = module.params['role'] role = module.params['role']
clientToken = module.params['client_token'] clientToken = module.params['client_token']
@ -410,7 +462,9 @@ def main():
module.params['desired_count'], module.params['desired_count'],
clientToken, clientToken,
role, role,
deploymentConfiguration) deploymentConfiguration,
module.params['placement_constraints'],
module.params['placement_strategy'])
results['service'] = response results['service'] = response
@ -440,7 +494,7 @@ def main():
elif module.params['state'] == 'deleting': elif module.params['state'] == 'deleting':
if not existing: if not existing:
module.fail_json(msg="Service '"+module.params['name']+" not found.") module.fail_json(msg="Service '" + module.params['name'] + " not found.")
return return
# it exists, so we should delete it and mark changed. # it exists, so we should delete it and mark changed.
# return info about the cluster deleted # return info about the cluster deleted
@ -454,8 +508,8 @@ def main():
results['changed'] = True results['changed'] = True
break break
time.sleep(delay) time.sleep(delay)
if i is repeat-1: if i is repeat - 1:
module.fail_json(msg="Service still not deleted after "+str(repeat)+" tries of "+str(delay)+" seconds each.") module.fail_json(msg="Service still not deleted after " + str(repeat) + " tries of " + str(delay) + " seconds each.")
return return
module.exit_json(**results) module.exit_json(**results)