From 7bb925489e7338975973cdcd9aacfe2870053b09 Mon Sep 17 00:00:00 2001 From: Alexandre Mulatinho Date: Thu, 19 Dec 2019 19:06:16 -0300 Subject: [PATCH] elb_{network_lb,target_group}: allow UDP/TCP_UDP (#65828) elb_network_lb.py: allow UDP and TCP_UDP protocols - Fixing documentation - Add support to UDP and TCP_UDP as described on AWS SDK elb_target_group.py: allow UDP, TLS, TCP_UDP proto - Fixing documentation - Making health checks with response codes and paths only in HTTP/HTTPS - Allow UDP, TLS, TCP_UDP protocols as described on AWS SDK. others: - Added changelog fragments - Integration test Fixes: #65265 Signed-off-by: Alexandre Mulatinho --- .../65265-allow-udp-tcpudp-protocol.yaml | 3 ++ .../modules/cloud/amazon/elb_network_lb.py | 9 ++--- .../modules/cloud/amazon/elb_target_group.py | 25 +++++++------- .../targets/elb_network_lb/defaults/main.yml | 1 + .../targets/elb_network_lb/tasks/main.yml | 27 +++++++++++++++ .../tasks/test_creating_nlb.yml | 24 +++++++++++-- .../roles/elb_target/defaults/main.yml | 1 + .../playbooks/roles/elb_target/tasks/main.yml | 34 +++++++++++++++++++ 8 files changed, 106 insertions(+), 18 deletions(-) create mode 100644 changelogs/fragments/65265-allow-udp-tcpudp-protocol.yaml diff --git a/changelogs/fragments/65265-allow-udp-tcpudp-protocol.yaml b/changelogs/fragments/65265-allow-udp-tcpudp-protocol.yaml new file mode 100644 index 00000000000..7253e1c9c78 --- /dev/null +++ b/changelogs/fragments/65265-allow-udp-tcpudp-protocol.yaml @@ -0,0 +1,3 @@ +minor_changes: + - elb_network_lb - added support to UDP and TCP_UDP protocols + - elb_target_group - allow UDP and TCP_UDP protocols; permit only HTTP/HTTPS health checks using response codes and paths diff --git a/lib/ansible/modules/cloud/amazon/elb_network_lb.py b/lib/ansible/modules/cloud/amazon/elb_network_lb.py index 4b9d6d90994..141223ce563 100644 --- a/lib/ansible/modules/cloud/amazon/elb_network_lb.py +++ b/lib/ansible/modules/cloud/amazon/elb_network_lb.py @@ -145,7 +145,7 @@ EXAMPLES = ''' - subnet-012345678 - subnet-abcdef000 listeners: - - Protocol: TCP # Required. The protocol for connections from clients to the load balancer (TCP or TLS) (case-sensitive). + - Protocol: TCP # Required. The protocol for connections from clients to the load balancer (TCP, TLS, UDP or TCP_UDP) (case-sensitive). Port: 80 # Required. The port on which the load balancer is listening. DefaultActions: - Type: forward # Required. Only 'forward' is accepted at this time @@ -159,7 +159,7 @@ EXAMPLES = ''' - SubnetId: subnet-012345678 AllocationId: eipalloc-aabbccdd listeners: - - Protocol: TCP # Required. The protocol for connections from clients to the load balancer (TCP or TLS) (case-sensitive). + - Protocol: TCP # Required. The protocol for connections from clients to the load balancer (TCP, TLS, UDP or TCP_UDP) (case-sensitive). Port: 80 # Required. The port on which the load balancer is listening. DefaultActions: - Type: forward # Required. Only 'forward' is accepted at this time @@ -450,8 +450,9 @@ def main(): if listeners is not None: for listener in listeners: for key in listener.keys(): - if key == 'Protocol' and listener[key] not in ['TCP', 'TLS']: - module.fail_json(msg="'Protocol' must be either 'TCP' or 'TLS'") + protocols_list = ['TCP', 'TLS', 'UDP', 'TCP_UDP'] + if key == 'Protocol' and listener[key] not in protocols_list: + module.fail_json(msg="'Protocol' must be either " + ", ".join(protocols_list)) connection = module.client('elbv2') connection_ec2 = module.client('ec2') diff --git a/lib/ansible/modules/cloud/amazon/elb_target_group.py b/lib/ansible/modules/cloud/amazon/elb_target_group.py index c5b3a2d6723..a9192bd73b2 100644 --- a/lib/ansible/modules/cloud/amazon/elb_target_group.py +++ b/lib/ansible/modules/cloud/amazon/elb_target_group.py @@ -31,7 +31,7 @@ options: description: - The protocol the load balancer uses when performing health checks on targets. required: false - choices: [ 'http', 'https', 'tcp', 'HTTP', 'HTTPS', 'TCP' ] + choices: [ 'http', 'https', 'tcp', 'tls', 'udp', 'tcp_udp', 'HTTP', 'HTTPS', 'TCP', 'TLS', 'UDP', 'TCP_UDP'] type: str health_check_port: description: @@ -81,7 +81,7 @@ options: description: - The protocol to use for routing traffic to the targets. Required when I(state) is C(present). required: false - choices: [ 'http', 'https', 'tcp', 'HTTP', 'HTTPS', 'TCP'] + choices: [ 'http', 'https', 'tcp', 'tls', 'udp', 'tcp_udp', 'HTTP', 'HTTPS', 'TCP', 'TLS', 'UDP', 'TCP_UDP'] type: str purge_tags: description: @@ -480,7 +480,8 @@ def create_or_update_target_group(connection, module): params['UnhealthyThresholdCount'] = module.params.get("unhealthy_threshold_count") # Only need to check response code and path for http(s) health checks - if module.params.get("health_check_protocol") is not None and module.params.get("health_check_protocol").upper() != 'TCP': + protocol = module.params.get("health_check_protocol") + if protocol is not None and protocol.upper() in ['HTTP', 'HTTPS']: if module.params.get("health_check_path") is not None: params['HealthCheckPath'] = module.params.get("health_check_path") @@ -535,7 +536,7 @@ def create_or_update_target_group(connection, module): health_check_params['UnhealthyThresholdCount'] = params['UnhealthyThresholdCount'] # Only need to check response code and path for http(s) health checks - if tg['HealthCheckProtocol'] != 'TCP': + if tg['HealthCheckProtocol'] in ['HTTP', 'HTTPS']: # Health check path if 'HealthCheckPath'in params and tg['HealthCheckPath'] != params['HealthCheckPath']: health_check_params['HealthCheckPath'] = params['HealthCheckPath'] @@ -799,11 +800,13 @@ def delete_target_group(connection, module): def main(): + protocols_list = ['http', 'https', 'tcp', 'tls', 'udp', 'tcp_udp', 'HTTP', + 'HTTPS', 'TCP', 'TLS', 'UDP', 'TCP_UDP'] argument_spec = ec2_argument_spec() argument_spec.update( dict( deregistration_delay_timeout=dict(type='int'), - health_check_protocol=dict(choices=['http', 'https', 'tcp', 'HTTP', 'HTTPS', 'TCP']), + health_check_protocol=dict(choices=protocols_list), health_check_port=dict(), health_check_path=dict(), health_check_interval=dict(type='int'), @@ -812,7 +815,7 @@ def main(): modify_targets=dict(default=True, type='bool'), name=dict(required=True), port=dict(type='int'), - protocol=dict(choices=['http', 'https', 'tcp', 'HTTP', 'HTTPS', 'TCP']), + protocol=dict(choices=protocols_list), purge_tags=dict(default=True, type='bool'), stickiness_enabled=dict(type='bool'), stickiness_type=dict(default='lb_cookie'), @@ -829,12 +832,10 @@ def main(): ) ) - module = AnsibleAWSModule(argument_spec=argument_spec, - required_if=[ - ['target_type', 'instance', ['protocol', 'port', 'vpc_id']], - ['target_type', 'ip', ['protocol', 'port', 'vpc_id']], - ] - ) + module = AnsibleAWSModule(argument_spec=argument_spec, required_if=[ + ['target_type', 'instance', ['protocol', 'port', 'vpc_id']], + ['target_type', 'ip', ['protocol', 'port', 'vpc_id']], + ]) connection = module.client('elbv2') diff --git a/test/integration/targets/elb_network_lb/defaults/main.yml b/test/integration/targets/elb_network_lb/defaults/main.yml index ad31bf839d9..5ee3fa45379 100644 --- a/test/integration/targets/elb_network_lb/defaults/main.yml +++ b/test/integration/targets/elb_network_lb/defaults/main.yml @@ -4,3 +4,4 @@ # was created and allows tests to be run in parallel nlb_name: "my-nlb-{{ resource_prefix | regex_search('([0-9]+)$') }}" tg_name: "my-tg-{{ resource_prefix | regex_search('([0-9]+)$') }}" +tg_tcpudp_name: "my-tg-tcpudp-{{ resource_prefix | regex_search('([0-9]+)$') }}" diff --git a/test/integration/targets/elb_network_lb/tasks/main.yml b/test/integration/targets/elb_network_lb/tasks/main.yml index 7cee4422a77..f2d77a67bbe 100644 --- a/test/integration/targets/elb_network_lb/tasks/main.yml +++ b/test/integration/targets/elb_network_lb/tasks/main.yml @@ -110,6 +110,16 @@ <<: *aws_connection_info register: tg + - name: create a target group for testing tcp_udp protocols + elb_target_group: + name: "{{ tg_tcpudp_name }}" + protocol: tcp_udp + port: 80 + vpc_id: "{{ vpc.vpc.id }}" + state: present + <<: *aws_connection_info + register: tg_tcpudp + - include_tasks: test_nlb_bad_listener_options.yml - include_tasks: test_nlb_tags.yml - include_tasks: test_creating_nlb.yml @@ -145,6 +155,23 @@ when: tg is defined ignore_errors: yes + - name: destroy tcp_udp target group if it was created + elb_target_group: + name: "{{ tg_tcpudp_name }}" + protocol: tcp_udp + port: 80 + vpc_id: "{{ vpc.vpc.id }}" + state: absent + wait: yes + wait_timeout: 600 + <<: *aws_connection_info + register: remove_tg + retries: 5 + delay: 3 + until: remove_tg is success + when: tg_tcpudp is defined + ignore_errors: yes + - name: destroy sec group ec2_group: name: "{{ sec_group.group_name }}" diff --git a/test/integration/targets/elb_network_lb/tasks/test_creating_nlb.yml b/test/integration/targets/elb_network_lb/tasks/test_creating_nlb.yml index ca502452a1a..b99af17b38f 100644 --- a/test/integration/targets/elb_network_lb/tasks/test_creating_nlb.yml +++ b/test/integration/targets/elb_network_lb/tasks/test_creating_nlb.yml @@ -27,13 +27,23 @@ DefaultActions: - Type: forward TargetGroupName: "{{ tg_name }}" + - Protocol: UDP + Port: 13 + DefaultActions: + - Type: forward + TargetGroupName: "{{ tg_tcpudp_name }}" + - Protocol: TCP_UDP + Port: 17 + DefaultActions: + - Type: forward + TargetGroupName: "{{ tg_tcpudp_name }}" <<: *aws_connection_info register: nlb - assert: that: - nlb.changed - - nlb.listeners|length == 2 + - nlb.listeners|length == 4 - name: test idempotence creating NLB with listeners elb_network_lb: @@ -53,10 +63,20 @@ DefaultActions: - Type: forward TargetGroupName: "{{ tg_name }}" + - Protocol: UDP + Port: 13 + DefaultActions: + - Type: forward + TargetGroupName: "{{ tg_tcpudp_name }}" + - Protocol: TCP_UDP + Port: 17 + DefaultActions: + - Type: forward + TargetGroupName: "{{ tg_tcpudp_name }}" <<: *aws_connection_info register: nlb - assert: that: - not nlb.changed - - nlb.listeners|length == 2 \ No newline at end of file + - nlb.listeners|length == 4 diff --git a/test/integration/targets/elb_target/playbooks/roles/elb_target/defaults/main.yml b/test/integration/targets/elb_target/playbooks/roles/elb_target/defaults/main.yml index 75df402a02d..b9ff75083de 100644 --- a/test/integration/targets/elb_target/playbooks/roles/elb_target/defaults/main.yml +++ b/test/integration/targets/elb_target/playbooks/roles/elb_target/defaults/main.yml @@ -4,4 +4,5 @@ ec2_ami_image: us-east-2: ami-c5062ba0 tg_name: "ansible-test-{{ resource_prefix | regex_search('([0-9]+)$') }}-tg" +tg_tcpudp_name: "ansible-test-{{ resource_prefix | regex_search('([0-9]+)$') }}-tgtcpudp" lb_name: "ansible-test-{{ resource_prefix | regex_search('([0-9]+)$') }}-lb" diff --git a/test/integration/targets/elb_target/playbooks/roles/elb_target/tasks/main.yml b/test/integration/targets/elb_target/playbooks/roles/elb_target/tasks/main.yml index 4afedd3e534..b6a2cb030a7 100644 --- a/test/integration/targets/elb_target/playbooks/roles/elb_target/tasks/main.yml +++ b/test/integration/targets/elb_target/playbooks/roles/elb_target/tasks/main.yml @@ -102,6 +102,19 @@ Description: "Created by {{ resource_prefix }}" <<: *aws_connection_info + - name: set up testing target group (type=instance) with UDP protocol + elb_target_group: + name: "{{ tg_tcpudp_name }}" + protocol: udp + port: 53 + vpc_id: '{{ vpc.vpc.id }}' + state: present + target_type: instance + tags: + Protocol: "UDP" + Description: "Created by {{ resource_prefix }}" + <<: *aws_connection_info + - name: set up testing target group for ALB (type=instance) elb_target_group: name: "{{ tg_name }}-used" @@ -362,6 +375,27 @@ - "{{ tg_name }}-used" ignore_errors: true + - name: remove udp testing target groups + elb_target_group: + name: "{{ item }}" + protocol: udp + port: 53 + vpc_id: '{{ vpc.vpc.id }}' + state: absent + target_type: instance + tags: + Description: "Created by {{ resource_prefix }}" + Protocol: "UDP" + wait: true + wait_timeout: 200 + <<: *aws_connection_info + register: removed + retries: 10 + until: removed is not failed + with_items: + - "{{ tg_tcpudp_name }}" + ignore_errors: true + - name: remove application load balancer elb_application_lb: name: "{{ lb_name }}"