# Buggy code
def get_target_from_rule(module, client, rule, name, group, groups, vpc_id):
    """
    Returns tuple of (group_id, ip) after validating rule params.

    rule: Dict describing a rule.
    name: Name of the security group being managed.
    groups: Dict of all available security groups.

    AWS accepts an ip range or a security group as target of a rule. This
    function validate the rule specification and return either a non-None
    group_id or a non-None ip range.
    """

    FOREIGN_SECURITY_GROUP_REGEX = "^(\S+)/(sg-\S+)/(\S+)"
    group_id = None
    group_name = None
    ip = None
    ipv6 = None
    target_group_created = False

    if "group_id" in rule and "cidr_ip" in rule:
        module.fail_json(msg="Specify group_id OR cidr_ip, not both")
    elif "group_name" in rule and "cidr_ip" in rule:
        module.fail_json(msg="Specify group_name OR cidr_ip, not both")
    elif "group_id" in rule and "cidr_ipv6" in rule:
        module.fail_json(msg="Specify group_id OR cidr_ipv6, not both")
    elif "group_name" in rule and "cidr_ipv6" in rule:
        module.fail_json(msg="Specify group_name OR cidr_ipv6, not both")
    elif "group_id" in rule and "group_name" in rule:
        module.fail_json(msg="Specify group_id OR group_name, not both")
    elif "cidr_ip" in rule and "cidr_ipv6" in rule:
        module.fail_json(msg="Specify cidr_ip OR cidr_ipv6, not both")
    elif rule.get("group_id") and re.match(
        FOREIGN_SECURITY_GROUP_REGEX, rule["group_id"]
    ):
        # this is a foreign Security Group. Since you can't fetch it you must create an instance of it
        owner_id, group_id, group_name = re.match(
            FOREIGN_SECURITY_GROUP_REGEX, rule["group_id"]
        ).groups()
        group_instance = dict(GroupId=group_id, GroupName=group_name)
        groups[group_id] = group_instance
        groups[group_name] = group_instance
    elif "group_id" in rule:
        group_id = rule["group_id"]
    elif "group_name" in rule:
        group_name = rule["group_name"]
        if group_name == name:
            group_id = group["GroupId"]
            groups[group_id] = group
            groups[group_name] = group
        elif group_name in groups and (
            vpc_id is None or groups[group_name]["VpcId"] == vpc_id
        ):
            group_id = groups[group_name]["GroupId"]
        else:
            if not rule.get("group_desc", "").strip():
                module.fail_json(
                    msg="group %s will be automatically created by rule %s and "
                    "no description was provided" % (group_name, rule)
                )
            if not module.check_mode:
                params = dict(GroupName=group_name, Description=rule["group_desc"])
                if vpc_id:
                    params["VpcId"] = vpc_id
                auto_group = client.create_security_group(**params)
                group_id = auto_group["GroupId"]
                groups[group_id] = auto_group
                groups[group_name] = auto_group
            target_group_created = True
    elif "cidr_ip" in rule:
        ip = rule["cidr_ip"]
    elif "cidr_ipv6" in rule:
        ipv6 = rule["cidr_ipv6"]

    return group_id, ip, ipv6, target_group_created


# Traceback (nboto.exception.EC2ResponseError)
"module_stderr": "Traceback (most recent call last):\n  File \"/var/folders/t8/vdrxm90s1ps41pghp7wxn8n80000gp/T/ansible_pJu0pZ/ansible_module_ec2_group.py\", line 479, in <module>\n    main()\n  File \"/var/folders/t8/vdrxm90s1ps41pghp7wxn8n80000gp/T/ansible_pJu0pZ/ansible_module_ec2_group.py\", line 374, in main\n    group.authorize(rule['proto'], rule['from_port'], rule['to_port'], thisip, grantGroup)\n  File \"/Library/Python/2.7/site-packages/boto-2.38.0-py2.7.egg/boto/ec2/securitygroup.py\", line 203, in authorize\n    dry_run=dry_run)\n  File \"/Library/Python/2.7/site-packages/boto-2.38.0-py2.7.egg/boto/ec2/connection.py\", line 3191, in authorize_security_group\n    params, verb='POST')\n  File \"/Library/Python/2.7/site-packages/boto-2.38.0-py2.7.egg/boto/connection.py\", line 1227, in get_status\n    raise self.ResponseError(response.status, response.reason, body)\nboto.exception.EC2ResponseError: EC2ResponseError: 400 Bad Request\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response><Errors><Error><Code>InvalidPermission.Duplicate</Code><Message>the specified rule \"peer: sg-xxxxxxxx, TCP, from port: 22, to port: 22, ALLOW\" already exists</Message></Error></Errors><RequestID>b9ec5eee-4a86-49d7-90b8-86bfbf2ba21b</RequestID></Response>\n",
"module_stdout": "",
"msg": "MODULE FAILURE"

# Fixed code
def get_target_from_rule(module, client, rule, name, group, groups, vpc_id):
    """
    Returns tuple of (group_id, ip) after validating rule params.

    rule: Dict describing a rule.
    name: Name of the security group being managed.
    groups: Dict of all available security groups.

    AWS accepts an ip range or a security group as target of a rule. This
    function validate the rule specification and return either a non-None
    group_id or a non-None ip range.
    """

    FOREIGN_SECURITY_GROUP_REGEX = "^(\S+)/(sg-\S+)/(\S+)"
    group_id = None
    group_name = None
    ip = None
    ipv6 = None
    target_group_created = False

    if "group_id" in rule and "cidr_ip" in rule:
        module.fail_json(msg="Specify group_id OR cidr_ip, not both")
    elif "group_name" in rule and "cidr_ip" in rule:
        module.fail_json(msg="Specify group_name OR cidr_ip, not both")
    elif "group_id" in rule and "cidr_ipv6" in rule:
        module.fail_json(msg="Specify group_id OR cidr_ipv6, not both")
    elif "group_name" in rule and "cidr_ipv6" in rule:
        module.fail_json(msg="Specify group_name OR cidr_ipv6, not both")
    elif "group_id" in rule and "group_name" in rule:
        module.fail_json(msg="Specify group_id OR group_name, not both")
    elif "cidr_ip" in rule and "cidr_ipv6" in rule:
        module.fail_json(msg="Specify cidr_ip OR cidr_ipv6, not both")
    elif rule.get("group_id") and re.match(
        FOREIGN_SECURITY_GROUP_REGEX, rule["group_id"]
    ):
        # this is a foreign Security Group. Since you can't fetch it you must create an instance of it
        owner_id, group_id, group_name = re.match(
            FOREIGN_SECURITY_GROUP_REGEX, rule["group_id"]
        ).groups()
        group_instance = dict(GroupId=group_id, GroupName=group_name)
        groups[group_id] = group_instance
        groups[group_name] = group_instance
    elif "group_id" in rule:
        group_id = rule["group_id"]
    elif "group_name" in rule:
        group_name = rule["group_name"]
        if group_name == name:
            group_id = group["GroupId"]
            groups[group_id] = group
            groups[group_name] = group
        elif group_name in groups:
            group_id = groups[group_name]["GroupId"]
        else:
            if not rule.get("group_desc", "").strip():
                module.fail_json(
                    msg="group %s will be automatically created by rule %s and "
                    "no description was provided" % (group_name, rule)
                )
            if not module.check_mode:
                params = dict(GroupName=group_name, Description=rule["group_desc"])
                if vpc_id:
                    params["VpcId"] = vpc_id
                auto_group = client.create_security_group(**params)
                group_id = auto_group["GroupId"]
                groups[group_id] = auto_group
                groups[group_name] = auto_group
            target_group_created = True
    elif "cidr_ip" in rule:
        ip = rule["cidr_ip"]
    elif "cidr_ipv6" in rule:
        ipv6 = rule["cidr_ipv6"]

    return group_id, ip, ipv6, target_group_created