Repository: ansible-collections/community.aws

Issue:
elb_target_group: support target_type alb
### Summary

Add support for `target_type: alb`  
Currently only `instance`, `ip`, and `lambda` are supported.

### Issue Type

Feature Idea

### Component Name

elb_target_group

### Additional Information

<!--- Paste example playbooks or commands between quotes below -->
```yaml (paste below)

```


### Code of Conduct

- [X] I agree to follow the Ansible Code of Conduct


Discussion:

Resolving patch:
diff --git a/plugins/modules/elb_target_group.py b/plugins/modules/elb_target_group.py
--- a/plugins/modules/elb_target_group.py
+++ b/plugins/modules/elb_target_group.py
@@ -76,13 +76,14 @@
     type: str
   port:
     description:
-      - The port on which the targets receive traffic. This port is used unless you specify a port override when registering the target. Required if
-        I(state) is C(present).
+      - The port on which the targets receive traffic. This port is used unless you specify a port override when registering the target.
+      - Required when I(state) is C(present) and I(target_type) is C(instance), C(ip), or C(alb).
     required: false
     type: int
   protocol:
     description:
-      - The protocol to use for routing traffic to the targets. Required when I(state) is C(present).
+      - The protocol to use for routing traffic to the targets.
+      - Required when I(state) is C(present) and I(target_type) is C(instance), C(ip), or C(alb).
     required: false
     choices: [ 'http', 'https', 'tcp', 'tls', 'udp', 'tcp_udp', 'HTTP', 'HTTPS', 'TCP', 'TLS', 'UDP', 'TCP_UDP']
     type: str
@@ -141,15 +142,16 @@
   target_type:
     description:
       - The type of target that you must specify when registering targets with this target group. The possible values are
-        C(instance) (targets are specified by instance ID), C(ip) (targets are specified by IP address) or C(lambda) (target is specified by ARN).
-        Note that you can't specify targets for a target group using more than one type. Target type lambda only accept one target. When more than
+        C(instance) (targets are specified by instance ID), C(ip) (targets are specified by IP address), C(lambda) (target is specified by ARN),
+        or C(alb) (target is specified by ARN).
+        Note that you can't specify targets for a target group using more than one type. Target types lambda and alb only accept one target. When more than
         one target is specified, only the first one is used. All additional targets are ignored.
         If the target type is ip, specify IP addresses from the subnets of the virtual private cloud (VPC) for the target
         group, the RFC 1918 range (10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16), and the RFC 6598 range (100.64.0.0/10).
         You can't specify publicly routable IP addresses.
       - The default behavior is C(instance).
     required: false
-    choices: ['instance', 'ip', 'lambda']
+    choices: ['instance', 'ip', 'lambda', 'alb']
     type: str
   targets:
     description:
@@ -165,7 +167,8 @@
     type: int
   vpc_id:
     description:
-      - The identifier of the virtual private cloud (VPC). Required when I(state) is C(present).
+      - The identifier of the virtual private cloud (VPC).
+      - Required when I(state) is C(present) and I(target_type) is C(instance), C(ip), or C(alb).
     required: false
     type: str
   preserve_client_ip_enabled:
@@ -891,7 +894,7 @@ def main():
         state=dict(required=True, choices=['present', 'absent']),
         successful_response_codes=dict(),
         tags=dict(default={}, type='dict'),
-        target_type=dict(choices=['instance', 'ip', 'lambda']),
+        target_type=dict(choices=['instance', 'ip', 'lambda', 'alb']),
         targets=dict(type='list', elements='dict'),
         unhealthy_threshold_count=dict(type='int'),
         vpc_id=dict(),
@@ -905,6 +908,7 @@ def main():
                               required_if=[
                                   ['target_type', 'instance', ['protocol', 'port', 'vpc_id']],
                                   ['target_type', 'ip', ['protocol', 'port', 'vpc_id']],
+                                  ['target_type', 'alb', ['protocol', 'port', 'vpc_id']],
                               ]
                               )
 


Test patch:
diff --git a/tests/integration/targets/elb_target/tasks/alb_target.yml b/tests/integration/targets/elb_target/tasks/alb_target.yml
new file mode 100644
--- /dev/null
+++ b/tests/integration/targets/elb_target/tasks/alb_target.yml
@@ -0,0 +1,205 @@
+---
+- name: test elb_target_group with target_type = alb
+  block:
+    - name: set up testing VPC
+      ec2_vpc_net:
+        name: "{{ resource_prefix }}-vpc"
+        state: present
+        cidr_block: 20.0.0.0/16
+        tags:
+          Name: "{{ resource_prefix }}-vpc"
+          Description: "Created by ansible-test"
+      register: vpc
+
+    - name: set up testing internet gateway
+      ec2_vpc_igw:
+        vpc_id: "{{ vpc.vpc.id }}"
+        state: present
+      register: igw
+
+    - name: set up testing subnet
+      ec2_vpc_subnet:
+        state: present
+        vpc_id: "{{ vpc.vpc.id }}"
+        cidr: 20.0.0.0/18
+        az: "{{ aws_region }}a"
+        resource_tags:
+          Name: "{{ resource_prefix }}-subnet"
+      register: subnet_1
+
+    - name: set up testing subnet
+      ec2_vpc_subnet:
+        state: present
+        vpc_id: "{{ vpc.vpc.id }}"
+        cidr: 20.0.64.0/18
+        az: "{{ aws_region }}b"
+        resource_tags:
+          Name: "{{ resource_prefix }}-subnet"
+      register: subnet_2
+
+    - name: create routing rules
+      ec2_vpc_route_table:
+        vpc_id: "{{ vpc.vpc.id }}"
+        tags:
+          created: "{{ resource_prefix }}-route"
+        routes:
+          - dest: 0.0.0.0/0
+            gateway_id: "{{ igw.gateway_id }}"
+        subnets:
+          - "{{ subnet_1.subnet.id }}"
+          - "{{ subnet_2.subnet.id }}"
+      register: route_table
+
+    - name: create testing security group
+      ec2_group:
+        name: "{{ resource_prefix }}-sg"
+        description: a security group for ansible tests
+        vpc_id: "{{ vpc.vpc.id }}"
+        rules:
+          - proto: tcp
+            from_port: 80
+            to_port: 80
+            cidr_ip: 0.0.0.0/0
+          - proto: tcp
+            from_port: 22
+            to_port: 22
+            cidr_ip: 0.0.0.0/0
+      register: sg
+
+    - name: set up testing target group for NLB (type=alb)
+      elb_target_group:
+        name: "{{ elb_target_group_name }}"
+        target_type: alb
+        state: present
+        protocol: TCP
+        port: 80
+        vpc_id: "{{ vpc.vpc.id }}"
+      register: elb_target_group
+
+    - name: assert target group was created successfully
+      assert:
+        that:
+          - elb_target_group.changed
+          - elb_target_group.target_group_name == elb_target_group_name
+          - elb_target_group.target_type == 'alb'
+          - elb_target_group.vpc_id == vpc.vpc.id
+          - elb_target_group.port == 80
+          - elb_target_group.protocol == 'TCP'
+          - elb_target_group.load_balancer_arns | length == 0
+
+    - name: create a network load balancer and attach to target group
+      elb_network_lb:
+        name: "{{ lb_name }}-nlb"
+        subnets:
+          - "{{ subnet_1.subnet.id }}"
+          - "{{ subnet_2.subnet.id }}"
+        listeners:
+          - Protocol: TCP
+            Port: 80
+            DefaultActions:
+              - Type: forward
+                TargetGroupName: "{{ elb_target_group_name }}"
+        state: present
+      register: nlb
+
+    - name: assert NLB was created successfully and attached to target group
+      assert:
+        that:
+          - nlb is changed
+          - nlb.listeners | length == 1
+          - nlb.listeners[0].default_actions[0].forward_config.target_groups[0].target_group_arn == elb_target_group.target_group_arn
+
+    - name: get target group info
+      elb_target_group_info:
+        load_balancer_arn: "{{ nlb.load_balancer_arn }}"
+      register: tg_info
+
+    - name: assert target group's target is nlb
+      assert:
+        that:
+          - tg_info.target_groups[0].target_group_name == elb_target_group_name
+          - tg_info.target_groups[0].target_type == 'alb'
+          - tg_info.target_groups[0].load_balancer_arns | length == 1
+          - tg_info.target_groups[0].load_balancer_arns[0] == nlb.load_balancer_arn
+
+  always:
+  - name: remove network load balancer
+    elb_network_lb:
+      name: "{{ lb_name }}-nlb"
+      state: absent
+      wait: true
+      wait_timeout: 600
+    register: removed
+    retries: 10
+    until: removed is not failed
+    ignore_errors: true
+
+  - name: remove elb target group
+    elb_target_group:
+      name: "{{ elb_target_group_name }}"
+      target_type: alb
+      state: absent
+      protocol: HTTP
+      port: 80
+      vpc_id: "{{ vpc.vpc.id }}"
+    ignore_errors: true
+
+  - name: remove routing rules
+    ec2_vpc_route_table:
+      state: absent
+      lookup: id
+      route_table_id: "{{ route_table.route_table.id }}"
+    register: removed
+    retries: 5
+    until: removed is not failed
+    ignore_errors: true
+
+  - name: remove testing subnet
+    ec2_vpc_subnet:
+      state: absent
+      vpc_id: "{{ vpc.vpc.id }}"
+      cidr: 20.0.0.0/18
+      az: "{{ aws_region }}a"
+    register: removed
+    retries: 10
+    until: removed is not failed
+    ignore_errors: true
+
+  - name: remove testing subnet
+    ec2_vpc_subnet:
+      state: absent
+      vpc_id: "{{ vpc.vpc.id }}"
+      cidr: 20.0.64.0/18
+      az: "{{ aws_region }}b"
+    register: removed
+    retries: 10
+    until: removed is not failed
+    ignore_errors: true
+
+  - name: remove testing security group
+    ec2_group:
+      state: absent
+      name: "{{ resource_prefix }}-sg"
+    register: removed
+    retries: 10
+    until: removed is not failed
+    ignore_errors: true
+
+  - name: remove testing internet gateway
+    ec2_vpc_igw:
+      vpc_id: "{{ vpc.vpc.id }}"
+      state: absent
+    register: removed
+    retries: 2
+    until: removed is not failed
+    ignore_errors: true
+
+  - name: remove testing VPC
+    ec2_vpc_net:
+      name: "{{ resource_prefix }}-vpc"
+      cidr_block: 20.0.0.0/16
+      state: absent
+    register: removed
+    retries: 2
+    until: removed is not failed
+    ignore_errors: true
\ No newline at end of file
diff --git a/tests/integration/targets/elb_target/tasks/lambda_target.yml b/tests/integration/targets/elb_target/tasks/lambda_target.yml
--- a/tests/integration/targets/elb_target/tasks/lambda_target.yml
+++ b/tests/integration/targets/elb_target/tasks/lambda_target.yml
@@ -91,7 +91,7 @@
       targets: []
     register: elb_target_group
 
-  - name: target is still the same, state must not be changed (idempotency)
+  - name: remove lambda target from target group
     assert:
       that:
         - elb_target_group.changed
diff --git a/tests/integration/targets/elb_target/tasks/main.yml b/tests/integration/targets/elb_target/tasks/main.yml
--- a/tests/integration/targets/elb_target/tasks/main.yml
+++ b/tests/integration/targets/elb_target/tasks/main.yml
@@ -12,3 +12,4 @@
   block:
     - include_tasks: ec2_target.yml
     - include_tasks: lambda_target.yml
+    - include_tasks: alb_target.yml