Updated Branches:
  refs/heads/trunk 7fc910a88 -> 8d529766d

Handle Rackspace pagination of DNS records.

Rackspace paginates DNS records returned from their API. In iterate_records and
iterate_zones, query Rackspace multiple times, if needed, to get the full
result.

Signed-off-by: Tomaz Muraus <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/caa689d2
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/caa689d2
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/caa689d2

Branch: refs/heads/trunk
Commit: caa689d2744af09f8ba389af1d8fd4545747e2db
Parents: 7fc910a
Author: Roy Wellington Ⅳ <[email protected]>
Authored: Tue Dec 10 15:57:02 2013 -0800
Committer: Tomaz Muraus <[email protected]>
Committed: Fri Jan 24 22:39:45 2014 +0100

----------------------------------------------------------------------
 libcloud/dns/drivers/rackspace.py | 80 ++++++++++++++++++++++------------
 1 file changed, 53 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/caa689d2/libcloud/dns/drivers/rackspace.py
----------------------------------------------------------------------
diff --git a/libcloud/dns/drivers/rackspace.py 
b/libcloud/dns/drivers/rackspace.py
index 3410742..84b9ab8 100644
--- a/libcloud/dns/drivers/rackspace.py
+++ b/libcloud/dns/drivers/rackspace.py
@@ -150,18 +150,47 @@ class RackspaceDNSDriver(DNSDriver, OpenStackDriverMixin):
         RecordType.PTR: 'PTR',
     }
 
-    def list_zones(self):
-        response = self.connection.request(action='/domains')
-        zones = self._to_zones(data=response.object['domains'])
-        return zones
-
-    def list_records(self, zone):
+    def iterate_zones(self):
+        offset = 0
+        limit = 100
+        while True:
+            params = {
+                'limit': limit,
+                'offset': offset,
+            }
+            response = self.connection.request(
+                action='/domains', params=params).object
+            zones_list = response['domains']
+            for item in zones_list:
+                yield self._to_zone(item)
+
+            if _rackspace_result_has_more(response, len(zones_list), limit):
+                offset += limit
+            else:
+                break
+
+    def iterate_records(self, zone):
         self.connection.set_context({'resource': 'zone', 'id': zone.id})
-        response = self.connection.request(action='/domains/%s' % (zone.id),
-                                           params={'showRecord': True}).object
-        records = self._to_records(data=response['recordsList']['records'],
-                                   zone=zone)
-        return records
+        offset = 0
+        limit = 100
+        while True:
+            params = {
+                'showRecord': True,
+                'limit': limit,
+                'offset': offset,
+            }
+            response = self.connection.request(
+                action='/domains/%s' % (zone.id), params=params).object
+            records_list = response['recordsList']
+            records = records_list['records']
+            for item in records:
+                record = self._to_record(data=item, zone=zone)
+                yield record
+
+            if _rackspace_result_has_more(records_list, len(records), limit):
+                offset += limit
+            else:
+                break
 
     def get_zone(self, zone_id):
         self.connection.set_context({'resource': 'zone', 'id': zone_id})
@@ -305,14 +334,6 @@ class RackspaceDNSDriver(DNSDriver, OpenStackDriverMixin):
                                       method='DELETE')
         return True
 
-    def _to_zones(self, data):
-        zones = []
-        for item in data:
-            zone = self._to_zone(data=item)
-            zones.append(zone)
-
-        return zones
-
     def _to_zone(self, data):
         id = data['id']
         domain = data['name']
@@ -330,14 +351,6 @@ class RackspaceDNSDriver(DNSDriver, OpenStackDriverMixin):
                     driver=self, extra=extra)
         return zone
 
-    def _to_records(self, data, zone):
-        records = []
-        for item in data:
-            record = self._to_record(data=item, zone=zone)
-            records.append(record)
-
-        return records
-
     def _to_record(self, data, zone):
         id = data['id']
         fqdn = data['name']
@@ -396,6 +409,19 @@ class RackspaceDNSDriver(DNSDriver, OpenStackDriverMixin):
         return kwargs
 
 
+def _rackspace_result_has_more(obj, result_length, limit):
+    # If rackspace returns less than the limit, then we've reached the end of
+    # the result set.
+    if result_length < limit:
+        return False
+    # Paginated results return links to the previous and next sets of data, but
+    # 'next' only exists when there is more to get.
+    for item in obj.get('links', ()):
+        if item['rel'] == 'next':
+            return True
+    return False
+
+
 class RackspaceUSDNSDriver(RackspaceDNSDriver):
     name = 'Rackspace DNS (US)'
     type = Provider.RACKSPACE_US

Reply via email to