diff options
author | Daniel G. Taylor <dan@programmer-art.org> | 2014-09-02 10:26:59 -0700 |
---|---|---|
committer | Daniel G. Taylor <dan@programmer-art.org> | 2014-09-02 10:26:59 -0700 |
commit | 3ba380f0e2098d7d475225e3b75deb3cb4b59384 (patch) | |
tree | 94c7cb69e431f938d8fcc3fecf19b816b63aed89 | |
parent | ac2b311c04cb49b337ba033b1a550039c12c929d (diff) | |
parent | 0e762624c4e6de6e6b763f0e90ffc5f77151f041 (diff) | |
download | boto-3ba380f0e2098d7d475225e3b75deb3cb4b59384.tar.gz |
Merge pull request #2542 from cloudregistry/r53_list_rrsets_paging_fix
Truncated Response Handling in Route53 ListResourceRecordSets. Fixes #2542.
-rw-r--r-- | boto/route53/connection.py | 2 | ||||
-rw-r--r-- | boto/route53/record.py | 11 | ||||
-rw-r--r-- | tests/unit/route53/test_connection.py | 100 |
3 files changed, 108 insertions, 5 deletions
diff --git a/boto/route53/connection.py b/boto/route53/connection.py index 2cab2359..7ca6df86 100644 --- a/boto/route53/connection.py +++ b/boto/route53/connection.py @@ -383,7 +383,7 @@ class Route53Connection(AWSAuthConnection): """ params = {'type': type, 'name': name, - 'Identifier': identifier, 'maxitems': maxitems} + 'identifier': identifier, 'maxitems': maxitems} uri = '/%s/hostedzone/%s/rrset' % (self.Version, hosted_zone_id) response = self.make_request('GET', uri, params=params) body = response.read() diff --git a/boto/route53/record.py b/boto/route53/record.py index 664739b8..b8c69d44 100644 --- a/boto/route53/record.py +++ b/boto/route53/record.py @@ -54,6 +54,7 @@ class ResourceRecordSets(ResultSet): self.changes = [] self.next_record_name = None self.next_record_type = None + self.next_record_identifier = None super(ResourceRecordSets, self).__init__([('ResourceRecordSet', Record)]) def __repr__(self): @@ -165,12 +166,14 @@ class ResourceRecordSets(ResultSet): return self.connection.change_rrsets(self.hosted_zone_id, self.to_xml()) def endElement(self, name, value, connection): - """Overwritten to also add the NextRecordName and - NextRecordType to the base object""" + """Overwritten to also add the NextRecordName, + NextRecordType and NextRecordIdentifier to the base object""" if name == 'NextRecordName': self.next_record_name = value elif name == 'NextRecordType': self.next_record_type = value + elif name == 'NextRecordIdentifier': + self.next_record_identifier = value else: return super(ResourceRecordSets, self).endElement(name, value, connection) @@ -183,7 +186,9 @@ class ResourceRecordSets(ResultSet): yield obj if self.is_truncated: self.is_truncated = False - results = self.connection.get_all_rrsets(self.hosted_zone_id, name=self.next_record_name, type=self.next_record_type) + results = self.connection.get_all_rrsets(self.hosted_zone_id, name=self.next_record_name, + type=self.next_record_type, + identifier=self.next_record_identifier) else: results = None self.is_truncated = truncated diff --git a/tests/unit/route53/test_connection.py b/tests/unit/route53/test_connection.py index 16df3747..f1d5d8e6 100644 --- a/tests/unit/route53/test_connection.py +++ b/tests/unit/route53/test_connection.py @@ -23,7 +23,6 @@ from tests.compat import mock, unittest import re import xml.dom.minidom - from boto.exception import BotoServerError from boto.route53.connection import Route53Connection from boto.route53.exception import DNSServerError @@ -33,6 +32,8 @@ from boto.route53.zone import Zone from nose.plugins.attrib import attr from tests.unit import AWSMockServiceTestCase +from boto.compat import six +urllib = six.moves.urllib @attr(route53=True) class TestRoute53Connection(AWSMockServiceTestCase): @@ -372,6 +373,103 @@ class TestGetAllRRSetsRoute53(AWSMockServiceTestCase): self.assertEqual(healthcheck_record.alias_dns_name, 'example-123456-evaluate-health-healthcheck.us-west-2.elb.amazonaws.com.') @attr(route53=True) +class TestTruncatedGetAllRRSetsRoute53(AWSMockServiceTestCase): + connection_class = Route53Connection + + def setUp(self): + super(TestTruncatedGetAllRRSetsRoute53, self).setUp() + + def default_body(self): + return b""" +<ListResourceRecordSetsResponse xmlns="https://route53.amazonaws.com/doc/2013-04-01/"> + <ResourceRecordSets> + <ResourceRecordSet> + <Name>example.com.</Name> + <Type>NS</Type> + <TTL>900</TTL> + <ResourceRecords> + <ResourceRecord> + <Value>ns-91.awsdns-41.co.uk.</Value> + </ResourceRecord> + <ResourceRecord> + <Value>ns-1929.awsdns-93.net.</Value> + </ResourceRecord> + <ResourceRecord> + <Value>ns-12.awsdns-21.org.</Value> + </ResourceRecord> + <ResourceRecord> + <Value>ns-102.awsdns-96.com.</Value> + </ResourceRecord> + </ResourceRecords> + </ResourceRecordSet> + <ResourceRecordSet> + <Name>example.com.</Name> + <Type>SOA</Type> + <TTL>1800</TTL> + <ResourceRecords> + <ResourceRecord> + <Value>ns-1929.awsdns-93.net. hostmaster.awsdns.net. 1 10800 3600 604800 1800</Value> + </ResourceRecord> + </ResourceRecords> + </ResourceRecordSet> + <ResourceRecordSet> + <Name>wrr.example.com.</Name> + <Type>A</Type> + <SetIdentifier>primary</SetIdentifier> + <Weight>100</Weight> + <TTL>300</TTL> + <ResourceRecords> + <ResourceRecord><Value>127.0.0.1</Value></ResourceRecord> + </ResourceRecords> + </ResourceRecordSet> + </ResourceRecordSets> + <IsTruncated>true</IsTruncated> + <NextRecordName>wrr.example.com.</NextRecordName> + <NextRecordType>A</NextRecordType> + <NextRecordIdentifier>secondary</NextRecordIdentifier> + <MaxItems>3</MaxItems> +</ListResourceRecordSetsResponse>""" + + def paged_body(self): + return b""" +<ListResourceRecordSetsResponse xmlns="https://route53.amazonaws.com/doc/2013-04-01/"> + <ResourceRecordSets> + <ResourceRecordSet> + <Name>wrr.example.com.</Name> + <Type>A</Type> + <SetIdentifier>secondary</SetIdentifier> + <Weight>50</Weight> + <TTL>300</TTL> + <ResourceRecords> + <ResourceRecord><Value>127.0.0.2</Value></ResourceRecord> + </ResourceRecords> + </ResourceRecordSet> + </ResourceRecordSets> + <IsTruncated>false</IsTruncated> + <MaxItems>3</MaxItems> +</ListResourceRecordSetsResponse>""" + + + def test_get_all_rr_sets(self): + self.set_http_response(status_code=200) + response = self.service_connection.get_all_rrsets("Z1111", maxitems=3) + + # made first request + self.assertEqual(self.actual_request.path, '/2013-04-01/hostedzone/Z1111/rrset?maxitems=3') + + # anticipate a second request when we page it + self.set_http_response(status_code=200, body=self.paged_body()) + + # this should trigger another call to get_all_rrsets + self.assertEqual(len(list(response)), 4) + + url_parts = urllib.parse.urlparse(self.actual_request.path) + self.assertEqual(url_parts.path, '/2013-04-01/hostedzone/Z1111/rrset') + self.assertEqual(urllib.parse.parse_qs(url_parts.query), + dict(type=['A'], name=['wrr.example.com.'], identifier=['secondary'])) + + +@attr(route53=True) class TestCreateHealthCheckRoute53IpAddress(AWSMockServiceTestCase): connection_class = Route53Connection |