# Buggy code
def _compare_listener(self, current_listener, new_listener):
    """
    Compare two listeners.

    :param current_listener:
    :param new_listener:
    :return:
    """

    modified_listener = {}

    # Port
    if current_listener["Port"] != new_listener["Port"]:
        modified_listener["Port"] = new_listener["Port"]

    # Protocol
    if current_listener["Protocol"] != new_listener["Protocol"]:
        modified_listener["Protocol"] = new_listener["Protocol"]

    # If Protocol is HTTPS, check additional attributes
    if current_listener["Protocol"] == "HTTPS" and new_listener["Protocol"] == "HTTPS":
        # Cert
        if current_listener["SslPolicy"] != new_listener["SslPolicy"]:
            modified_listener["SslPolicy"] = new_listener["SslPolicy"]
        if (
            current_listener["Certificates"][0]["CertificateArn"]
            != new_listener["Certificates"][0]["CertificateArn"]
        ):
            modified_listener["Certificates"] = []
            modified_listener["Certificates"].append({})
            modified_listener["Certificates"][0]["CertificateArn"] = new_listener[
                "Certificates"
            ][0]["CertificateArn"]
    elif (
        current_listener["Protocol"] != "HTTPS" and new_listener["Protocol"] == "HTTPS"
    ):
        modified_listener["SslPolicy"] = new_listener["SslPolicy"]
        modified_listener["Certificates"] = []
        modified_listener["Certificates"].append({})
        modified_listener["Certificates"][0]["CertificateArn"] = new_listener[
            "Certificates"
        ][0]["CertificateArn"]

    # Default action
    #   We wont worry about the Action Type because it is always 'forward'
    if (
        current_listener["DefaultActions"][0]["TargetGroupArn"]
        != new_listener["DefaultActions"][0]["TargetGroupArn"]
    ):
        modified_listener["DefaultActions"] = []
        modified_listener["DefaultActions"].append({})
        modified_listener["DefaultActions"][0]["TargetGroupArn"] = new_listener[
            "DefaultActions"
        ][0]["TargetGroupArn"]
        modified_listener["DefaultActions"][0]["Type"] = "forward"

    if modified_listener:
        return modified_listener
    else:
        return None


# Traceback (KeyError)
TASK [create alb] *********************************************************************************************************************************************************************
task path: /home/jevers/misc_dev/ansible_alb_test/alb.yml:63
Using module file /home/jevers/.local/lib/python3.6/site-packages/ansible/modules/cloud/amazon/elb_application_lb.py
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: jevers
<localhost> EXEC /bin/sh -c 'python3 &amp;&amp; sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/tmp/ansible_7qen__0n/ansible_module_elb_application_lb.py", line 1028, in <module>
main()
File "/tmp/ansible_7qen__0n/ansible_module_elb_application_lb.py", line 1023, in main
create_or_update_elb(connection, connection_ec2, module)
File "/tmp/ansible_7qen__0n/ansible_module_elb_application_lb.py", line 915, in create_or_update_elb
listener_changed = create_or_update_elb_listeners(connection, module, elb)
File "/tmp/ansible_7qen__0n/ansible_module_elb_application_lb.py", line 762, in create_or_update_elb_listeners
rules_to_add, rules_to_modify, rules_to_delete = compare_rules(connection, module, current_listeners, listener)
File "/tmp/ansible_7qen__0n/ansible_module_elb_application_lb.py", line 693, in compare_rules
modified_rule = compare_rule(current_rule, new_rule)
File "/tmp/ansible_7qen__0n/ansible_module_elb_application_lb.py", line 600, in compare_rule
if current_rule['Actions'][0]['TargetGroupArn'] != new_rule['Actions'][0]['TargetGroupArn']:
KeyError: 'TargetGroupArn'

fatal: [localhost]: FAILED! => {
"changed": false,
"module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_7qen__0n/ansible_module_elb_application_lb.py\", line 1028, in <module>\n    main()\n  File \"/tmp/ansible_7qen__0n/ansible_module_elb_application_lb.py\", line 1023, in main\n    create_or_update_elb(connection, connection_ec2, module)\n  File \"/tmp/ansible_7qen__0n/ansible_module_elb_application_lb.py\", line 915, in create_or_update_elb\n    listener_changed = create_or_update_elb_listeners(connection, module, elb)\n  File \"/tmp/ansible_7qen__0n/ansible_module_elb_application_lb.py\", line 762, in create_or_update_elb_listeners\n    rules_to_add, rules_to_modify, rules_to_delete = compare_rules(connection, module, current_listeners, listener)\n  File \"/tmp/ansible_7qen__0n/ansible_module_elb_application_lb.py\", line 693, in compare_rules\n    modified_rule = compare_rule(current_rule, new_rule)\n  File \"/tmp/ansible_7qen__0n/ansible_module_elb_application_lb.py\", line 600, in compare_rule\n    if current_rule['Actions'][0]['TargetGroupArn'] != new_rule['Actions'][0]['TargetGroupArn']:\nKeyError: 'TargetGroupArn'\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 1
}

# Fixed code
def _compare_listener(self, current_listener, new_listener):
    """
    Compare two listeners.

    :param current_listener:
    :param new_listener:
    :return:
    """

    modified_listener = {}

    # Port
    if current_listener["Port"] != new_listener["Port"]:
        modified_listener["Port"] = new_listener["Port"]

    # Protocol
    if current_listener["Protocol"] != new_listener["Protocol"]:
        modified_listener["Protocol"] = new_listener["Protocol"]

    # If Protocol is HTTPS, check additional attributes
    if current_listener["Protocol"] == "HTTPS" and new_listener["Protocol"] == "HTTPS":
        # Cert
        if current_listener["SslPolicy"] != new_listener["SslPolicy"]:
            modified_listener["SslPolicy"] = new_listener["SslPolicy"]
        if (
            current_listener["Certificates"][0]["CertificateArn"]
            != new_listener["Certificates"][0]["CertificateArn"]
        ):
            modified_listener["Certificates"] = []
            modified_listener["Certificates"].append({})
            modified_listener["Certificates"][0]["CertificateArn"] = new_listener[
                "Certificates"
            ][0]["CertificateArn"]
    elif (
        current_listener["Protocol"] != "HTTPS" and new_listener["Protocol"] == "HTTPS"
    ):
        modified_listener["SslPolicy"] = new_listener["SslPolicy"]
        modified_listener["Certificates"] = []
        modified_listener["Certificates"].append({})
        modified_listener["Certificates"][0]["CertificateArn"] = new_listener[
            "Certificates"
        ][0]["CertificateArn"]

    # Default action

    # Check proper rule format on current listener
    if len(current_listener["DefaultActions"]) > 1:
        for action in current_listener["DefaultActions"]:
            if "Order" not in action:
                self.module.fail_json(
                    msg="'Order' key not found in actions. "
                    "installed version of botocore does not support "
                    "multiple actions, please upgrade botocore to version "
                    "1.10.30 or higher"
                )

    # If the lengths of the actions are the same, we'll have to verify that the
    # contents of those actions are the same
    if len(current_listener["DefaultActions"]) == len(new_listener["DefaultActions"]):
        # if actions have just one element, compare the contents and then update if
        # they're different
        if (
            len(current_listener["DefaultActions"]) == 1
            and len(new_listener["DefaultActions"]) == 1
        ):
            if current_listener["DefaultActions"] != new_listener["DefaultActions"]:
                modified_listener["DefaultActions"] = new_listener["DefaultActions"]
        # if actions have multiple elements, we'll have to order them first before comparing.
        # multiple actions will have an 'Order' key for this purpose
        else:
            current_actions_sorted = sorted(
                current_listener["DefaultActions"], key=lambda x: x["Order"]
            )
            new_actions_sorted = sorted(
                new_listener["DefaultActions"], key=lambda x: x["Order"]
            )

            # the AWS api won't return the client secret, so we'll have to remove it
            # or the module will always see the new and current actions as different
            # and try to apply the same config
            new_actions_sorted_no_secret = []
            for action in new_actions_sorted:
                # the secret is currently only defined in the oidc config
                if action["Type"] == "authenticate-oidc":
                    action["AuthenticateOidcConfig"].pop("ClientSecret")
                    new_actions_sorted_no_secret.append(action)
                else:
                    new_actions_sorted_no_secret.append(action)

            if current_actions_sorted != new_actions_sorted_no_secret:
                modified_listener["DefaultActions"] = new_listener["DefaultActions"]
    # If the action lengths are different, then replace with the new actions
    else:
        modified_listener["DefaultActions"] = new_listener["DefaultActions"]

    if modified_listener:
        return modified_listener
    else:
        return None