From 6ab71a4b2e4617aef34e3d29231fe78a67ebba92 Mon Sep 17 00:00:00 2001 From: "asaf.levy" Date: Tue, 15 Sep 2020 19:31:51 +0300 Subject: [PATCH 1/2] Allow ECS.Client.delete_service to force delete a service --- plugins/modules/ecs_service.py | 13 +- .../tasks/force_service_deletion.yml | 766 ++++++++++++++++++ .../targets/ecs_cluster/tasks/main.yml | 1 + 3 files changed, 777 insertions(+), 3 deletions(-) create mode 100644 tests/integration/targets/ecs_cluster/tasks/force_service_deletion.yml diff --git a/plugins/modules/ecs_service.py b/plugins/modules/ecs_service.py index 590276e0ab1..efc2877e99b 100644 --- a/plugins/modules/ecs_service.py +++ b/plugins/modules/ecs_service.py @@ -127,6 +127,11 @@ field: description: The field to apply the placement strategy against. type: str + force_deletion: + description: + - Forcabily delete the service. Required when deleting a service with >0 scale, or no target group. + default: False + type: bool network_configuration: description: - Network configuration of the service. Only applicable for task definitions created with I(network_mode=awsvpc). @@ -631,8 +636,8 @@ def jsonize(self, service): e['createdAt'] = str(e['createdAt']) return service - def delete_service(self, service, cluster=None): - return self.ecs.delete_service(cluster=cluster, service=service) + def delete_service(self, service, cluster=None, force=False): + return self.ecs.delete_service(cluster=cluster, service=service, force=force) def health_check_setable(self, params): load_balancers = params.get('loadBalancers', []) @@ -652,6 +657,7 @@ def main(): delay=dict(required=False, type='int', default=10), repeat=dict(required=False, type='int', default=10), force_new_deployment=dict(required=False, default=False, type='bool'), + force_deletion=dict(required=False, default=False, type='bool'), deployment_configuration=dict(required=False, default={}, type='dict'), placement_constraints=dict( required=False, @@ -810,7 +816,8 @@ def main(): try: service_mgr.delete_service( module.params['name'], - module.params['cluster'] + module.params['cluster'], + module.params['force_deletion'], ) except botocore.exceptions.ClientError as e: module.fail_json_aws(e, msg="Couldn't delete service") diff --git a/tests/integration/targets/ecs_cluster/tasks/force_service_deletion.yml b/tests/integration/targets/ecs_cluster/tasks/force_service_deletion.yml new file mode 100644 index 00000000000..058dc3173f0 --- /dev/null +++ b/tests/integration/targets/ecs_cluster/tasks/force_service_deletion.yml @@ -0,0 +1,766 @@ +--- +# tasks file for ecs_cluster +- name: ecs_cluster tests + collections: + - amazon.aws + + block: + - name: ensure IAM instance role exists + iam_role: + name: ecsInstanceRole + assume_role_policy_document: "{{ lookup('file','ec2-trust-policy.json') }}" + state: present + create_instance_profile: yes + managed_policy: + - AmazonEC2ContainerServiceforEC2Role + + - name: ensure IAM service role exists + iam_role: + name: ecsServiceRole + assume_role_policy_document: "{{ lookup('file','ecs-trust-policy.json') }}" + state: present + create_instance_profile: no + managed_policy: + - AmazonEC2ContainerServiceRole + + - name: ensure AWSServiceRoleForECS role exists + iam_role_info: + name: AWSServiceRoleForECS + register: iam_role_result + + # FIXME: come up with a way to automate this + - name: fail if AWSServiceRoleForECS role does not exist + fail: + msg: > + Run `aws iam create-service-linked-role --aws-service-name=ecs.amazonaws.com ` to create + a linked role for AWS VPC load balancer management + when: not iam_role_result.iam_roles + + - name: create an ECS cluster + ecs_cluster: + name: "{{ ecs_cluster_name }}" + state: present + register: ecs_cluster + + - name: check that ecs_cluster changed + assert: + that: + - ecs_cluster.changed + + - name: create same ECS cluster (should do nothing) + ecs_cluster: + name: "{{ ecs_cluster_name }}" + state: present + register: ecs_cluster_again + + - name: check that ecs_cluster did not change + assert: + that: + - not ecs_cluster_again.changed + + - name: create a VPC to work in + ec2_vpc_net: + cidr_block: 10.0.0.0/16 + state: present + name: '{{ resource_prefix }}_ecs_cluster' + resource_tags: + Name: '{{ resource_prefix }}_ecs_cluster' + register: setup_vpc + + - name: create a key pair to use for creating an ec2 instance + ec2_key: + name: '{{ resource_prefix }}_ecs_cluster' + state: present + when: ec2_keypair is not defined # allow override in cloud-config-aws.ini + register: setup_key + + - name: create subnets + ec2_vpc_subnet: + az: '{{ ec2_region }}{{ item.zone }}' + tags: + Name: '{{ resource_prefix }}_ecs_cluster-subnet-{{ item.zone }}' + vpc_id: '{{ setup_vpc.vpc.id }}' + cidr: "{{ item.cidr }}" + state: present + register: setup_subnet + with_items: + - zone: a + cidr: 10.0.1.0/24 + - zone: b + cidr: 10.0.2.0/24 + + - name: create an internet gateway so that ECS agents can talk to ECS + ec2_vpc_igw: + vpc_id: '{{ setup_vpc.vpc.id }}' + state: present + register: igw + + - name: create a security group to use for creating an ec2 instance + ec2_group: + name: '{{ resource_prefix }}_ecs_cluster-sg' + description: 'created by Ansible integration tests' + state: present + vpc_id: '{{ setup_vpc.vpc.id }}' + rules: # allow all ssh traffic but nothing else + - ports: 22 + cidr: 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 + + - name: set image id fact + set_fact: + ecs_image_id: "{{ (ec2_ami_info.images|first).image_id }}" + + - name: provision ec2 instance to create an image + ec2_instance: + key_name: '{{ ec2_keypair|default(setup_key.key.name) }}' + instance_type: t2.micro + state: present + image_id: '{{ ecs_image_id }}' + wait: yes + user_data: "{{ user_data }}" + instance_role: ecsInstanceRole + tags: + Name: '{{ resource_prefix }}_ecs_agent' + security_group: '{{ setup_sg.group_id }}' + vpc_subnet_id: '{{ setup_subnet.results[0].subnet.id }}' + register: setup_instance + + - name: create target group + elb_target_group: + name: "{{ ecs_target_group_name }}1" + state: present + protocol: HTTP + port: 8080 + modify_targets: no + vpc_id: '{{ setup_vpc.vpc.id }}' + target_type: instance + register: elb_target_group_instance + + - name: create second target group to use ip target_type + elb_target_group: + name: "{{ ecs_target_group_name }}2" + state: present + protocol: HTTP + port: 8080 + modify_targets: no + vpc_id: '{{ setup_vpc.vpc.id }}' + target_type: ip + register: elb_target_group_ip + + - name: create load balancer + elb_application_lb: + name: "{{ ecs_load_balancer_name }}" + state: present + scheme: internal + security_groups: '{{ setup_sg.group_id }}' + subnets: "{{ setup_subnet.results | community.general.json_query('[].subnet.id') }}" + listeners: + - Protocol: HTTP + Port: 80 + DefaultActions: + - Type: forward + TargetGroupName: "{{ ecs_target_group_name }}1" + - Protocol: HTTP + Port: 81 + DefaultActions: + - Type: forward + TargetGroupName: "{{ ecs_target_group_name }}2" + + - name: create task definition + ecs_taskdefinition: + containers: "{{ ecs_task_containers }}" + family: "{{ ecs_task_name }}" + state: present + register: ecs_task_definition + + - name: obtain ECS task definition facts + ecs_taskdefinition_info: + task_definition: "{{ ecs_task_name }}:{{ ecs_task_definition.taskdefinition.revision }}" + + - name: create ECS service definition + ecs_service: + state: present + name: "{{ ecs_service_name }}" + cluster: "{{ ecs_cluster_name }}" + task_definition: "{{ ecs_task_name }}:{{ ecs_task_definition.taskdefinition.revision }}" + desired_count: 1 + deployment_configuration: "{{ ecs_service_deployment_configuration }}" + placement_strategy: "{{ ecs_service_placement_strategy }}" + health_check_grace_period_seconds: "{{ ecs_service_health_check_grace_period }}" + load_balancers: + - targetGroupArn: "{{ elb_target_group_instance.target_group_arn }}" + containerName: "{{ ecs_task_name }}" + containerPort: "{{ ecs_task_container_port }}" + role: "ecsServiceRole" + register: ecs_service + + - name: check that ECS service creation changed + assert: + that: + - ecs_service.changed + +# TODO + +# - name: scale down ECS service +# ecs_service: +# state: present +# name: "{{ ecs_service_name }}" +# cluster: "{{ ecs_cluster_name }}" +# task_definition: "{{ ecs_task_name }}:{{ ecs_task_definition.taskdefinition.revision }}" +# desired_count: 0 +# deployment_configuration: "{{ ecs_service_deployment_configuration }}" +# placement_strategy: "{{ ecs_service_placement_strategy }}" +# load_balancers: +# - targetGroupArn: "{{ elb_target_group_instance.target_group_arn }}" +# containerName: "{{ ecs_task_name }}" +# containerPort: "{{ ecs_task_container_port }}" +# role: "ecsServiceRole" +# register: ecs_service_scale_down +# +# - name: pause to allow service to scale down +# pause: +# seconds: 60 + + - name: delete ECS service definition even while service is scaled - Should fail + ecs_service: + state: absent + name: "{{ ecs_service_name }}" + cluster: "{{ ecs_cluster_name }}" + ignore_errors: yes + register: delete_ecs_service_fail + + - name: assert that updating ECS load balancer failed with helpful message + assert: + that: + - delete_ecs_service_fail is failed + + - name: delete ECS service definition even while service is scaled + ecs_service: + state: absent + name: "{{ ecs_service_name }}" + cluster: "{{ ecs_cluster_name }}" + force_deletion: yes + register: delete_ecs_service + + - name: assert that deleting ECS service worked + assert: + that: + - delete_ecs_service.changed + + - name: create ECS service definition + ecs_service: + state: present + name: "{{ ecs_service_name }}" + cluster: "{{ ecs_cluster_name }}" + task_definition: "{{ ecs_task_name }}:{{ ecs_task_definition.taskdefinition.revision }}" + desired_count: 1 + deployment_configuration: "{{ ecs_service_deployment_configuration }}" + placement_strategy: "{{ ecs_service_placement_strategy }}" + health_check_grace_period_seconds: "{{ ecs_service_health_check_grace_period }}" + load_balancers: + - targetGroupArn: "{{ elb_target_group_instance.target_group_arn }}" + containerName: "{{ ecs_task_name }}" + containerPort: "{{ ecs_task_container_port }}" + role: "ecsServiceRole" + register: ecs_service + + - name: remove target groups from load balancer + elb_application_lb: + name: "{{ ecs_load_balancer_name }}" + state: present + scheme: internal + security_groups: '{{ setup_sg.group_id }}' + subnets: "{{ setup_subnet.results | community.general.json_query('[].subnet.id') }}" + listeners: + - Protocol: HTTP + Port: 80 + DefaultActions: + - Type: fixed-response + FixedResponseConfig: + ContentType: "text/plain" + MessageBody: "This is the page you're looking for" + StatusCode: "200" + - Protocol: HTTP + Port: 81 + DefaultActions: + - Type: fixed-response + FixedResponseConfig: + ContentType: "text/plain" + MessageBody: "This is the page you're looking for" + StatusCode: "200" + + - name: pause to allow target groups to refresh into no-lb state + pause: + seconds: 10 + + - name: delete in-use targetGroup + elb_target_group: + state: absent + name: "{{ ecs_target_group_name }}1" + + - name: delete in-use targetGroup + elb_target_group: + state: absent + name: "{{ ecs_target_group_name }}2" + + - name: delete ECS service definition even while service is scaled - Should fail + ecs_service: + state: absent + name: "{{ ecs_service_name }}" + cluster: "{{ ecs_cluster_name }}" + force_deletion: yes + register: delete_ecs_service_fail + + - name: assert that updating ECS load balancer failed with helpful message + assert: + that: + - delete_ecs_service_fail is failed + + - name: delete ECS service definition even while service is scaled + ecs_service: + state: absent + name: "{{ ecs_service_name }}" + cluster: "{{ ecs_cluster_name }}" + force_deletion: yes + register: delete_ecs_service + + - name: obtain facts for all ECS services in the cluster + ecs_service_info: + cluster: "{{ ecs_cluster_name }}" + details: yes + events: no + register: ecs_service_info + + - name: assert that facts are useful + assert: + that: + - "'services' in ecs_service_info" + - ecs_service_info.services | length > 0 + - "'events' not in ecs_service_info.services[0]" + + - name: obtain facts for existing service in the cluster + ecs_service_info: + cluster: "{{ ecs_cluster_name }}" + service: "{{ ecs_service_name }}" + details: yes + events: no + register: ecs_service_info + + - name: assert that existing service is available and running + assert: + that: + - "ecs_service_info.services|length == 1" + - "ecs_service_info.services_not_running|length == 0" + + - name: obtain facts for non-existent service in the cluster + ecs_service_info: + cluster: "{{ ecs_cluster_name }}" + service: madeup + details: yes + events: no + register: ecs_service_info + + - name: assert that non-existent service is missing + assert: + that: + - "ecs_service_info.services_not_running[0].reason == 'MISSING'" + + - name: obtain specific ECS service facts + ecs_service_info: + service: "{{ ecs_service_name }}2" + cluster: "{{ ecs_cluster_name }}" + details: yes + register: ecs_service_info + +# +# # ============================================================ +# # Begin tests for Fargate +# +# - name: ensure AmazonECSTaskExecutionRolePolicy exists +# iam_role: +# name: ecsTaskExecutionRole +# assume_role_policy_document: "{{ lookup('file','ecs-trust-policy.json') }}" +# description: "Allows ECS containers to make calls to ECR" +# state: present +# create_instance_profile: no +# managed_policy: +# - AmazonEC2ContainerServiceRole +# register: iam_execution_role +# +# - name: create Fargate VPC-networked task definition with host port set to 8080 and unsupported network mode (expected to fail) +# ecs_taskdefinition: +# containers: "{{ ecs_fargate_task_containers }}" +# family: "{{ ecs_task_name }}-vpc" +# network_mode: bridge +# launch_type: FARGATE +# cpu: 512 +# memory: 1024 +# state: present +# vars: +# ecs_task_host_port: 8080 +# ignore_errors: yes +# register: ecs_fargate_task_definition_bridged_with_host_port +# +# - name: check that fargate task definition with bridged networking fails gracefully +# assert: +# that: +# - ecs_fargate_task_definition_bridged_with_host_port is failed +# - 'ecs_fargate_task_definition_bridged_with_host_port.msg == "To use FARGATE launch type, network_mode must be awsvpc"' +# +# - name: create Fargate VPC-networked task definition without CPU or Memory (expected to Fail) +# ecs_taskdefinition: +# containers: "{{ ecs_fargate_task_containers }}" +# family: "{{ ecs_task_name }}-vpc" +# network_mode: awsvpc +# launch_type: FARGATE +# state: present +# ignore_errors: yes +# register: ecs_fargate_task_definition_vpc_no_mem +# +# - name: check that fargate task definition without memory or cpu fails gracefully +# assert: +# that: +# - ecs_fargate_task_definition_vpc_no_mem is failed +# - 'ecs_fargate_task_definition_vpc_no_mem.msg == "launch_type is FARGATE but all of the following are missing: cpu, memory"' +# +# - name: create Fargate VPC-networked task definition with CPU or Memory and execution role +# ecs_taskdefinition: +# containers: "{{ ecs_fargate_task_containers }}" +# family: "{{ ecs_task_name }}-vpc" +# network_mode: awsvpc +# launch_type: FARGATE +# cpu: 512 +# memory: 1024 +# execution_role_arn: "{{ iam_execution_role.arn }}" +# state: present +# vars: +# ecs_task_host_port: 8080 +# register: ecs_fargate_task_definition +# +# - name: obtain ECS task definition facts +# ecs_taskdefinition_info: +# task_definition: "{{ ecs_task_name }}-vpc:{{ ecs_fargate_task_definition.taskdefinition.revision }}" +# +# - name: create fargate ECS service without network config (expected to fail) +# ecs_service: +# state: present +# name: "{{ ecs_service_name }}4" +# cluster: "{{ ecs_cluster_name }}" +# task_definition: "{{ ecs_task_name }}-vpc:{{ ecs_fargate_task_definition.taskdefinition.revision }}" +# desired_count: 1 +# deployment_configuration: "{{ ecs_service_deployment_configuration }}" +# launch_type: FARGATE +# register: ecs_fargate_service_network_without_awsvpc +# ignore_errors: yes +# +# - name: assert that using Fargate ECS service fails +# assert: +# that: +# - ecs_fargate_service_network_without_awsvpc is failed +# +# - name: create fargate ECS service with network config +# ecs_service: +# state: present +# name: "{{ ecs_service_name }}4" +# cluster: "{{ ecs_cluster_name }}" +# task_definition: "{{ ecs_task_name }}-vpc:{{ ecs_fargate_task_definition.taskdefinition.revision }}" +# desired_count: 1 +# deployment_configuration: "{{ ecs_service_deployment_configuration }}" +# launch_type: FARGATE +# network_configuration: +# subnets: "{{ setup_subnet.results | community.general.json_query('[].subnet.id') }}" +# security_groups: +# - '{{ setup_sg.group_id }}' +# assign_public_ip: true +# register: ecs_fargate_service_network_with_awsvpc +# +# - name: assert that public IP assignment is enabled +# assert: +# that: +# - 'ecs_fargate_service_network_with_awsvpc.service.networkConfiguration.awsvpcConfiguration.assignPublicIp == "ENABLED"' +# +# - name: create fargate ECS task with run task +# ecs_task: +# operation: run +# cluster: "{{ ecs_cluster_name }}" +# task_definition: "{{ ecs_task_name }}-vpc" +# launch_type: FARGATE +# count: 1 +# network_configuration: +# subnets: "{{ setup_subnet.results | community.general.json_query('[].subnet.id') }}" +# security_groups: +# - '{{ setup_sg.group_id }}' +# assign_public_ip: true +# started_by: ansible_user +# register: fargate_run_task_output +# +# # aws cli not installed in docker container; make sure it's installed. +# - name: install awscli +# pip: +# state: present +# name: awscli +# +# - name: disable taskLongArnFormat +# command: aws ecs put-account-setting --name taskLongArnFormat --value disabled +# environment: +# AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" +# AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" +# AWS_SESSION_TOKEN: "{{ security_token | default('') }}" +# AWS_DEFAULT_REGION: "{{ aws_region }}" +# +# - name: create fargate ECS task with run task and tags (LF disabled) (should fail) +# ecs_task: +# operation: run +# cluster: "{{ ecs_cluster_name }}" +# task_definition: "{{ ecs_task_name }}-vpc" +# launch_type: FARGATE +# count: 1 +# tags: +# tag_key: tag_value +# tag_key2: tag_value2 +# network_configuration: +# subnets: "{{ setup_subnet.results | community.general.json_query('[].subnet.id') }}" +# security_groups: +# - '{{ setup_sg.group_id }}' +# assign_public_ip: true +# started_by: ansible_user +# register: fargate_run_task_output_with_tags_fail +# ignore_errors: yes +# +# - name: enable taskLongArnFormat +# command: aws ecs put-account-setting --name taskLongArnFormat --value enabled +# environment: +# AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" +# AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" +# AWS_SESSION_TOKEN: "{{ security_token | default('') }}" +# AWS_DEFAULT_REGION: "{{ aws_region }}" +# +# - name: create fargate ECS task with run task and tags +# ecs_task: +# operation: run +# cluster: "{{ ecs_cluster_name }}" +# task_definition: "{{ ecs_task_name }}-vpc" +# launch_type: FARGATE +# count: 1 +# tags: +# tag_key: tag_value +# tag_key2: tag_value2 +# network_configuration: +# subnets: "{{ setup_subnet.results | community.general.json_query('[].subnet.id') }}" +# security_groups: +# - '{{ setup_sg.group_id }}' +# assign_public_ip: true +# started_by: ansible_user +# register: fargate_run_task_output_with_tags + + + # ============================================================ + # End tests for Fargate +# +# +# - name: scale down Fargate ECS service +# ecs_service: +# state: present +# name: "{{ ecs_service_name }}4" +# cluster: "{{ ecs_cluster_name }}" +# task_definition: "{{ ecs_task_name }}-vpc:{{ ecs_fargate_task_definition.taskdefinition.revision }}" +# desired_count: 0 +# deployment_configuration: "{{ ecs_service_deployment_configuration }}" +# ignore_errors: yes +# register: ecs_service_scale_down +# +# - name: stop Fargate ECS task +# ecs_task: +# task: "{{ fargate_run_task_output.task[0].taskArn }}" +# task_definition: "{{ ecs_task_name }}-vpc" +# operation: stop +# cluster: "{{ ecs_cluster_name }}" +# ignore_errors: yes +# +# - name: stop Fargate ECS task +# ecs_task: +# task: "{{ fargate_run_task_output_with_tags.task[0].taskArn }}" +# task_definition: "{{ ecs_task_name }}-vpc" +# operation: stop +# cluster: "{{ ecs_cluster_name }}" +# ignore_errors: yes +# - name: pause to allow services to scale down +# pause: +# seconds: 60 +# when: ecs_service_scale_down is not failed + + - name: remove ecs service + ecs_service: + state: absent + cluster: "{{ ecs_cluster_name }}" + name: "{{ ecs_service_name }}" + ignore_errors: yes + + - name: remove second ecs service + ecs_service: + state: absent + cluster: "{{ ecs_cluster_name }}" + name: "{{ ecs_service_name }}2" + ignore_errors: yes + + - name: remove mft ecs service + ecs_service: + state: absent + cluster: "{{ ecs_cluster_name }}" + name: "{{ ecs_service_name }}-mft" + ignore_errors: yes + + - name: remove scheduling_strategy ecs service + ecs_service: + state: absent + cluster: "{{ ecs_cluster_name }}" + name: "{{ ecs_service_name }}-replica" + ignore_errors: yes + +# until ansible supports service registries, the test for it can't run and this +# removal is not needed +# - name: remove service_registries ecs service +# ecs_service: +# state: absent +# cluster: "{{ ecs_cluster_name }}" +# name: "{{ ecs_service_name }}-service-registries" +# ignore_errors: yes + + - name: remove fargate ECS service + ecs_service: + state: absent + name: "{{ ecs_service_name }}4" + cluster: "{{ ecs_cluster_name }}" + ignore_errors: yes + register: ecs_fargate_service_network_with_awsvpc + + - name: remove ecs task definition + ecs_taskdefinition: + containers: "{{ ecs_task_containers }}" + family: "{{ ecs_task_name }}" + revision: "{{ ecs_task_definition.taskdefinition.revision }}" + state: absent + vars: + ecs_task_host_port: 8080 + ignore_errors: yes + + - name: remove ecs task definition again + ecs_taskdefinition: + containers: "{{ ecs_task_containers }}" + family: "{{ ecs_task_name }}" + revision: "{{ ecs_task_definition_again.taskdefinition.revision }}" + state: absent + vars: + ecs_task_host_port: 8080 + ignore_errors: yes + + - name: remove second ecs task definition + ecs_taskdefinition: + containers: "{{ ecs_task_containers }}" + family: "{{ ecs_task_name }}-vpc" + revision: "{{ ecs_task_definition_vpc_with_host_port.taskdefinition.revision }}" + state: absent + vars: + ecs_task_host_port: 8080 + ignore_errors: yes + + - name: remove fargate ecs task definition + ecs_taskdefinition: + containers: "{{ ecs_fargate_task_containers }}" + family: "{{ ecs_task_name }}-vpc" + revision: "{{ ecs_fargate_task_definition.taskdefinition.revision }}" + state: absent + ignore_errors: yes + + - name: remove ecs task definition for absent with arn + ecs_taskdefinition: + containers: "{{ ecs_task_containers }}" + family: "{{ ecs_task_name }}-absent" + revision: "{{ ecs_task_definition_absent_with_arn.taskdefinition.revision }}" + state: absent + ignore_errors: yes + + - name: remove load balancer + elb_application_lb: + name: "{{ ecs_load_balancer_name }}" + state: absent + wait: yes + ignore_errors: yes + register: elb_application_lb_remove + + - name: pause to allow target group to be disassociated + pause: + seconds: 30 + when: not elb_application_lb_remove is failed + + - name: remove target groups + elb_target_group: + name: "{{ item }}" + state: absent + with_items: + - "{{ ecs_target_group_name }}1" + - "{{ ecs_target_group_name }}2" + ignore_errors: yes + + - name: remove setup ec2 instance + ec2_instance: + instance_ids: '{{ setup_instance.instance_ids }}' + state: absent + wait: yes + ignore_errors: yes + + - name: remove setup keypair + ec2_key: + name: '{{ resource_prefix }}_ecs_cluster' + state: absent + ignore_errors: yes + + - name: remove security groups + ec2_group: + name: '{{ item }}' + description: 'created by Ansible integration tests' + state: absent + vpc_id: '{{ setup_vpc.vpc.id }}' + with_items: + - "{{ resource_prefix }}-ecs-vpc-test-sg" + - '{{ resource_prefix }}_ecs_cluster-sg' + ignore_errors: yes + + - name: remove IGW + ec2_vpc_igw: + state: absent + vpc_id: '{{ setup_vpc.vpc.id }}' + ignore_errors: yes + + - name: remove setup subnet + ec2_vpc_subnet: + az: '{{ aws_region }}{{ item.zone }}' + vpc_id: '{{ setup_vpc.vpc.id }}' + cidr: "{{ item.cidr}}" + state: absent + with_items: + - zone: a + cidr: 10.0.1.0/24 + - zone: b + cidr: 10.0.2.0/24 + ignore_errors: yes + + - name: remove setup VPC + ec2_vpc_net: + cidr_block: 10.0.0.0/16 + state: absent + name: '{{ resource_prefix }}_ecs_cluster' + ignore_errors: yes + + - name: remove ECS cluster + ecs_cluster: + name: "{{ ecs_cluster_name }}" + state: absent + ignore_errors: yes diff --git a/tests/integration/targets/ecs_cluster/tasks/main.yml b/tests/integration/targets/ecs_cluster/tasks/main.yml index fdcdd16a669..31c0bd3857e 100644 --- a/tests/integration/targets/ecs_cluster/tasks/main.yml +++ b/tests/integration/targets/ecs_cluster/tasks/main.yml @@ -11,4 +11,5 @@ block: - include_tasks: network_force_new_deployment.yml + - include_tasks: force_service_deletion.yml - include_tasks: full_test.yml From bcd4dc423193dfa38346aabda93cf23183162e2c Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Fri, 22 Oct 2021 18:55:42 +0200 Subject: [PATCH 2/2] Add missing changelog / version_added --- changelogs/fragments/228-ecs_service-force_delete.yml | 2 ++ plugins/modules/ecs_service.py | 1 + 2 files changed, 3 insertions(+) create mode 100644 changelogs/fragments/228-ecs_service-force_delete.yml diff --git a/changelogs/fragments/228-ecs_service-force_delete.yml b/changelogs/fragments/228-ecs_service-force_delete.yml new file mode 100644 index 00000000000..c0c4f68b021 --- /dev/null +++ b/changelogs/fragments/228-ecs_service-force_delete.yml @@ -0,0 +1,2 @@ +minor_changes: +- ecs_service - added support for forcing deletion of a service (https://github.com/ansible-collections/community.aws/pull/228). diff --git a/plugins/modules/ecs_service.py b/plugins/modules/ecs_service.py index efc2877e99b..d43253af386 100644 --- a/plugins/modules/ecs_service.py +++ b/plugins/modules/ecs_service.py @@ -132,6 +132,7 @@ - Forcabily delete the service. Required when deleting a service with >0 scale, or no target group. default: False type: bool + version_added: 2.1.0 network_configuration: description: - Network configuration of the service. Only applicable for task definitions created with I(network_mode=awsvpc).