Skip to content

Instantly share code, notes, and snippets.

@ckolos
Created August 11, 2017 13:45
Show Gist options
  • Save ckolos/02c923870fa3a39ffe56c6b3593a097f to your computer and use it in GitHub Desktop.
Save ckolos/02c923870fa3a39ffe56c6b3593a097f to your computer and use it in GitHub Desktop.
Code used to create 2000+ services.mozilla.com records in r53.
#!/usr/bin/env python
from __future__ import print_function
import argparse
import boto3
import time
from sys import exit
from zone_file import parse_zone_file
import pdb
name_alias = dict()
record_set = list()
cache = dict()
def batch(iterable, n=1):
l = len(iterable)
for index in range(0, l, n):
yield iterable[index:min(index + n, l)]
def build_rr_cache():
rrname = 'aaaa0000.' + my_zone # Gotta start somewhere
for count in ['100', '10', '1']:
response = r53.list_resource_record_sets(HostedZoneId=zone_id,
StartRecordName=rrname,
MaxItems=count)
while len(response['ResourceRecordSets']) > 0:
for i in range(0, len(response['ResourceRecordSets'])):
cache[response['ResourceRecordSets'][i]['Name']] = cache.get(response['ResourceRecordSets'][i]['Name'], 0)+1
try:
rrname = response['NextRecordName']
response = r53.list_resource_record_sets(HostedZoneId=zone_id,
StartRecordName=rrname,
MaxItems=count)
except KeyError:
break
def find_rec(name):
rrname = name + '.' + my_zone
if rrname in cache.keys():
return(True)
else:
return(False)
def add_a(name, ip):
rrname = name + '.' + my_zone
record_add = r53.change_resource_record_sets(
HostedZoneId=zone_id,
ChangeBatch={
'Comment': 'None',
'Changes': [
{
'Action': 'UPSERT',
'ResourceRecordSet': {
'Name': rrname,
'Type': 'A',
'TTL': 60,
'ResourceRecords': [
{
'Value': ip,
}
]
}
}
]
}
)
time.sleep(3)
return(record_add)
def make_cname(cname_record):
name, alias = cname_record
rrname = name + '.services.mozilla.com'
TTL = 86400
try:
rrname.index('sync')
except ValueError:
TTL = 60
return {
'Action': 'UPSERT',
'ResourceRecordSet': {
'Name': rrname,
'Type': 'CNAME',
'TTL': TTL,
'ResourceRecords': [
{
'Value': alias,
}
]}}
def add_records(record_set):
record_add = r53.change_resource_record_sets(
HostedZoneId=zone_id,
ChangeBatch={
'Comment': 'None',
'Changes': record_set,
}
)
time.sleep(3)
return(record_add)
def verify_change(response):
results = response['ChangeInfo']['Status']
if results == "PENDING":
check = response['ChangeInfo']['Id']
waiter = r53.get_waiter('resource_record_sets_changed')
waiter.wait(Id=check)
if args.verbose:
print('.', end='')
else:
if results == 'INSYNC':
return(True)
else:
return(False)
parser = argparse.ArgumentParser(
description='Populate smc from a bind forward lookup file')
parser.add_argument('--verbose', '-v', action="store_const", const=True,
default=False, help='show records being added')
parser.add_argument('--dry', '-n', action="store_const", const=True,
default=False, help='dry run. change nothing.')
parser.add_argument('--file', '-f', nargs=1, required=True,
help='the forward directory file to process')
parser.add_argument('--zone', '-z', nargs=1, required=True,
help='the zone you wish to add records to')
args = parser.parse_args()
my_zone = args.zone[0] + '.'
if args.file[0]:
try:
ns_file = open(args.file[0], "r")
ns_records = ns_file.read()
except IOError:
print("Couldn't open %s", args.file[0])
exit(1)
zone_file_object = parse_zone_file(ns_records)
try:
r53 = boto3.client('route53')
except:
print("Error creating boto connection to r53")
exit(1)
try:
zoneinfo = r53.list_hosted_zones()
except:
print("Error making connection to r53")
exit(1)
for zone in zoneinfo.get('HostedZones'):
if zone['Name'] == my_zone:
zone_id = zone['Id'].split('/')[-1]
if zone_id is None:
print("Error: smc zone id couldn't be found")
exit(1)
build_rr_cache()
for i in range(0, len(zone_file_object['a'])):
record = zone_file_object['a'][i]
name = record['name']
ip = record['ip']
if args.dry is False:
if find_rec(name):
print("Record {} already exists".format(record))
else:
if args.verbose is True:
if args.dry is True:
print("\nDRY RUN - Adding: {0}".format(record))
else:
print("\nAdding: {0}".format(record))
return_value = add_a(name, ip)
if verify_change(return_value):
if args.verbose is True:
print("\nAdded: {0}".format(record))
else:
print("Dry Run - Record added(?)")
for i in range(0, len(zone_file_object['cname'])):
name_alias[zone_file_object['cname'][i]['name']] = zone_file_object['cname'][i]['alias']
for working_set in batch(name_alias.items(), 75):
for item in working_set:
if args.verbose is True:
print("Adding: {0} {1}".format(item[0], item[1]))
if args.dry is True:
print("Dry Run - Record added(?) {} ".format(len(working_set)))
else:
if find_rec(item[0]):
print("Record {0} -> {1} already exists".format(item[0], item[1]))
else:
this_record = make_cname(item)
record_set.append(this_record)
if args.dry is True:
continue
else:
if len(record_set) != 0:
return_value = add_records(record_set)
if verify_change(return_value):
if args.verbose is True:
print("\nAdded: {0}".format(record_set))
else:
if args.verbose is True:
print("Moving to next record set")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment