Repository: ansible/ansible

Issue:
ec2_lc_facts lacking functionality, nearly unusable
<!---
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_lc_facts module

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.3.0.0 (detached HEAD d56ba0945d) last updated 2017/06/01 11:36:03 (GMT -500)
  config file = /Users/mconlon/git/hyperwave_relay_inf_as_code/ansible.cfg
  configured module search path = [u'custom_modules']
  python version = 2.7.12 (default, Oct 11 2016, 05:20:59) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.38)]
```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
ansible.cfg:
```
[defaults]
roles_path = roles
lookup_plugins = lookup_plugins
filter_plugins = filter_plugins
hash_behaviour = merge
library = custom_modules
forks = 50

[ssh_connection]
scp_if_ssh = True
pipelining = True
# an attempt to fix ssh unreachable errors when machines are actually reachable
retries = 5
```
##### 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.
-->
N/A
##### SUMMARY
<!--- Explain the problem briefly -->
I'm in a situation where I can't get a list of facts for launch configs that start with "test-". I'm not sure exactly how this module should solve the problem, so I'll just note the roadblocks I've noticed:

- the name option only accepts an exact match (regex match would be great if supported by boto)
- I can only retrieve a list of facts for 50 launch configs at a time (which apparently are determined by alphabetical order of the launch config name)
- sorting only happens on the set of 50 returned, rather than on the full set of launch configs in my account. This was a workaround attempt to start with, but it doesn't work.
- `sort_start: 50` returns no results. anything above 49 is invalid for this option (not documented)

I can't ever get the facts for launch configs outside of the first 50 alphabetical names that AWS/boto returns, unless I have the exact name for the launch config.


##### 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.
-->
1. Have more than 50 launch configs
2. Try to get the facts of any launch config alphabetically ranked as >50

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Facts should be returned for launch configs beyond the 50 first alphabetical listings

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
The same set is returned regardless of sorting options
No launch config beyond the 50th can have its facts returned



Discussion:
cc @willthames
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Bueller? Bueller?

Boto docs say that only 50-100 launch configs can get returned by a single API call http://boto3.readthedocs.io/en/latest/reference/services/autoscaling.html#AutoScaling.Client.describe_launch_configurations
and the module is definitely only using one call https://github.com/ansible/ansible/blob/1d0a629dcc87c49bf2b97a8922629f2e8952c911/lib/ansible/modules/cloud/amazon/ec2_lc_facts.py#L183

please use NextToken to add up all the results 🙏
needs_contributor
cc @psykotox
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/module_utils/ec2.py b/lib/ansible/module_utils/ec2.py
--- a/lib/ansible/module_utils/ec2.py
+++ b/lib/ansible/module_utils/ec2.py
@@ -317,7 +317,7 @@ def ec2_connect(module):
     return ec2
 
 
-def paging(pause=0, marker_property='marker'):
+def paging(pause=0, marker_property='marker', result_key=None):
     """ Adds paging to boto retrieval functions that support a 'marker'
         this is configurable as not all boto functions seem to use the
         same name.
@@ -328,8 +328,12 @@ def page(*args, **kwargs):
             marker = None
             while True:
                 try:
-                    new = f(*args, marker=marker, **kwargs)
-                    marker = getattr(new, marker_property)
+                    if marker:
+                        kwargs[marker_property] = marker
+                    new = f(*args, **kwargs)
+                    marker = new.get(marker_property)
+                    if result_key:
+                        new = new[result_key]
                     results.extend(new)
                     if not marker:
                         break
diff --git a/lib/ansible/modules/cloud/amazon/ec2_lc_facts.py b/lib/ansible/modules/cloud/amazon/ec2_lc_facts.py
--- a/lib/ansible/modules/cloud/amazon/ec2_lc_facts.py
+++ b/lib/ansible/modules/cloud/amazon/ec2_lc_facts.py
@@ -170,6 +170,8 @@
 except ImportError:
     HAS_BOTO3 = False
 
+from ansible.module_utils.ec2 import paging
+
 
 def list_launch_configs(connection, module):
 
@@ -180,7 +182,8 @@ def list_launch_configs(connection, module):
     sort_end = module.params.get('sort_end')
 
     try:
-        launch_configs = connection.describe_launch_configurations(LaunchConfigurationNames=launch_config_name)
+        launch_configs = {'LaunchConfigurations': paging(pause=0, marker_property='NextToken', result_key='LaunchConfigurations')
+                                                        (connection.describe_launch_configurations)(LaunchConfigurationNames=launch_config_name)}
     except ClientError as e:
         module.fail_json(msg=e.message)
 


Test patch: