Repository: ansible/ansible-modules-core

Issue:
ec2_elb_lb throws errors
##### ISSUE TYPE
- Bug Report
##### COMPONENT NAME

ec2_elb_lb
##### ANSIBLE VERSION

devel
##### CONFIGURATION

NA
##### OS / ENVIRONMENT

CentOS
##### SUMMARY

It seems that the commit 73586f7ddba7ff33fe25805537af73877ca534b3 has broken the elb_lb module for me.  Mentioning @nbrownus as the author of that commit.

It seems to be because i'm just trying to create an ELB with no instances and the module falls over in multiple places because of NoneType errors.

`fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "module_stderr": "", "module_stdout": "Traceback (most recent call last):\r\n  File \"/home/ansible/.ansible/tmp/ansible-tmp-1462349132.85-79515211462816/ec2_elb_lb\", line 3691, in <module>\r\n    main()\r\n  File \"/home/ansible/.ansible/tmp/ansible-tmp-1462349132.85-79515211462816/ec2_elb_lb\", line 1318, in main\r\n    elb_man.ensure_ok()\r\n  File \"/home/ansible/.ansible/tmp/ansible-tmp-1462349132.85-79515211462816/ec2_elb_lb\", line 411, in _do_op\r\n    return op(*args, **kwargs)\r\n  File \"/home/ansible/.ansible/tmp/ansible-tmp-1462349132.85-79515211462816/ec2_elb_lb\", line 499, in ensure_ok\r\n    self._set_instance_ids()\r\n  File \"/home/ansible/.ansible/tmp/ansible-tmp-1462349132.85-79515211462816/ec2_elb_lb\", line 1150, in _set_instance_ids\r\n    has_instances = [has_instance.id for has_instance in self.elb.instances]\r\nTypeError: 'NoneType' object is not iterable\r\n", "msg": "MODULE FAILURE", "parsed": false}`
##### STEPS TO REPRODUCE

My ELB task looks like this:

```
- name: ELB
  ec2_elb_lb:
    region: "{{ aws_region }}"
    name: myelb
    access_logs:
      s3_location: logs
      s3_prefix: "aws/elb/{{ env }}/{{ type }}"
    health_check:
      ping_protocol: tcp
      ping_port: 80
      response_timeout: 5
      interval: 10
      unhealthy_threshold: 3
      healthy_threshold: 3
    cross_az_load_balancing: yes
    connection_draining_timeout: 60
    listeners:
      - protocol: http
        load_balancer_port: 80
        instance_port: 80
      - protocol: https
        load_balancer_port: 443
        instance_port: 443
        ssl_certificate_id: "arn:aws:iam::{{ aws_account_id }}:server-certificate/{{ env }}.for.com.au"
    security_group_ids: "{{ sec_group.group_id }}"
    subnets: "{{ vpc_subnet_public_fact.subnets|idfromlistofdicts|list }}"
    tags:
      Env: "{{ env }}"
      Type: "{{ type }}"
    state: present

```
##### EXPECTED RESULTS

My ELB to be created
##### ACTUAL RESULTS

I tried various steps to skip the None iteration but it just runs in to another.  

fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "module_stderr": "", "module_stdout": "Traceback (most recent call last):\r\n  File \"/home/ansible/.ansible/tmp/ansible-tmp-1462349132.85-79515211462816/ec2_elb_lb\", line 3691, in <module>\r\n    main()\r\n  File \"/home/ansible/.ansible/tmp/ansible-tmp-1462349132.85-79515211462816/ec2_elb_lb\", line 1318, in main\r\n    elb_man.ensure_ok()\r\n  File \"/home/ansible/.ansible/tmp/ansible-tmp-1462349132.85-79515211462816/ec2_elb_lb\", line 411, in _do_op\r\n    return op(_args, *_kwargs)\r\n  File \"/home/ansible/.ansible/tmp/ansible-tmp-1462349132.85-79515211462816/ec2_elb_lb\", line 499, in ensure_ok\r\n    self._set_instance_ids()\r\n  File \"/home/ansible/.ansible/tmp/ansible-tmp-1462349132.85-79515211462816/ec2_elb_lb\", line 1150, in _set_instance_ids\r\n    has_instances = [has_instance.id for has_instance in self.elb.instances]\r\nTypeError: 'NoneType' object is not iterable\r\n", "msg": "MODULE FAILURE", "parsed": false}



Discussion:

Resolving patch:
diff --git a/cloud/amazon/ec2_elb_lb.py b/cloud/amazon/ec2_elb_lb.py
--- a/cloud/amazon/ec2_elb_lb.py
+++ b/cloud/amazon/ec2_elb_lb.py
@@ -1078,10 +1078,14 @@ def select_stickiness_policy(self):
 
     def _get_backend_policies(self):
         """Get a list of backend policies"""
-        return [
-            str(backend.instance_port) + ':' + policy.policy_name for backend in self.elb.backends
-            for policy in backend.policies
-        ]
+        policies = []
+        if self.elb.backends is not None:
+            for backend in self.elb.backends:
+                if backend.policies is not None:
+                    for policy in backend.policies:
+                        policies.append(str(backend.instance_port) + ':' + policy.policy_name)
+
+        return policies
 
     def _set_backend_policies(self):
         """Sets policies for all backends"""
@@ -1114,9 +1118,10 @@ def _set_backend_policies(self):
 
     def _get_proxy_protocol_policy(self):
         """Find out if the elb has a proxy protocol enabled"""
-        for policy in self.elb.policies.other_policies:
-            if policy.policy_name == 'ProxyProtocol-policy':
-                return policy.policy_name
+        if self.elb.policies is not None and self.elb.policies.other_policies is not None:
+            for policy in self.elb.policies.other_policies:
+                if policy.policy_name == 'ProxyProtocol-policy':
+                    return policy.policy_name
 
         return None
 
@@ -1137,11 +1142,20 @@ def _diff_list(self, a, b):
         b = set(b)
         return [aa for aa in a if aa not in b]
 
+    def _get_instance_ids(self):
+        """Get the current list of instance ids installed in the elb"""
+        instances = []
+        if self.elb.instances is not None:
+            for instance in self.elb.instances:
+                instances.append(instance.id)
+
+        return instances
+
     def _set_instance_ids(self):
         """Register or deregister instances from an lb instance"""
         assert_instances = self.instance_ids or []
 
-        has_instances = [has_instance.id for has_instance in self.elb.instances]
+        has_instances = self._get_instance_ids()
 
         add_instances = self._diff_list(assert_instances, has_instances)
         if add_instances:


Test patch: