I want to list all the CNAME records in a certain hosted zone. Let's say I have over 400 records in my hosted zone. I'm using boto3
:
response_per_zone = client.list_resource_record_sets(HostedZoneId=Id, MaxItems='100')
This command list 100 records of all types. There is a lot of CNAME records missing.
How do I iterate through all the records so that I can list all the CNAME records?
You should just use the official paginator method provided by AWS: https://boto3.readthedocs.io/en/latest/reference/services/route53.html#Route53.Paginator.ListResourceRecordSets
Example code for listing CNAME records regardless of the number of records:
#!/usr/bin/env python3
paginator = client.get_paginator('list_resource_record_sets')
try:
source_zone_records = paginator.paginate(HostedZoneId='HostedZoneId')
for record_set in source_zone_records:
for record in record_set['ResourceRecordSets']:
if record['Type'] == 'CNAME':
print(record['Name'])
except Exception as error:
print('An error occurred getting source zone records:')
print(str(error))
raise
Okay I found the answer to this after clearly reading the documentation. Each 100 records will have a trailing NextRecordType and NextRecordName field if the maxitems returned will be more than 100. We need to use these to get the next 100 items and so on. This code is working for me, let me know if my approach is wrong.
NextRecordName = 'a'
NextRecordType = 'CNAME'
while(NextRecordName is not None and NextRecordType is not None):
response_per_zone = client.list_resource_record_sets(HostedZoneId=Id,StartRecordName=NextRecordName, StartRecordType=NextRecordType ,MaxItems='400')
try:
NextRecordName = response_per_zone['NextRecordName']
NextRecordType = response_per_zone['NextRecordType']
except Exception as e:
NextRecordName = None
NextRecordType = None
print NextRecordType
print NextRecordName
#Since I need to find CNAME records, this is a function to check whether the record is CNAME, checking it is done using response_record = client.list_resource_record_sets(HostedZoneId=hostedzone, StartRecordName=cname_record, MaxItems='1')
private_zone = resp['Config']['PrivateZone']
if private_zone == False:
find_record(response_per_zone, Id, record_stack)
As per the AWS documentation: A flag will be set in the response to indicate if the result has been truncated (IsTruncated
will be set to True) - you can then look at the result of NextRecordName
in the response as the argument to StartRecordName
Let me know if you need me to code up an example and I'd be happy to :)
Most listing methods will return NextToken if there are more records. list_resource_record_sets uses NextRecordName instead and you can use it the same way like NexToken. Here's sample code that will iterate all records,
import boto3
aws_profile = '...'
zone_id = 'Z2A...'
max_records = 1000
session = boto3.Session(profile_name=aws_profile)
route53 = session.client('route53')
dns_records = []
dns_in_iteration = route53.list_resource_record_sets(HostedZoneId=zone_id)
dns_records.extend(dns_in_iteration['ResourceRecordSets'])
while len(dns_records) < max_records and 'NextRecordName' in dns_in_iteration.keys():
next_record_name = dns_in_iteration['NextRecordName']
print('listing next set: ' + next_record_name)
dns_in_iteration = route53.list_resource_record_sets(HostedZoneId=zone_id, StartRecordName=next_record_name)
dns_records.extend(dns_in_iteration['ResourceRecordSets'])
print('records found: ' + str(len(dns_records)))
for record in dns_records:
if record['Type'] == 'CNAME':
print(record['Name'])
I added max_records to test my 20k+ records, so it can stop with smaller set or records.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With