Skip to content

Commit

Permalink
ecs_service supports constraints and strategy update (#1601) (#1648)
Browse files Browse the repository at this point in the history
[PR #1601/316f0acb backport][stable-4] ecs_service supports constraints and strategy update

This is a backport of PR #1601 as merged into main (316f0ac).
SUMMARY


ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME

ecs_service
ADDITIONAL INFORMATION


related issue #1414

Reviewed-by: Markus Bergholz <[email protected]>
  • Loading branch information
patchback[bot] authored Jan 12, 2023
1 parent 3fa1115 commit 9643eb3
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bugfixes:
- ecs_service - respect ``placement_constraints`` for existing ecs services (https://github.com/ansible-collections/community.aws/pull/1601).
18 changes: 15 additions & 3 deletions plugins/modules/ecs_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -807,14 +807,24 @@ 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:
Expand Down Expand Up @@ -1026,6 +1036,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'],
Expand Down
181 changes: 173 additions & 8 deletions tests/integration/targets/ecs_cluster/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -598,6 +608,143 @@
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: 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"
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.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:
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.placementStrategy | length == 1"
- "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

Expand Down Expand Up @@ -985,6 +1132,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
Expand Down

0 comments on commit 9643eb3

Please sign in to comment.