diff --git a/changelogs/fragments/migrate_elb_classic_lb_info.yml b/changelogs/fragments/migrate_elb_classic_lb_info.yml new file mode 100644 index 00000000000..60ec869a41e --- /dev/null +++ b/changelogs/fragments/migrate_elb_classic_lb_info.yml @@ -0,0 +1,5 @@ +--- +major_changes: + - elb_classic_lb_info - The module has been migrated from the ``community.aws`` + collection. Playbooks using the Fully Qualified Collection Name for this module + should be updated to use ``amazon.aws.elb_classic_lb_info``. diff --git a/meta/runtime.yml b/meta/runtime.yml index 94614615f1e..0b20328f0be 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -71,6 +71,7 @@ action_groups: - elb_application_lb - elb_application_lb_info - elb_classic_lb + - elb_classic_lb_info - execute_lambda - iam_access_key - iam_access_key_info @@ -162,14 +163,14 @@ plugin_routing: rds_param_group: redirect: amazon.aws.rds_instance_param_group deprecation: - removal_version: 10.0.0 - warning_text: >- - rds_param_group has been renamed to rds_instance_param_group. - Please update your tasks. + removal_version: 10.0.0 + warning_text: >- + rds_param_group has been renamed to rds_instance_param_group. + Please update your tasks. lookup: aws_ssm: # Deprecation for this alias should not *start* prior to 2024-09-01 redirect: amazon.aws.ssm_parameter aws_secret: # Deprecation for this alias should not *start* prior to 2024-09-01 - redirect: amazon.aws.secretsmanager_secret + redirect: amazon.aws.secretsmanager_secret \ No newline at end of file diff --git a/plugins/modules/elb_classic_lb_info.py b/plugins/modules/elb_classic_lb_info.py new file mode 100644 index 00000000000..308bc89ae39 --- /dev/null +++ b/plugins/modules/elb_classic_lb_info.py @@ -0,0 +1,506 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: Contributors to the Ansible project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: elb_classic_lb_info +version_added: 1.0.0 +version_added_collection: community.aws +short_description: Gather information about EC2 Classic Elastic Load Balancers in AWS +description: + - Gather information about EC2 Classic Elastic Load Balancers in AWS. +author: + - "Michael Schultz (@mjschultz)" + - "Fernando Jose Pando (@nand0p)" +options: + names: + description: + - List of ELB names to gather information about. Pass this option to gather information about a set of ELBs, otherwise, all ELBs are returned. + type: list + elements: str + default: [] +extends_documentation_fragment: + - amazon.aws.common.modules + - amazon.aws.region.modules + - amazon.aws.boto3 +""" + +EXAMPLES = r""" +# Note: These examples do not set authentication details, see the AWS Guide for details. +# Output format tries to match amazon.aws.elb_classic_lb module input parameters + +- name: Gather information about all ELBs + amazon.aws.elb_classic_lb_info: + register: elb_info + +- name: Gather information about a particular ELB + amazon.aws.elb_classic_lb_info: + names: frontend-prod-elb + register: elb_info + +- name: Gather information about a set of ELBs + amazon.aws.elb_classic_lb_info: + names: + - frontend-prod-elb + - backend-prod-elb + register: elb_info +""" + +RETURN = r""" +elbs: + description: A list of load balancers. + returned: always + type: list + elements: dict + contains: + attributes: + description: Information about the load balancer attributes. + returned: always + type: dict + contains: + access_log: + description: Information on whether access logs are enabled or not. + type: dict + sample: { + "enabled": false + } + additional_attributes: + description: Information about additional load balancer attributes. + type: list + elements: dict + sample: [ + { + "key": "elb.http.desyncmitigationmode", + "value": "defensive" + } + ] + connection_draining: + description: + - Information on connection draining configuration of elastic load balancer. + type: dict + sample: { + "enabled": true, + "timeout": 300 + } + contains: + enabled: + description: Whether connection draining is enabled. + type: bool + returned: always + timeout: + description: The maximum time, in seconds, to keep the existing connections open before deregistering the instances. + type: int + returned: always + connection_settings: + description: Information on connection settings. + type: dict + sample: { + "idle_timeout": 60 + } + cross_zone_load_balancing: + description: Information on whether cross zone load balancing is enabled or not. + type: dict + sample: { + "enabled": true + } + availability_zones: + description: The Availability Zones for the load balancer. + type: list + elements: str + returned: always + sample: [ + "us-west-2a" + ] + backend_server_descriptions: + description: Information about your EC2 instances. + type: list + elements: dict + returned: always + sample: [ + { + instance_port: 8085, + policy_names: [ + 'MyPolicy1', + ] + }, + ] + canonical_hosted_zone_name: + description: The DNS name of the load balancer. + type: str + returned: always + sample: "test-123456789.us-west-2.elb.amazonaws.com" + canonical_hosted_zone_name_id: + description: The ID of the Amazon Route 53 hosted zone for the load balancer. + type: str + returned: always + sample: "Z1Z1ZZ5HABSF5" + created_time: + description: The date and time the load balancer was created. + type: str + returned: always + sample: "2024-09-04T17:52:22.270000+00:00" + dns_name: + description: The DNS name of the load balancer. + type: str + returned: "always" + sample: "test-123456789.us-west-2.elb.amazonaws.com" + health_check: + description: Information about the health checks conducted on the load balancer. + type: dict + returned: always + sample: { + "healthy_threshold": 10, + "interval": 5, + "target": "HTTP:80/index.html", + "timeout": 2, + "unhealthy_threshold": 2 + } + contains: + healthy_threshold: + description: The number of consecutive health checks successes required before moving the instance to the Healthy state. + type: int + returned: always + interval: + description: The approximate interval, in seconds, between health checks of an individual instance. + type: int + returned: always + target: + description: The instance being checked. The protocol is either TCP, HTTP, HTTPS, or SSL. The range of valid ports is one (1) through 65535. + type: str + returned: always + timeout: + description: The amount of time, in seconds, during which no response means a failed health check. + type: int + returned: always + unhealthy_threshold: + description: The number of consecutive health checks successes required before moving the instance to the Unhealthy state. + type: int + returned: always + instances: + description: The IDs of the instances for the load balancer. + type: list + elements: dict + returned: always + sample: [ + { + "instance_id": "i-11d1f111ea111111b" + } + ] + instances_inservice: + description: Information about instances for load balancer in state "InService". + type: list + returned: always + sample: [ + "i-11d1f111ea111111b" + ] + instances_inservice_count: + description: Total number of instances for load balancer with state "InService". + type: int + returned: always + sample: 1 + instances_outofservice: + description: Information about instances for load balancer in state "OutOfService". + type: list + returned: always + sample: [ + "i-11d1f111ea111111b" + ] + instances_outofservice_count: + description: Total number of instances for load balancer with state "OutOfService". + type: int + returned: always + sample: 0 + instances_unknownservice: + description: Information about instances for load balancer in state "Unknown". + type: list + returned: always + sample: [ + "i-11d1f111ea111111b" + ] + instances_unknownservice_count: + description: Total number of instances for load balancer with state "Unknown". + type: int + returned: always + sample: 1 + listener_descriptions: + description: Information about the listeners for the load balancer. + type: list + elements: dict + returned: always + sample: [ + { + "listener": { + "instance_port": 80, + "instance_protocol": "HTTP", + "load_balancer_port": 80, + "protocol": "HTTP" + }, + "policy_names": [] + } + ] + load_balancer_name: + description: The name of the elastic load balancer. + type: str + returned: always + sample: "MyLoadBalancer" + policies: + description: Information about the policies defined for the load balancer. + type: dict + returned: always + sample: { + "app_cookie_stickiness_policies": [], + "lb_cookie_stickiness_policies": [], + "other_policies": [] + } + contains: + app_cookie_stickiness_policies: + description: The stickiness policies created using CreateAppCookieStickinessPolicy. + type: list + returned: always + lb_cookie_stickiness_policies: + description: The stickiness policies created using CreateLBCookieStickinessPolicy. + type: list + returned: always + other_policies: + description: The policies other than the stickiness policies. + type: list + returned: always + scheme: + description: The type of load balancer. + type: str + returned: always + sample: "internet-facing" + security_groups: + description: The security groups for the load balancer. + type: list + returned: always + sample: [ + "sg-111111af1111cb111" + ] + source_security_group: + description: + - The security group for the load balancer, + which are used as part of inbound rules for registered instances. + type: dict + returned: always + sample: { + "group_name": "default", + "owner_alias": "721111111111" + } + contains: + group_name: + description: The name of the security group. + type: str + returned: always + owner_alias: + description: The owner of the security group. + type: str + returned: always + subnets: + description: The IDs of the subnets for the load balancer. + type: list + returned: always + sample: [ + "subnet-111111af1111cb111" + ] + tags: + description: The tags associated with a load balancer. + type: dict + returned: always + sample: { + "Env": "Dev", + "Owner": "Dev001" + } + vpc_id: + description: The ID of the VPC for the load balancer. + type: str + returned: always + sample: "vpc-0cc28c9e20d111111" +""" + +from typing import Any +from typing import Dict +from typing import List +from typing import Tuple +from typing import Union + +try: + import botocore +except ImportError: + pass # caught by AnsibleAWSModule + +from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict + +from ansible_collections.amazon.aws.plugins.module_utils.botocore import is_boto3_error_code +from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry +from ansible_collections.amazon.aws.plugins.module_utils.tagging import boto3_tag_list_to_ansible_dict + + +def list_elbs(connection: Any, load_balancer_names: List[str]) -> List[Dict]: + """ + List Elastic Load Balancers (ELBs) and their detailed information. + + Parameters: + connection (boto3.client): The Boto3 ELB client object. + load_balancer_names (List[str]): List of ELB names to gather information about. + + Returns: + A list of dictionaries where each dictionary contains informtion about one ELB. + """ + results = [] + + if not load_balancer_names: + for lb in get_all_lb(connection): + results.append(describe_elb(connection, lb)) + + for load_balancer_name in load_balancer_names: + lb = get_lb(connection, load_balancer_name) + if not lb: + continue + results.append(describe_elb(connection, lb)) + return results + + +def describe_elb(connection: Any, lb: Dict[str, Any]) -> Dict[str, Any]: + """ + Describes an Elastic Load Balancer (ELB). + + Parameters: + connection (boto3.client): The Boto3 ELB client object. + lb (Dict): Dictionary containing ELB . + + Returns: + A dictionary with detailed information of the ELB. + """ + description = camel_dict_to_snake_dict(lb) + name = lb["LoadBalancerName"] + instances = lb.get("Instances", []) + description["tags"] = get_tags(connection, name) + description["instances_inservice"], description["instances_inservice_count"] = lb_instance_health( + connection, name, instances, "InService" + ) + description["instances_outofservice"], description["instances_outofservice_count"] = lb_instance_health( + connection, name, instances, "OutOfService" + ) + description["instances_unknownservice"], description["instances_unknownservice_count"] = lb_instance_health( + connection, name, instances, "Unknown" + ) + description["attributes"] = get_lb_attributes(connection, name) + return description + + +@AWSRetry.jittered_backoff() +def get_all_lb(connection: Any) -> List: + """ + Get paginated result for information of all Elastic Load Balancers. + + Parameters: + connection (boto3.client): The Boto3 ELB client object. + + Returns: + A list of dictionaries containing descriptions of all ELBs. + """ + paginator = connection.get_paginator("describe_load_balancers") + return paginator.paginate().build_full_result()["LoadBalancerDescriptions"] + + +def get_lb(connection: Any, load_balancer_name: str) -> Union[Dict[str, Any], List]: + """ + Describes a specific Elastic Load Balancer (ELB) by name. + + Parameters: + connection (boto3.client): The Boto3 ELB client object. + load_balancer_name (str): Name of the ELB to gather information about. + + Returns: + A dictionary with detailed information of the specified ELB. + """ + try: + return connection.describe_load_balancers(aws_retry=True, LoadBalancerNames=[load_balancer_name])[ + "LoadBalancerDescriptions" + ][0] + except is_boto3_error_code("LoadBalancerNotFound"): + return [] + + +def get_lb_attributes(connection: Any, load_balancer_name: str) -> Dict[str, Any]: + """ + Retrieves attributes of specific Elastic Load Balancer (ELB) by name. + + Parameters: + connection (boto3.client): The Boto3 ELB client object. + load_balancer_name (str): Name of the ELB to gather information about. + + Returns: + A dictionary with detailed information of the attributes of specified ELB. + """ + attributes = connection.describe_load_balancer_attributes(aws_retry=True, LoadBalancerName=load_balancer_name).get( + "LoadBalancerAttributes", {} + ) + return camel_dict_to_snake_dict(attributes) + + +def get_tags(connection: Any, load_balancer_name: str) -> Dict[str, Any]: + """ + Retrieves tags of specific Elastic Load Balancer (ELB) by name. + + Parameters: + connection (boto3.client): The Boto3 ELB client object. + load_balancer_name (str): Name of the ELB to gather information about. + + Returns: + A dictionary of tags associated with the specified ELB. + """ + tags = connection.describe_tags(aws_retry=True, LoadBalancerNames=[load_balancer_name])["TagDescriptions"] + if not tags: + return {} + return boto3_tag_list_to_ansible_dict(tags[0]["Tags"]) + + +def lb_instance_health( + connection: Any, load_balancer_name: str, instances: List[Dict[str, Any]], state: str +) -> Tuple[List[str], int]: + """ + Describes the health status of instances associated with a specific Elastic Load Balancer (ELB). + + Parameters: + connection (Any): The Boto3 client object for ELB. + load_balancer_name (str): The name of the ELB. + instances (List[Dict]): List of dictionaries containing instances associated with the ELB. + state (str): The health state to filter by (e.g., "InService", "OutOfService", "Unknown"). + + Returns: + Tuple[List, int]: A tuple containing a list of instance IDs matching state and the count of matching instances. + """ + instance_states = connection.describe_instance_health(LoadBalancerName=load_balancer_name, Instances=instances).get( + "InstanceStates", [] + ) + instate = [instance["InstanceId"] for instance in instance_states if instance["State"] == state] + return instate, len(instate) + + +def main(): + argument_spec = dict( + names=dict(default=[], type="list", elements="str"), + ) + module = AnsibleAWSModule( + argument_spec=argument_spec, + supports_check_mode=True, + ) + + connection = module.client("elb", retry_decorator=AWSRetry.jittered_backoff(retries=5, delay=5)) + + try: + elbs = list_elbs(connection, module.params.get("names")) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + module.fail_json_aws(e, msg="Failed to get load balancer information.") + + module.exit_json(elbs=elbs) + + +if __name__ == "__main__": + main() diff --git a/tests/integration/targets/elb_classic_lb/tasks/basic_internal.yml b/tests/integration/targets/elb_classic_lb/tasks/basic_internal.yml index 5a6f9d6c300..e5e043eaad1 100644 --- a/tests/integration/targets/elb_classic_lb/tasks/basic_internal.yml +++ b/tests/integration/targets/elb_classic_lb/tasks/basic_internal.yml @@ -75,7 +75,7 @@ that: - info.network_interfaces | length > 0 - - community.aws.elb_classic_lb_info: + - amazon.aws.elb_classic_lb_info: names: ["{{ elb_name }}"] register: info diff --git a/tests/integration/targets/elb_classic_lb/tasks/basic_public.yml b/tests/integration/targets/elb_classic_lb/tasks/basic_public.yml index c427a50626d..ab5b0b88a60 100644 --- a/tests/integration/targets/elb_classic_lb/tasks/basic_public.yml +++ b/tests/integration/targets/elb_classic_lb/tasks/basic_public.yml @@ -71,7 +71,7 @@ that: - info.network_interfaces | length > 0 - - community.aws.elb_classic_lb_info: + - amazon.aws.elb_classic_lb_info: names: ["{{ elb_name }}"] register: info diff --git a/tests/integration/targets/elb_classic_lb_info/aliases b/tests/integration/targets/elb_classic_lb_info/aliases new file mode 100644 index 00000000000..4ef4b2067d0 --- /dev/null +++ b/tests/integration/targets/elb_classic_lb_info/aliases @@ -0,0 +1 @@ +cloud/aws diff --git a/tests/integration/targets/elb_classic_lb_info/defaults/main.yml b/tests/integration/targets/elb_classic_lb_info/defaults/main.yml new file mode 100644 index 00000000000..7279a8194da --- /dev/null +++ b/tests/integration/targets/elb_classic_lb_info/defaults/main.yml @@ -0,0 +1,2 @@ +# defaults file for test_ec2_eip +elb_name: ansible-test-{{ tiny_prefix }}-ecli diff --git a/tests/integration/targets/elb_classic_lb_info/tasks/main.yml b/tests/integration/targets/elb_classic_lb_info/tasks/main.yml new file mode 100644 index 00000000000..407933733c4 --- /dev/null +++ b/tests/integration/targets/elb_classic_lb_info/tasks/main.yml @@ -0,0 +1,317 @@ +# __Test Info__ +# Create a self signed cert and upload it to AWS +# http://www.akadia.com/services/ssh_test_certificate.html +# http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/ssl-server-cert.html + +# __Test Outline__ +# +# __elb_classic_lb__ +# create test elb with listeners and certificate +# change AZ's +# change listeners +# remove listeners +# remove elb + +# __amazon.aws.elb_classic_lb_info_ +# get nonexistent load balancer + +- module_defaults: + group/aws: + region: '{{ aws_region }}' + access_key: '{{ aws_access_key }}' + secret_key: '{{ aws_secret_key }}' + session_token: '{{ security_token | default(omit) }}' + block: + + # ============================================================ + # create test elb with listeners, certificate, and health check + + - name: Create ELB + amazon.aws.elb_classic_lb: + name: '{{ elb_name }}' + state: present + zones: + - '{{ aws_region }}a' + - '{{ aws_region }}b' + listeners: + - protocol: http + load_balancer_port: 80 + instance_port: 80 + - protocol: http + load_balancer_port: 8080 + instance_port: 8080 + health_check: + ping_protocol: http + ping_port: 80 + ping_path: /index.html + response_timeout: 5 + interval: 30 + unhealthy_threshold: 2 + healthy_threshold: 10 + register: create + + - assert: + that: + - create is changed + # We rely on these for the info test, make sure they're what we expect + - aws_region ~ 'a' in create.elb.zones + - aws_region ~ 'b' in create.elb.zones + - create.elb.health_check.healthy_threshold == 10 + - create.elb.health_check.interval == 30 + - create.elb.health_check.target == "HTTP:80/index.html" + - create.elb.health_check.timeout == 5 + - create.elb.health_check.unhealthy_threshold == 2 + - '[80, 80, "HTTP", "HTTP"] in create.elb.listeners' + - '[8080, 8080, "HTTP", "HTTP"] in create.elb.listeners' + + - name: Get ELB info + amazon.aws.elb_classic_lb_info: + names: '{{ elb_name }}' + register: info + + - assert: + that: + - info.elbs|length == 1 + - elb.availability_zones|length == 2 + - aws_region ~ 'a' in elb.availability_zones + - aws_region ~ 'b' in elb.availability_zones + - elb.health_check.healthy_threshold == 10 + - elb.health_check.interval == 30 + - elb.health_check.target == "HTTP:80/index.html" + - elb.health_check.timeout == 5 + - elb.health_check.unhealthy_threshold == 2 + - '{"instance_port": 80, "instance_protocol": "HTTP", "load_balancer_port": + 80, "protocol": "HTTP"} == listeners[0]' + - '{"instance_port": 8080, "instance_protocol": "HTTP", "load_balancer_port": + 8080, "protocol": "HTTP"} == listeners[1]' + vars: + elb: '{{ info.elbs[0] }}' + listeners: "{{ elb.listener_descriptions|map(attribute='listener')|sort(attribute='load_balancer_port') + }}" + + # ============================================================ + + # check ports, would be cool, but we are at the mercy of AWS + # to start things in a timely manner + + #- name: check to make sure 80 is listening + # wait_for: host={{ info.elb.dns_name }} port=80 timeout=600 + # register: result + + #- name: assert can connect to port# + # assert: 'result.state == "started"' + + #- name: check to make sure 443 is listening + # wait_for: host={{ info.elb.dns_name }} port=443 timeout=600 + # register: result + + #- name: assert can connect to port# + # assert: 'result.state == "started"' + + # ============================================================ + + # Change AZ's + + - name: Change AZ's + amazon.aws.elb_classic_lb: + name: '{{ elb_name }}' + state: present + zones: + - '{{ aws_region }}c' + listeners: + - protocol: http + load_balancer_port: 80 + instance_port: 80 + purge_zones: yes + health_check: + ping_protocol: http + ping_port: 80 + ping_path: /index.html + response_timeout: 5 + interval: 30 + unhealthy_threshold: 2 + healthy_threshold: 10 + register: update_az + + - assert: + that: + - update_az is changed + - update_az.elb.zones[0] == aws_region ~ 'c' + + - name: Get ELB info after changing AZ's + amazon.aws.elb_classic_lb_info: + names: '{{ elb_name }}' + register: info + + - assert: + that: + - elb.availability_zones|length == 1 + - aws_region ~ 'c' in elb.availability_zones[0] + vars: + elb: '{{ info.elbs[0] }}' + + # ============================================================ + + # Update AZ's + + - name: Update AZ's + amazon.aws.elb_classic_lb: + name: '{{ elb_name }}' + state: present + zones: + - '{{ aws_region }}a' + - '{{ aws_region }}b' + - '{{ aws_region }}c' + listeners: + - protocol: http + load_balancer_port: 80 + instance_port: 80 + purge_zones: yes + register: update_az + + - assert: + that: + - update_az is changed + - aws_region ~ 'a' in update_az.elb.zones + - aws_region ~ 'b' in update_az.elb.zones + - aws_region ~ 'c' in update_az.elb.zones + + - name: Get ELB info after updating AZ's + amazon.aws.elb_classic_lb_info: + names: '{{ elb_name }}' + register: info + + - assert: + that: + - elb.availability_zones|length == 3 + - aws_region ~ 'a' in elb.availability_zones + - aws_region ~ 'b' in elb.availability_zones + - aws_region ~ 'c' in elb.availability_zones + vars: + elb: '{{ info.elbs[0] }}' + + # ============================================================ + + # Purge Listeners + + - name: Purge Listeners + amazon.aws.elb_classic_lb: + name: '{{ elb_name }}' + state: present + zones: + - '{{ aws_region }}a' + - '{{ aws_region }}b' + - '{{ aws_region }}c' + listeners: + - protocol: http + load_balancer_port: 80 + instance_port: 81 + purge_listeners: yes + register: purge_listeners + + - assert: + that: + - purge_listeners is changed + - '[80, 81, "HTTP", "HTTP"] in purge_listeners.elb.listeners' + - purge_listeners.elb.listeners|length == 1 + + - name: Get ELB info after purging listeners + amazon.aws.elb_classic_lb_info: + names: '{{ elb_name }}' + register: info + + - assert: + that: + - elb.listener_descriptions|length == 1 + - '{"instance_port": 81, "instance_protocol": "HTTP", "load_balancer_port": + 80, "protocol": "HTTP"} == elb.listener_descriptions[0].listener' + vars: + elb: '{{ info.elbs[0] }}' + + + # ============================================================ + + # add Listeners + + - name: Add Listeners + amazon.aws.elb_classic_lb: + name: '{{ elb_name }}' + state: present + zones: + - '{{ aws_region }}a' + - '{{ aws_region }}b' + - '{{ aws_region }}c' + listeners: + - protocol: http + load_balancer_port: 8081 + instance_port: 8081 + purge_listeners: no + register: update_listeners + + - assert: + that: + - update_listeners is changed + - '[80, 81, "HTTP", "HTTP"] in update_listeners.elb.listeners' + - '[8081, 8081, "HTTP", "HTTP"] in update_listeners.elb.listeners' + - update_listeners.elb.listeners|length == 2 + + - name: Get ELB info after adding listeners + amazon.aws.elb_classic_lb_info: + names: '{{ elb_name }}' + register: info + + - assert: + that: + - elb.listener_descriptions|length == 2 + - '{"instance_port": 81, "instance_protocol": "HTTP", "load_balancer_port": + 80, "protocol": "HTTP"} == listeners[0]' + - '{"instance_port": 8081, "instance_protocol": "HTTP", "load_balancer_port": + 8081, "protocol": "HTTP"} == listeners[1]' + vars: + elb: '{{ info.elbs[0] }}' + listeners: "{{ elb.listener_descriptions|map(attribute='listener')|sort(attribute='load_balancer_port') + }}" + + # ============================================================ + + # Test getting nonexistent load balancer + - name: get nonexistent load balancer + amazon.aws.elb_classic_lb_info: + names: invalid-elb + register: info + + - assert: + that: + - info.elbs|length==0 + + # Test getting a valid and nonexistent load balancer + - name: get nonexistent load balancer + amazon.aws.elb_classic_lb_info: + names: ['{{ elb_name }}', invalid-elb] + register: info + + - assert: + that: + - info.elbs|length==1 + - info.elbs[0].load_balancer_name == elb_name + + # ============================================================ + + - name: get all load balancers + amazon.aws.elb_classic_lb_info: + names: '{{ omit }}' + register: info + + - assert: + that: + - info.elbs|length>0 + + always: + + # ============================================================ + - name: remove the test load balancer completely + amazon.aws.elb_classic_lb: + name: '{{ elb_name }}' + state: absent + register: result + ignore_errors: true