Skip to content

Instantly share code, notes, and snippets.

@Duologic
Last active August 29, 2015 14:01
Show Gist options
  • Select an option

  • Save Duologic/8c12be99cb591ececfc5 to your computer and use it in GitHub Desktop.

Select an option

Save Duologic/8c12be99cb591ececfc5 to your computer and use it in GitHub Desktop.
r53updater.py
from boto import route53
class R53Updater(object):
"""
Example for A record:
r53 = R53Updater()
r53.connect()
records = r53.find_record('example.org')
new_ip_list = ['1.2.3.4', '4.3.2.1']
r53.update_record(records[0], new_ip_list)
"""
def connect(self):
"""
Setup connection to AWS Route53
"""
self.conn = route53.connect_to_region('eu-west-1')
def get_zone_ids(self, domainnames):
"""
Get zone ids of a list of domainnames
Returns a dict of lists
Might contain more zone ids per domain if not fully qualified domainname
"""
all_zones = self.conn.get_all_hosted_zones()
ret = {}
for domainname in domainnames:
ret[domainname] = []
for zone in all_zones.get('ListHostedZonesResponse').get('HostedZones'):
if zone['Name'].startswith(domainname):
ret[domainname].append(zone['Id'].split('/')[2])
return ret
def get_recordsets(self, zone_id=None, cached=None):
"""
Get the recordsets
Default, returns the whole list of RecordSets in this account
zone_id: returns a list with that single RecordSet
cached: if cached, returns a list of the cached RecordSets
"""
key_all_zones = "all_zones"
if zone_id is None:
zid = key_all_zones
else:
zid = zone_id
if not hasattr(self, 'rrsets'):
self.rrsets = {}
else:
if zid in self.rrsets.keys() and cached is None:
return self.rrsets[zid]
if zid != key_all_zones:
rrsets = [self.conn.get_all_rrsets(zone_id),]
else:
all_zones = self.conn.get_all_hosted_zones()
rrsets = []
for zone in all_zones.get('ListHostedZonesResponse').get('HostedZones'):
rrsets.append(self.conn.get_all_rrsets(zone.get('Id').split('/')[2]))
self.rrsets[zid] = rrsets
return self.rrsets[zid]
def find_record(self, hostname, rtype=None, zone_id=None, cached=None):
"""
Finds records according to its hostname
Default, returns a list of tuples (Record, RecordSet) of type 'A'
rtype: returns Default but with this type
zone_id: see self.get_recordsets
cached: see self.get_recordsets
"""
if rtype is None:
rtype = 'A'
found_records = []
for recordset in self.get_recordsets(zone_id=zone_id, cached=cached):
for record in recordset:
for res in record.resource_records:
if record.type == rtype and res.startswith(hostname):
found_records.append((record, recordset))
if record.type == rtype and record.name.startswith(hostname):
found_records.append((record, recordset))
return found_records
def create_record(self, zonename, rname, rtype, values, ttl=300):
"""
Creates a new Record
Returns a ChangeResourceRecordSetsResponse
zonename: a string that can return a single zone
rname: a string with a FQDN
rtype: a string with a record type like A, TXT, CNAME, ...
values: list of values of for this Record
ttl: time to live value
"""
zone_ids = self.get_zone_ids([zonename])
if len(zone_ids[zonename])<>1:
raise Exception('Too many zones returned, can only be one')
zone_id = zone_ids[zonename][0]
recordsets = self.get_recordsets(zone_id, cached=False)
if len(recordsets)<>1:
raise Exception('Too many recordsets returned, can only be one')
recordset = recordsets[0]
found_records = self.find_record(rname, rtype, zone_id)
if len(found_records):
raise Exception('Record already exists')
new_record = route53.record.Record(name=rname,
type=rtype,
ttl=ttl,
resource_records=values)
recordset.add_change_record("CREATE", new_record)
return recordset.commit()
def update_record(self, recordtuple, values):
"""
Updates a Record
Returns a ChangeResourceRecordSetsResponse
recordtuple: (Record, RecordSet)
values: list of values of for this Record
"""
record, recordset = recordtuple
new_record = route53.record.Record(name=record.name,
type=record.type,
ttl=300,
resource_records=values,
alias_hosted_zone_id=record.alias_hosted_zone_id)
recordset.add_change_record("DELETE", record)
recordset.add_change_record("CREATE", new_record)
return recordset.commit()
def delete_record(self, recordtuple):
"""
Deletes a Record
Returns a ChangeResourceRecordSetsResponse
recordtuple: (Record, RecordSet)
"""
record, recordset = recordtuple
recordset.add_change_record("DELETE", record)
return recordset.commit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment