Repository: ansible/ansible

Issue:
ec2_elb_facts fails to find elb's if >400 elb's exist
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
- ec2_elb_facts

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible --version
ansible 2.2.1.0
```

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->
- Mac OSX 10.11.6

##### SUMMARY
<!--- Explain the problem briefly -->
Internal boto of ec2_elb_facts.py seems to be truncating result list to 400 entries like boto3 does. Current implementation of facts retrieves all elb's and then loops through resulting list looking for specific elb names if `names` is provided. This will fail if the searched elb name is not within the first 400 returned elbs.

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->
- Have an aws account with >400 elbs
- Run ansible playbook containing ec2_elb_facts and specify an elb name not within first 400 elb's in aws console
- Debug `msg` the returned elb's from facts task, note elb's list is empty

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
- Expected list of returned elb's to contain information of named elb's

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
- Debug message of registered returned results will show an empty elb's list (cannot paste actual results due to security)

ec2_elb_facts fails to find elb's if >400 elb's exist
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
- ec2_elb_facts

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible --version
ansible 2.2.1.0
```

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->
- Mac OSX 10.11.6

##### SUMMARY
<!--- Explain the problem briefly -->
Internal boto of ec2_elb_facts.py seems to be truncating result list to 400 entries like boto3 does. Current implementation of facts retrieves all elb's and then loops through resulting list looking for specific elb names if `names` is provided. This will fail if the searched elb name is not within the first 400 returned elbs.

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->
- Have an aws account with >400 elbs
- Run ansible playbook containing ec2_elb_facts and specify an elb name not within first 400 elb's in aws console
- Debug `msg` the returned elb's from facts task, note elb's list is empty

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
- Expected list of returned elb's to contain information of named elb's

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
- Debug message of registered returned results will show an empty elb's list (cannot paste actual results due to security)



Discussion:
cc @mjschultz
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
cc @mjschultz
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/cloud/amazon/ec2_elb_facts.py b/lib/ansible/modules/cloud/amazon/ec2_elb_facts.py
--- a/lib/ansible/modules/cloud/amazon/ec2_elb_facts.py
+++ b/lib/ansible/modules/cloud/amazon/ec2_elb_facts.py
@@ -78,6 +78,8 @@
 
 '''
 
+import traceback
+
 try:
     import boto.ec2.elb
     from boto.ec2.tag import Tag
@@ -201,20 +203,28 @@ def _get_elb_info(self, elb):
 
 
     def list_elbs(self):
-        elb_array = []
-
-        try:
-            all_elbs = self.connection.get_all_load_balancers()
-        except BotoServerError as err:
-            self.module.fail_json(msg = "%s: %s" % (err.error_code, err.error_message))
+        elb_array, token = [], None
 
-        if all_elbs:
-            if self.names:
-                for existing_lb in all_elbs:
-                    if existing_lb.name in self.names:
-                        elb_array.append(existing_lb)
+        while True:
+            try:
+                all_elbs = self.connection.get_all_load_balancers(marker=token)
+                token = all_elbs.next_token
+            except BotoServerError as err:
+                self.module.fail_json(msg = "%s: %s" % (err.error_code, err.error_message),
+                    exception=traceback.format_exc())
+
+            if all_elbs:
+                if self.names:
+                    for existing_lb in all_elbs:
+                        if existing_lb.name in self.names:
+                            elb_array.append(existing_lb)
+                else:
+                    elb_array.extend(all_elbs)
             else:
-                elb_array = all_elbs
+                break
+
+            if token is None:
+                break
 
         return list(map(self._get_elb_info, elb_array))
 


Test patch: