From 3fae6ffe7c782fc7ad3dbd51d76d2aff30897dd6 Mon Sep 17 00:00:00 2001 From: Feng Zhou Date: Wed, 23 Nov 2022 12:14:42 +0800 Subject: [PATCH 01/10] Support ecs service constraints and strategy update. --- plugins/modules/ecs_service.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/plugins/modules/ecs_service.py b/plugins/modules/ecs_service.py index 93abbe75a7b..7ce7545ab68 100644 --- a/plugins/modules/ecs_service.py +++ b/plugins/modules/ecs_service.py @@ -819,14 +819,22 @@ def create_service(self, service_name, cluster_name, task_definition, load_balan response = self.ecs.create_service(**params) return self.jsonize(response['service']) - def update_service(self, service_name, cluster_name, task_definition, - desired_count, deployment_configuration, network_configuration, - health_check_grace_period_seconds, force_new_deployment, capacity_provider_strategy): + def update_service(self, service_name, cluster_name, task_definition, desired_count, + deployment_configuration, placement_constraints, placement_strategy, + network_configuration, health_check_grace_period_seconds, + force_new_deployment, capacity_provider_strategy): params = dict( cluster=cluster_name, service=service_name, taskDefinition=task_definition, deploymentConfiguration=deployment_configuration) + # filter placement_constraint and left only those where value is not None + # use-case: `distinctInstance` type should never contain `expression`, but None will fail `str` type validation + if placement_constraints: + params['placementConstraints'] = [{key: value for key, value in constraint.items() if value is not None} + for constraint in placement_constraints] + if placement_strategy: + params['placementStrategy'] = placement_strategy if network_configuration: params['networkConfiguration'] = network_configuration if force_new_deployment: From b234b4ff8a13e307de73d13530b66e4f1b88d2ff Mon Sep 17 00:00:00 2001 From: Feng Zhou Date: Wed, 23 Nov 2022 14:17:30 +0800 Subject: [PATCH 02/10] Add placement_constraints and placement_strategy parameters when call ecs update_service. --- plugins/modules/ecs_service.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/modules/ecs_service.py b/plugins/modules/ecs_service.py index 7ce7545ab68..a438260463b 100644 --- a/plugins/modules/ecs_service.py +++ b/plugins/modules/ecs_service.py @@ -665,7 +665,6 @@ 'minimum_healthy_percent': 'int', 'deployment_circuit_breaker': 'dict', } - from ansible.module_utils.common.dict_transformations import snake_dict_to_camel_dict from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule @@ -1046,6 +1045,8 @@ def main(): task_definition, module.params['desired_count'], deploymentConfiguration, + module.params['placement_constraints'], + module.params['placement_strategy'], network_configuration, module.params['health_check_grace_period_seconds'], module.params['force_new_deployment'], From 1b565cff8ba660e2eb7488d7555d6b1b816fdaf1 Mon Sep 17 00:00:00 2001 From: Feng Zhou Date: Wed, 23 Nov 2022 14:21:24 +0800 Subject: [PATCH 03/10] Add empty line. --- plugins/modules/ecs_service.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/ecs_service.py b/plugins/modules/ecs_service.py index a438260463b..eb19f8e2b36 100644 --- a/plugins/modules/ecs_service.py +++ b/plugins/modules/ecs_service.py @@ -665,6 +665,7 @@ 'minimum_healthy_percent': 'int', 'deployment_circuit_breaker': 'dict', } + from ansible.module_utils.common.dict_transformations import snake_dict_to_camel_dict from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule From e6e37851f61d313a944a3df07bdc95e435e3d3f7 Mon Sep 17 00:00:00 2001 From: Feng Zhou Date: Wed, 23 Nov 2022 15:18:39 +0800 Subject: [PATCH 04/10] Add changelog fragment. --- ...1601-ecs_service-support_constraints_and_strategy_update.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelogs/fragments/1601-ecs_service-support_constraints_and_strategy_update.yml diff --git a/changelogs/fragments/1601-ecs_service-support_constraints_and_strategy_update.yml b/changelogs/fragments/1601-ecs_service-support_constraints_and_strategy_update.yml new file mode 100644 index 00000000000..e608fc4e8b3 --- /dev/null +++ b/changelogs/fragments/1601-ecs_service-support_constraints_and_strategy_update.yml @@ -0,0 +1,2 @@ +bugfixes: + - ecs_service supports constraints and strategy update (https://github.com/ansible-collections/community.aws/pull/1601). From 47aeab028848e318ec38b5fff6c500e51093d1ab Mon Sep 17 00:00:00 2001 From: Feng Zhou Date: Mon, 28 Nov 2022 17:26:48 +0800 Subject: [PATCH 05/10] Add integration test cases. --- .../targets/ecs_cluster/tasks/main.yml | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/tests/integration/targets/ecs_cluster/tasks/main.yml b/tests/integration/targets/ecs_cluster/tasks/main.yml index 57a010a5bdb..d105d087d08 100644 --- a/tests/integration/targets/ecs_cluster/tasks/main.yml +++ b/tests/integration/targets/ecs_cluster/tasks/main.yml @@ -598,6 +598,104 @@ that: - ecs_task_definition_constraints_delete is not changed + - name: Create ecs service with placement constraints + ecs_service: + name: "{{ ecs_service_name }}-constraint" + cluster: "{{ ecs_cluster_name }}" + load_balancers: + - targetGroupArn: "{{ elb_target_group_instance.target_group_arn }}" + containerName: "{{ ecs_task_name }}" + containerPort: "{{ ecs_task_container_port }}" + task_definition: "{{ ecs_task_name }}:{{ ecs_task_definition.taskdefinition.revision }}" + scheduling_strategy: "REPLICA" + placement_constraints: + - type: distinctInstance + desired_count: 1 + state: present + register: ecs_service_creation_constraints + + - name: Assert ecs service constraint + assert: + that: + - ecs_service_creation_constraints.changed + - "{{ ecs_service_creation_constraints.service.placementConstraints | length }} == 1" + - "{{ ecs_service_creation_constraints.service.placementConstraints[0].type }} == distinctInstance" + + - name: Update ecs service's placement constraints + ecs_service: + name: "{{ ecs_service_name }}-constraint" + cluster: "{{ ecs_cluster_name }}" + load_balancers: + - targetGroupArn: "{{ elb_target_group_instance.target_group_arn }}" + containerName: "{{ ecs_task_name }}" + containerPort: "{{ ecs_task_container_port }}" + task_definition: "{{ ecs_task_name }}:{{ ecs_task_definition.taskdefinition.revision }}" + scheduling_strategy: "REPLICA" + placement_constraints: + - type: memberOf + expression: 'attribute:ecs.instance-type == t3.micro' + desired_count: 1 + state: present + register: ecs_service_update_constraints + + - name: Assert ecs service constraint + assert: + that: + - ecs_service_update_constraints.changed + - "{{ ecs_service_update_constraints.service.placementConstraints | length }} == 1" + - "{{ ecs_service_update_constraints.service.placementConstraints[0].type }} == memberOf" + - "{{ ecs_service_update_constraints.service.placementConstraints[0].expression }} == 'attribute:ecs.instance-type == t3.micro'" + + - name: Create ecs service with placement strategy + ecs_service: + name: "{{ ecs_service_name }}-strategy" + cluster: "{{ ecs_cluster_name }}" + load_balancers: + - targetGroupArn: "{{ elb_target_group_instance.target_group_arn }}" + containerName: "{{ ecs_task_name }}" + containerPort: "{{ ecs_task_container_port }}" + task_definition: "{{ ecs_task_name }}:{{ ecs_task_definition.taskdefinition.revision }}" + scheduling_strategy: "REPLICA" + placement_strategy: + - type: binpack + field: MEMORY + desired_count: 1 + state: present + register: ecs_service_creation_strategy + + - name: Assert ecs service strategy + assert: + that: + - ecs_service_creation_strategy.changed + - "{{ ecs_service_creation_strategy.service.placementplacementStrategy | length }} == 1" + - "{{ ecs_service_creation_strategy.service.placementConstraints[0].type }} == binpack" + - "{{ ecs_service_creation_strategy.service.placementConstraints[0].field }} == MEMORY" + + - name: Update ecs service's placement strategy + ecs_service: + name: "{{ ecs_service_name }}-strategy" + cluster: "{{ ecs_cluster_name }}" + load_balancers: + - targetGroupArn: "{{ elb_target_group_instance.target_group_arn }}" + containerName: "{{ ecs_task_name }}" + containerPort: "{{ ecs_task_container_port }}" + task_definition: "{{ ecs_task_name }}:{{ ecs_task_definition.taskdefinition.revision }}" + scheduling_strategy: "REPLICA" + placement_strategy: + - type: spread + field: instanceId + desired_count: 1 + state: present + register: ecs_service_update_strategy + + - name: Assert ecs service strategy + assert: + that: + - ecs_service_update_strategy.changed + - "{{ ecs_service_update_strategy.service.placementplacementStrategy | length }} == 1" + - "{{ ecs_service_update_strategy.service.placementConstraints[0].type }} == spread" + - "{{ ecs_service_update_strategy.service.placementConstraints[0].field }} == instanceId" + # ============================================================ # Begin tests for Fargate @@ -985,6 +1083,24 @@ wait: yes ignore_errors: yes + - name: remove constraints ecs service + ecs_service: + state: absent + cluster: "{{ ecs_cluster_name }}" + name: "{{ ecs_service_name }}-constraint" + force_deletion: yes + wait: yes + ignore_errors: yes + + - name: remove strategy ecs service + ecs_service: + state: absent + cluster: "{{ ecs_cluster_name }}" + name: "{{ ecs_service_name }}-strategy" + force_deletion: yes + wait: yes + ignore_errors: yes + - name: remove scheduling_strategy ecs service ecs_service: state: absent From a71cf7519bb8e23cd85104199877f4714a00065a Mon Sep 17 00:00:00 2001 From: Feng Zhou Date: Mon, 5 Dec 2022 10:45:58 +0800 Subject: [PATCH 06/10] Update integration tests and changelogs. --- ...upport_constraints_and_strategy_update.yml | 2 +- .../targets/ecs_cluster/tasks/main.yml | 48 +++++++++++-------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/changelogs/fragments/1601-ecs_service-support_constraints_and_strategy_update.yml b/changelogs/fragments/1601-ecs_service-support_constraints_and_strategy_update.yml index e608fc4e8b3..380e9349954 100644 --- a/changelogs/fragments/1601-ecs_service-support_constraints_and_strategy_update.yml +++ b/changelogs/fragments/1601-ecs_service-support_constraints_and_strategy_update.yml @@ -1,2 +1,2 @@ bugfixes: - - ecs_service supports constraints and strategy update (https://github.com/ansible-collections/community.aws/pull/1601). + - ecs_service - respect ``placement_constraints`` for existing ecs services(https://github.com/ansible-collections/community.aws/pull/1601). diff --git a/tests/integration/targets/ecs_cluster/tasks/main.yml b/tests/integration/targets/ecs_cluster/tasks/main.yml index d105d087d08..36b2ee317f3 100644 --- a/tests/integration/targets/ecs_cluster/tasks/main.yml +++ b/tests/integration/targets/ecs_cluster/tasks/main.yml @@ -108,19 +108,21 @@ vpc_id: '{{ setup_vpc.vpc.id }}' rules: # allow all ssh traffic but nothing else - ports: 22 - cidr: 0.0.0.0/0 + cidr_ip: 0.0.0.0/0 register: setup_sg - - name: find a suitable AMI - ec2_ami_info: - owner: amazon - filters: - description: "Amazon Linux AMI* ECS *" - register: ec2_ami_info + - set_fact: + # As a lookup plugin we don't have access to module_defaults + connection_args: + region: "{{ aws_region }}" + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + aws_security_token: "{{ security_token | default(omit) }}" + no_log: True - name: set image id fact set_fact: - ecs_image_id: "{{ (ec2_ami_info.images|last).image_id }}" + ecs_image_id: "{{ lookup('aws_ssm', '/aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id', **connection_args) }}" - name: provision ec2 instance to create an image ec2_instance: @@ -146,6 +148,10 @@ modify_targets: no vpc_id: '{{ setup_vpc.vpc.id }}' target_type: instance + health_check_interval: 5 + health_check_timeout: 2 + healthy_threshold_count: 2 + unhealthy_threshold_count: 2 register: elb_target_group_instance - name: create second target group to use ip target_type @@ -157,6 +163,10 @@ modify_targets: no vpc_id: '{{ setup_vpc.vpc.id }}' target_type: ip + health_check_interval: 5 + health_check_timeout: 2 + healthy_threshold_count: 2 + unhealthy_threshold_count: 2 register: elb_target_group_ip - name: create load balancer @@ -618,8 +628,8 @@ assert: that: - ecs_service_creation_constraints.changed - - "{{ ecs_service_creation_constraints.service.placementConstraints | length }} == 1" - - "{{ ecs_service_creation_constraints.service.placementConstraints[0].type }} == distinctInstance" + - "ecs_service_creation_constraints.service.placementConstraints | length == 1" + - "ecs_service_creation_constraints.service.placementConstraints[0].type == distinctInstance" - name: Update ecs service's placement constraints ecs_service: @@ -642,9 +652,9 @@ assert: that: - ecs_service_update_constraints.changed - - "{{ ecs_service_update_constraints.service.placementConstraints | length }} == 1" - - "{{ ecs_service_update_constraints.service.placementConstraints[0].type }} == memberOf" - - "{{ ecs_service_update_constraints.service.placementConstraints[0].expression }} == 'attribute:ecs.instance-type == t3.micro'" + - "ecs_service_update_constraints.service.placementConstraints | length == 1" + - "ecs_service_update_constraints.service.placementConstraints[0].type == memberOf" + - "ecs_service_update_constraints.service.placementConstraints[0].expression == 'attribute:ecs.instance-type == t3.micro'" - name: Create ecs service with placement strategy ecs_service: @@ -667,9 +677,9 @@ assert: that: - ecs_service_creation_strategy.changed - - "{{ ecs_service_creation_strategy.service.placementplacementStrategy | length }} == 1" - - "{{ ecs_service_creation_strategy.service.placementConstraints[0].type }} == binpack" - - "{{ ecs_service_creation_strategy.service.placementConstraints[0].field }} == MEMORY" + - "ecs_service_creation_strategy.service.placementplacementStrategy | length == 1" + - "ecs_service_creation_strategy.service.placementConstraints[0].type == binpack" + - "ecs_service_creation_strategy.service.placementConstraints[0].field == MEMORY" - name: Update ecs service's placement strategy ecs_service: @@ -692,9 +702,9 @@ assert: that: - ecs_service_update_strategy.changed - - "{{ ecs_service_update_strategy.service.placementplacementStrategy | length }} == 1" - - "{{ ecs_service_update_strategy.service.placementConstraints[0].type }} == spread" - - "{{ ecs_service_update_strategy.service.placementConstraints[0].field }} == instanceId" + - "ecs_service_update_strategy.service.placementplacementStrategy | length == 1" + - "ecs_service_update_strategy.service.placementConstraints[0].type == spread" + - "ecs_service_update_strategy.service.placementConstraints[0].field == instanceId" # ============================================================ # Begin tests for Fargate From 268ca40df7cae0abadad9343d14766e7b5561ec3 Mon Sep 17 00:00:00 2001 From: Feng Zhou Date: Tue, 20 Dec 2022 18:12:34 +0800 Subject: [PATCH 07/10] Fix test cases. --- tests/integration/targets/ecs_cluster/tasks/main.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/integration/targets/ecs_cluster/tasks/main.yml b/tests/integration/targets/ecs_cluster/tasks/main.yml index 36b2ee317f3..9e47153f290 100644 --- a/tests/integration/targets/ecs_cluster/tasks/main.yml +++ b/tests/integration/targets/ecs_cluster/tasks/main.yml @@ -677,9 +677,9 @@ assert: that: - ecs_service_creation_strategy.changed - - "ecs_service_creation_strategy.service.placementplacementStrategy | length == 1" - - "ecs_service_creation_strategy.service.placementConstraints[0].type == binpack" - - "ecs_service_creation_strategy.service.placementConstraints[0].field == MEMORY" + - "ecs_service_creation_strategy.service.placementStrategy | length == 1" + - "ecs_service_creation_strategy.service.placementStrategy[0].type == binpack" + - "ecs_service_creation_strategy.service.placementStrategy[0].field == MEMORY" - name: Update ecs service's placement strategy ecs_service: @@ -702,9 +702,9 @@ assert: that: - ecs_service_update_strategy.changed - - "ecs_service_update_strategy.service.placementplacementStrategy | length == 1" - - "ecs_service_update_strategy.service.placementConstraints[0].type == spread" - - "ecs_service_update_strategy.service.placementConstraints[0].field == instanceId" + - "ecs_service_update_strategy.service.placementStrategy | length == 1" + - "ecs_service_update_strategy.service.placementStrategy[0].type == spread" + - "ecs_service_update_strategy.service.placementStrategy[0].field == instanceId" # ============================================================ # Begin tests for Fargate From 2542122b83238bc5799ac24626800d3d496fe6b0 Mon Sep 17 00:00:00 2001 From: Feng Zhou Date: Tue, 20 Dec 2022 18:20:02 +0800 Subject: [PATCH 08/10] For compatibility, remove ecs servivce's constraints and strategies when not specified. --- plugins/modules/ecs_service.py | 4 ++ .../targets/ecs_cluster/tasks/main.yml | 39 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/plugins/modules/ecs_service.py b/plugins/modules/ecs_service.py index eb19f8e2b36..d23678b447d 100644 --- a/plugins/modules/ecs_service.py +++ b/plugins/modules/ecs_service.py @@ -833,8 +833,12 @@ def update_service(self, service_name, cluster_name, task_definition, desired_co if placement_constraints: params['placementConstraints'] = [{key: value for key, value in constraint.items() if value is not None} for constraint in placement_constraints] + else: + params['placementConstraints'] = [] if placement_strategy: params['placementStrategy'] = placement_strategy + else: + params['placementStrategy'] = [] if network_configuration: params['networkConfiguration'] = network_configuration if force_new_deployment: diff --git a/tests/integration/targets/ecs_cluster/tasks/main.yml b/tests/integration/targets/ecs_cluster/tasks/main.yml index 9e47153f290..edeaf7b452e 100644 --- a/tests/integration/targets/ecs_cluster/tasks/main.yml +++ b/tests/integration/targets/ecs_cluster/tasks/main.yml @@ -656,6 +656,26 @@ - "ecs_service_update_constraints.service.placementConstraints[0].type == memberOf" - "ecs_service_update_constraints.service.placementConstraints[0].expression == 'attribute:ecs.instance-type == t3.micro'" + - name: Remove ecs service's placement constraints + ecs_service: + name: "{{ ecs_service_name }}-constraint" + cluster: "{{ ecs_cluster_name }}" + load_balancers: + - targetGroupArn: "{{ elb_target_group_instance.target_group_arn }}" + containerName: "{{ ecs_task_name }}" + containerPort: "{{ ecs_task_container_port }}" + task_definition: "{{ ecs_task_name }}:{{ ecs_task_definition.taskdefinition.revision }}" + scheduling_strategy: "REPLICA" + desired_count: 1 + state: present + register: ecs_service_remove_constraints + + - name: Assert ecs service constraint + assert: + that: + - ecs_service_remove_constraints.changed + - "ecs_service_remove_constraints.service.placementConstraints | length == 0" + - name: Create ecs service with placement strategy ecs_service: name: "{{ ecs_service_name }}-strategy" @@ -706,6 +726,25 @@ - "ecs_service_update_strategy.service.placementStrategy[0].type == spread" - "ecs_service_update_strategy.service.placementStrategy[0].field == instanceId" + - name: Remove ecs service's placement strategy + ecs_service: + name: "{{ ecs_service_name }}-strategy" + cluster: "{{ ecs_cluster_name }}" + load_balancers: + - targetGroupArn: "{{ elb_target_group_instance.target_group_arn }}" + containerName: "{{ ecs_task_name }}" + containerPort: "{{ ecs_task_container_port }}" + task_definition: "{{ ecs_task_name }}:{{ ecs_task_definition.taskdefinition.revision }}" + scheduling_strategy: "REPLICA" + desired_count: 1 + state: present + register: ecs_service_remove_strategy + + - name: Assert ecs service strategy + assert: + that: + - ecs_service_remove_strategy.changed + - "ecs_service_remove_strategy.service.placementStrategy | length == 0" # ============================================================ # Begin tests for Fargate From 66d31ed1139a1d93576c29570762ec73b1dff536 Mon Sep 17 00:00:00 2001 From: Markus Bergholz Date: Tue, 10 Jan 2023 09:32:15 +0100 Subject: [PATCH 09/10] Update changelogs/fragments/1601-ecs_service-support_constraints_and_strategy_update.yml --- ...1601-ecs_service-support_constraints_and_strategy_update.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/1601-ecs_service-support_constraints_and_strategy_update.yml b/changelogs/fragments/1601-ecs_service-support_constraints_and_strategy_update.yml index 380e9349954..daa58d11ae7 100644 --- a/changelogs/fragments/1601-ecs_service-support_constraints_and_strategy_update.yml +++ b/changelogs/fragments/1601-ecs_service-support_constraints_and_strategy_update.yml @@ -1,2 +1,2 @@ bugfixes: - - ecs_service - respect ``placement_constraints`` for existing ecs services(https://github.com/ansible-collections/community.aws/pull/1601). + - ecs_service - respect ``placement_constraints`` for existing ecs services (https://github.com/ansible-collections/community.aws/pull/1601). From 55e8c58b7bfaa52c77d260022a291d228fb75d1e Mon Sep 17 00:00:00 2001 From: Markus Bergholz Date: Tue, 10 Jan 2023 09:43:10 +0100 Subject: [PATCH 10/10] Update plugins/modules/ecs_service.py --- plugins/modules/ecs_service.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/modules/ecs_service.py b/plugins/modules/ecs_service.py index d23678b447d..e7d9192e3e3 100644 --- a/plugins/modules/ecs_service.py +++ b/plugins/modules/ecs_service.py @@ -833,12 +833,10 @@ def update_service(self, service_name, cluster_name, task_definition, desired_co if placement_constraints: params['placementConstraints'] = [{key: value for key, value in constraint.items() if value is not None} for constraint in placement_constraints] - else: - params['placementConstraints'] = [] + if placement_strategy: params['placementStrategy'] = placement_strategy - else: - params['placementStrategy'] = [] + if network_configuration: params['networkConfiguration'] = network_configuration if force_new_deployment: