Repository: ansible-collections/community.aws

Issue:
ec2_asg not updating target group
##### SUMMARY
Previously reported at https://github.com/ansible/ansible/issues/65008.  But in the repo migrations it looks like it got closed without ever getting fixed.

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
ec2_asg

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes -->
```
ansible 2.10.6
  config file = None
  configured module search path = ['/home/msven/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/msven/python3/venv/lib/python3.6/site-packages/ansible
  executable location = /home/msven/python3/venv/bin/ansible
  python version = 3.6.9 (default, Jan 26 2021, 15:33:00) [GCC 8.4.0]
```

##### CONFIGURATION
<!--- Paste verbatim output from "ansible-config dump --only-changed" between quotes -->
```
COLLECTIONS_PATHS(env: ANSIBLE_COLLECTIONS_PATH) = ['/home/msven/git/ansible_collections', '/home/msven']
```

##### OS / ENVIRONMENT
<!--- Provide all relevant information below, e.g. target OS versions, network device firmware, etc. -->


##### STEPS TO REPRODUCE
<!--- Describe exactly how to reproduce the problem, using a minimal test-case -->

1. Create new ec2 auto scaling group
2. Create new target group or attach existing target group via target_group_arns property under ec2_asg module.
3. Now create new target group and update target_group_arns with new arn.

<!--- Paste example playbooks or commands between quotes below -->


<!--- HINT: You can paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- Describe what you expected to happen when running the steps above -->

* New target group should get attached to asg and old should be removed.

##### ACTUAL RESULTS
<!--- Describe what actually happened. If possible run with extra verbosity (-vvvv) -->
* Target group doesn't get updated with new arn.
<!--- Paste verbatim command output between quotes -->




Discussion:
Files identified in the description:
* [`plugins/modules/ec2_asg.py`](https://github.com/['ansible-collections/amazon.aws', 'ansible-collections/community.aws', 'ansible-collections/community.vmware']/blob/main/plugins/modules/ec2_asg.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @garethr @jillr @s-hertel @tremble @wimnat
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
I have a fix for this and will submit a PR to fix soon.

Resolving patch:
diff --git a/plugins/modules/ec2_asg.py b/plugins/modules/ec2_asg.py
--- a/plugins/modules/ec2_asg.py
+++ b/plugins/modules/ec2_asg.py
@@ -1260,25 +1260,22 @@ def create_autoscaling_group(connection):
             # Get differences
             wanted_tgs = set(target_group_arns)
             has_tgs = set(as_group['TargetGroupARNs'])
-            # check if all requested are already existing
-            if has_tgs.issuperset(wanted_tgs):
-                # if wanted contains less than existing, then we need to delete some
-                tgs_to_detach = has_tgs.difference(wanted_tgs)
-                if tgs_to_detach:
-                    changed = True
-                    try:
-                        detach_lb_target_groups(connection, group_name, list(tgs_to_detach))
-                    except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
-                        module.fail_json_aws(e, msg="Failed to detach load balancer target groups {0}".format(tgs_to_detach))
-            if wanted_tgs.issuperset(has_tgs):
-                # if has contains less than wanted, then we need to add some
-                tgs_to_attach = wanted_tgs.difference(has_tgs)
-                if tgs_to_attach:
-                    changed = True
-                    try:
-                        attach_lb_target_groups(connection, group_name, list(tgs_to_attach))
-                    except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
-                        module.fail_json(msg="Failed to attach load balancer target groups {0}".format(tgs_to_attach))
+
+            tgs_to_detach = has_tgs.difference(wanted_tgs)
+            if tgs_to_detach:
+                changed = True
+                try:
+                    detach_lb_target_groups(connection, group_name, list(tgs_to_detach))
+                except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
+                    module.fail_json_aws(e, msg="Failed to detach load balancer target groups {0}".format(tgs_to_detach))
+
+            tgs_to_attach = wanted_tgs.difference(has_tgs)
+            if tgs_to_attach:
+                changed = True
+                try:
+                    attach_lb_target_groups(connection, group_name, list(tgs_to_attach))
+                except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
+                    module.fail_json(msg="Failed to attach load balancer target groups {0}".format(tgs_to_attach))
 
         # check for attributes that aren't required for updating an existing ASG
         # check if min_size/max_size/desired capacity have been specified and if not use ASG values


Test patch:
diff --git a/tests/integration/targets/ec2_asg/tasks/main.yml b/tests/integration/targets/ec2_asg/tasks/main.yml
--- a/tests/integration/targets/ec2_asg/tasks/main.yml
+++ b/tests/integration/targets/ec2_asg/tasks/main.yml
@@ -695,6 +695,134 @@
           - "output.mixed_instances_policy_full['instances_distribution']['on_demand_percentage_above_base_capacity'] == 0"
           - "output.mixed_instances_policy_full['instances_distribution']['spot_allocation_strategy'] == 'capacity-optimized'"
 
+    # ============================================================
+
+    # Target group names have max length of 32 characters
+    - set_fact:
+        tg1_name: "{{ (resource_prefix + '-tg1' ) | regex_search('(.{1,32})$') }}"
+        tg2_name: "{{ (resource_prefix + '-tg2' ) | regex_search('(.{1,32})$') }}"
+
+    - name: create target group 1
+      elb_target_group:
+        name: "{{ tg1_name }}"
+        protocol: tcp
+        port: 80
+        health_check_protocol: tcp
+        health_check_port: 80
+        healthy_threshold_count: 2
+        unhealthy_threshold_count: 2
+        vpc_id: "{{ testing_vpc.vpc.id }}"
+        state: present
+      register: out_tg1
+
+    - name: create target group 2
+      elb_target_group:
+        name: "{{ tg2_name }}"
+        protocol: tcp
+        port: 80
+        health_check_protocol: tcp
+        health_check_port: 80
+        healthy_threshold_count: 2
+        unhealthy_threshold_count: 2
+        vpc_id: "{{ testing_vpc.vpc.id }}"
+        state: present
+      register: out_tg2
+
+    - name: update autoscaling group with tg1
+      ec2_asg:
+        name: "{{ resource_prefix }}-asg"
+        launch_template: 
+          launch_template_name: "{{ resource_prefix }}-lt"
+        target_group_arns:
+          - "{{ out_tg1.target_group_arn }}"
+        desired_capacity: 1
+        min_size: 1
+        max_size: 1
+        state: present
+        wait_for_instances: yes
+      register: output
+
+    - assert:
+        that:
+          - output.target_group_arns[0] == out_tg1.target_group_arn
+
+    - name: update autoscaling group add tg2
+      ec2_asg:
+        name: "{{ resource_prefix }}-asg"
+        launch_template: 
+          launch_template_name: "{{ resource_prefix }}-lt"
+        target_group_arns:
+          - "{{ out_tg1.target_group_arn }}"
+          - "{{ out_tg2.target_group_arn }}"
+        desired_capacity: 1
+        min_size: 1
+        max_size: 1
+        state: present
+        wait_for_instances: yes
+      register: output
+
+    - assert:
+        that:
+          - "output.target_group_arns | length == 2"
+
+    - name: update autoscaling group remove tg1
+      ec2_asg:
+        name: "{{ resource_prefix }}-asg"
+        launch_template: 
+          launch_template_name: "{{ resource_prefix }}-lt"
+        target_group_arns:
+          - "{{ out_tg2.target_group_arn }}"
+        desired_capacity: 1
+        min_size: 1
+        max_size: 1
+        state: present
+        wait_for_instances: yes
+      register: output
+
+    - assert:
+        that:
+          - "output.target_group_arns | length == 1"
+          - "output.target_group_arns[0] == out_tg2.target_group_arn"
+
+    - name: update autoscaling group remove tg2 and add tg1
+      ec2_asg:
+        name: "{{ resource_prefix }}-asg"
+        launch_template: 
+          launch_template_name: "{{ resource_prefix }}-lt"
+        target_group_arns:
+          - "{{ out_tg1.target_group_arn }}"
+        desired_capacity: 1
+        min_size: 1
+        max_size: 1
+        state: present
+        wait_for_instances: yes
+      register: output
+
+    - assert:
+        that:
+          - "output.target_group_arns | length == 1"
+          - "output.target_group_arns[0] == out_tg1.target_group_arn"
+
+    - name: target group no change
+      ec2_asg:
+        name: "{{ resource_prefix }}-asg"
+        launch_template: 
+          launch_template_name: "{{ resource_prefix }}-lt"
+        target_group_arns:
+          - "{{ out_tg1.target_group_arn }}"
+        desired_capacity: 1
+        min_size: 1
+        max_size: 1
+        state: present
+        wait_for_instances: yes
+      register: output
+
+    - assert:
+        that:
+          - "output.target_group_arns | length == 1"
+          - "output.target_group_arns[0] == out_tg1.target_group_arn"
+          - "output.changed == false"
+
 # ============================================================
 
   always:
@@ -710,6 +838,18 @@
 
     # Remove the testing dependencies
 
+    - name: remove target group
+      elb_target_group:
+        name: "{{ item }}"
+        state: absent
+      register: removed
+      until: removed is not failed
+      ignore_errors: yes
+      retries: 10
+      loop:
+        - "{{ tg1_name }}"
+        - "{{ tg2_name }}"
+
     - name: remove the load balancer
       ec2_elb_lb:
         name: "{{ load_balancer_name }}"
@@ -738,7 +878,7 @@
 
     - name: remove launch configs
       ec2_lc:
-        name: "{{ resource_prefix }}-lc"
+        name: "{{ item }}"
         state: absent
       register: removed
       until: removed is not failed