Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PR #1601/316f0acb backport][stable-4] ecs_service supports constraints and strategy update #1648

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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