# Buggy code
def get_properties(autoscaling_group):
    properties = dict(
        (attr, getattr(autoscaling_group, attr)) for attr in ASG_ATTRIBUTES
    )

    # Ugly hack to make this JSON-serializable.  We take a list of boto Tag
    # objects and replace them with a dict-representation.  Needed because the
    # tags are included in ansible's return value (which is jsonified)
    if "tags" in properties and isinstance(properties["tags"], list):
        serializable_tags = {}
        for tag in properties["tags"]:
            serializable_tags[tag.key] = [tag.value, tag.propagate_at_launch]
        properties["tags"] = serializable_tags

    properties["healthy_instances"] = 0
    properties["in_service_instances"] = 0
    properties["unhealthy_instances"] = 0
    properties["pending_instances"] = 0
    properties["viable_instances"] = 0
    properties["terminating_instances"] = 0

    instance_facts = {}

    if autoscaling_group.instances:
        properties["instances"] = [i.instance_id for i in autoscaling_group.instances]
        for i in autoscaling_group.instances:
            instance_facts[i.instance_id] = {
                "health_status": i.health_status,
                "lifecycle_state": i.lifecycle_state,
                "launch_config_name": i.launch_config_name,
            }
            if i.health_status == "Healthy" and i.lifecycle_state == "InService":
                properties["viable_instances"] += 1
            if i.health_status == "Healthy":
                properties["healthy_instances"] += 1
            else:
                properties["unhealthy_instances"] += 1
            if i.lifecycle_state == "InService":
                properties["in_service_instances"] += 1
            if i.lifecycle_state == "Terminating":
                properties["terminating_instances"] += 1
            if i.lifecycle_state == "Pending":
                properties["pending_instances"] += 1
    properties["instance_facts"] = instance_facts
    properties["load_balancers"] = autoscaling_group.load_balancers

    if getattr(autoscaling_group, "tags", None):
        properties["tags"] = dict((t.key, t.value) for t in autoscaling_group.tags)

    return properties


# Traceback (KeyError)
TASK [ec2 : ec2_asg] ***************************************************************************************************************************************************************************************
task path: /../servers.yml
An exception occurred during task execution. The full traceback is:
Traceback (most recent call last):
File "/var/folders/y2/l4g6_6zn03s1mh34lkz1czjm0000gn/T/ansible_lJMEl4/ansible_module_ec2_asg.py", line 928, in <module>
main()
File "/var/folders/y2/l4g6_6zn03s1mh34lkz1czjm0000gn/T/ansible_lJMEl4/ansible_module_ec2_asg.py", line 922, in main
replace_changed, asg_properties=replace(connection, module)
File "/var/folders/y2/l4g6_6zn03s1mh34lkz1czjm0000gn/T/ansible_lJMEl4/ansible_module_ec2_asg.py", line 646, in replace
instances = props['instances']
KeyError: 'instances'

fatal: [localhost]: FAILED! => {
"changed": false,
"failed": true,
"invocation": {
"module_name": "ec2_asg"
},
"module_stderr": "Traceback (most recent call last):\n  File \"/var/folders/y2/l4g6_6zn03s1mh34lkz1czjm0000gn/T/ansible_lJMEl4/ansible_module_ec2_asg.py\", line 928, in <module>\n    main()\n  File \"/var/folders/y2/l4g6_6zn03s1mh34lkz1czjm0000gn/T/ansible_lJMEl4/ansible_module_ec2_asg.py\", line 922, in main\n    replace_changed, asg_properties=replace(connection, module)\n  File \"/var/folders/y2/l4g6_6zn03s1mh34lkz1czjm0000gn/T/ansible_lJMEl4/ansible_module_ec2_asg.py\", line 646, in replace\n    instances = props['instances']\nKeyError: 'instances'\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 1
}

# Fixed code
def get_properties(autoscaling_group):
    properties = dict(
        (attr, getattr(autoscaling_group, attr)) for attr in ASG_ATTRIBUTES
    )

    # Ugly hack to make this JSON-serializable.  We take a list of boto Tag
    # objects and replace them with a dict-representation.  Needed because the
    # tags are included in ansible's return value (which is jsonified)
    if "tags" in properties and isinstance(properties["tags"], list):
        serializable_tags = {}
        for tag in properties["tags"]:
            serializable_tags[tag.key] = [tag.value, tag.propagate_at_launch]
        properties["tags"] = serializable_tags

    properties["healthy_instances"] = 0
    properties["in_service_instances"] = 0
    properties["unhealthy_instances"] = 0
    properties["pending_instances"] = 0
    properties["viable_instances"] = 0
    properties["terminating_instances"] = 0

    instance_facts = {}

    if autoscaling_group.instances:
        properties["instances"] = [i.instance_id for i in autoscaling_group.instances]
        for i in autoscaling_group.instances:
            instance_facts[i.instance_id] = {
                "health_status": i.health_status,
                "lifecycle_state": i.lifecycle_state,
                "launch_config_name": i.launch_config_name,
            }
            if i.health_status == "Healthy" and i.lifecycle_state == "InService":
                properties["viable_instances"] += 1
            if i.health_status == "Healthy":
                properties["healthy_instances"] += 1
            else:
                properties["unhealthy_instances"] += 1
            if i.lifecycle_state == "InService":
                properties["in_service_instances"] += 1
            if i.lifecycle_state == "Terminating":
                properties["terminating_instances"] += 1
            if i.lifecycle_state == "Pending":
                properties["pending_instances"] += 1
    else:
        properties["instances"] = []
    properties["instance_facts"] = instance_facts
    properties["load_balancers"] = autoscaling_group.load_balancers

    if getattr(autoscaling_group, "tags", None):
        properties["tags"] = dict((t.key, t.value) for t in autoscaling_group.tags)

    return properties