Repository: boto/boto

Issue:
Add support for next_token to get_all_reservations
Also modify get_only_instances use it to fetch all results.



Discussion:

Resolving patch:
diff --git a/boto/__init__.py b/boto/__init__.py
--- a/boto/__init__.py
+++ b/boto/__init__.py
@@ -37,7 +37,7 @@
 import urlparse
 from boto.exception import InvalidUriError
 
-__version__ = '2.31.0'
+__version__ = '2.31.1'
 Version = __version__  # for backware compatibility
 
 # http://bugs.python.org/issue7980
diff --git a/boto/ec2/connection.py b/boto/ec2/connection.py
--- a/boto/ec2/connection.py
+++ b/boto/ec2/connection.py
@@ -610,15 +610,24 @@ def get_only_instances(self, instance_ids=None, filters=None,
         :rtype: list
         :return: A list of  :class:`boto.ec2.instance.Instance`
         """
-        reservations = self.get_all_reservations(instance_ids=instance_ids,
-                                                 filters=filters,
-                                                 dry_run=dry_run,
-                                                 max_results=max_results)
-        return [instance for reservation in reservations
-                for instance in reservation.instances]
+        next_token = None
+        retval = []
+        while True:
+            reservations = self.get_all_reservations(instance_ids=instance_ids,
+                                                     filters=filters,
+                                                     dry_run=dry_run,
+                                                     max_results=max_results,
+                                                     next_token=next_token)
+            retval.extend([instance for reservation in reservations for
+                           instance in reservation.instances])
+            next_token = reservations.next_token
+            if not next_token:
+                break
+
+        return retval
 
     def get_all_reservations(self, instance_ids=None, filters=None,
-                             dry_run=False, max_results=None):
+                             dry_run=False, max_results=None, next_token=None):
         """
         Retrieve all the instance reservations associated with your account.
 
@@ -640,6 +649,10 @@ def get_all_reservations(self, instance_ids=None, filters=None,
         :param max_results: The maximum number of paginated instance
             items per response.
 
+        :type next_token: str
+        :param next_token: A string specifying the next paginated set
+            of results to return.
+
         :rtype: list
         :return: A list of  :class:`boto.ec2.instance.Reservation`
         """
@@ -660,6 +673,8 @@ def get_all_reservations(self, instance_ids=None, filters=None,
             params['DryRun'] = 'true'
         if max_results is not None:
             params['MaxResults'] = max_results
+        if next_token:
+            params['NextToken'] = next_token
         return self.get_list('DescribeInstances', params,
                              [('item', Reservation)], verb='POST')
 


Test patch:
diff --git a/tests/unit/ec2/test_connection.py b/tests/unit/ec2/test_connection.py
--- a/tests/unit/ec2/test_connection.py
+++ b/tests/unit/ec2/test_connection.py
@@ -1347,6 +1347,18 @@ def test_default_behavior(self):
              ignore_params_values=['AWSAccessKeyId', 'SignatureMethod',
                                    'SignatureVersion', 'Timestamp', 'Version'])
 
+        self.ec2.get_all_reservations()
+        self.assert_request_parameters({
+            'Action': 'DescribeInstances'},
+             ignore_params_values=['AWSAccessKeyId', 'SignatureMethod',
+                                   'SignatureVersion', 'Timestamp', 'Version'])
+
+        self.ec2.get_only_instances()
+        self.assert_request_parameters({
+            'Action': 'DescribeInstances'},
+             ignore_params_values=['AWSAccessKeyId', 'SignatureMethod',
+                                   'SignatureVersion', 'Timestamp', 'Version'])
+
     def test_max_results(self):
         self.set_http_response(status_code=200)
         self.ec2.get_all_instances(
@@ -1358,6 +1370,16 @@ def test_max_results(self):
              ignore_params_values=['AWSAccessKeyId', 'SignatureMethod',
                                    'SignatureVersion', 'Timestamp', 'Version'])
 
+    def test_next_token(self):
+        self.set_http_response(status_code=200)
+        self.ec2.get_all_reservations(
+            next_token='abcdefgh',
+        )
+        self.assert_request_parameters({
+            'Action': 'DescribeInstances',
+            'NextToken': 'abcdefgh'},
+             ignore_params_values=['AWSAccessKeyId', 'SignatureMethod',
+                                   'SignatureVersion', 'Timestamp', 'Version'])
 
 class TestDescribeTags(TestEC2ConnectionBase):