Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8a32546

Browse files
committed
route53-migrate-zone now handles existing records gracefully.
1 parent 231f0f5 commit 8a32546

1 file changed

Lines changed: 72 additions & 19 deletions

File tree

route53-migrate-zone/route53-migrate-zone.py

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,23 @@ def commit_record_changeset(to_zone_record_changeset):
2020
sys.stdout.write("The error message given was: " + error.error_message + ".\n")
2121
exit(69)
2222

23+
24+
def diff_record(record_a, record_a_object, record_b, record_b_object):
25+
compare_values = ["type", "ttl", "resource_records", "alias_hosted_zone_id", "alias_dns_name", "identifier", "weight", "region"]
26+
diff_record_result = False
27+
28+
for value in compare_values:
29+
if getattr(record, value) != getattr(to_zone_existing_resource_record_dict[record.name], value):
30+
diff_record_result = True
31+
return diff_record_result
32+
2333
app_name = os.path.basename(__file__)
2434
config = ConfigParser.ConfigParser()
2535
config.read('config.ini')
26-
#functions: newzone, new account, newzone and newaccount
27-
functions = ["newzone", "newaccount"]
36+
#functions: currently supports newzone - the functions are set automatically by the route53-migrate-zone script
37+
functions = []
2838

29-
#these user credentials should be read-only
39+
#the from_zone user credentials should be read-only
3040
from_access_key = config.get("from_zone_values", "from_access_key")
3141
from_secret_key = config.get("from_zone_values", "from_secret_key")
3242
from_zone_name = config.get("from_zone_values", "from_zone_name")
@@ -37,25 +47,55 @@ def commit_record_changeset(to_zone_record_changeset):
3747
#best would be to retreive the to_zone_id using to_zone_name
3848
to_zone_id = config.get("to_zone_values", "to_zone_id")
3949

50+
record_types_to_migrate = ["A", "CNAME", "MX", "TXT"]
51+
52+
if from_zone_name != to_zone_name:
53+
print app_name + " will rewrite domain names ending in \"" + from_zone_name + "\" to domain names ending in \"" + to_zone_name + "\""
54+
functions.append("newzone")
55+
4056
#creates Route53Connection Object
4157
from_connection = boto.route53.Route53Connection(aws_access_key_id=from_access_key, aws_secret_access_key=from_secret_key)
4258
to_connection = boto.route53.Route53Connection(aws_access_key_id=to_access_key, aws_secret_access_key=to_secret_key)
43-
#creates a set of changes to be delivered to Route53
44-
to_zone_record_changeset = boto.route53.record.ResourceRecordSets(to_connection, to_zone_id)
45-
46-
record_types_to_migrate = ["A", "CNAME", "MX", "TXT"]
4759

48-
#print out all records
60+
#create connection to from_zone
4961
try:
5062
from_zone = from_connection.get_zone(from_zone_name)
5163
except boto.route53.exception.DNSServerError, error:
5264
sys.stdout.write("An error occured when attempting to create a connection to AWS.\n")
5365
sys.stdout.write("The error message given was: " + error.error_message + ".\n")
5466
exit(1)
5567

68+
#create connection to to_zone
69+
try:
70+
to_zone = to_connection.get_zone(to_zone_name)
71+
except boto.route53.exception.DNSServerError, error:
72+
sys.stdout.write("An error occured when attempting to create a connection to AWS.\n")
73+
sys.stdout.write("The error message given was: " + error.error_message + ".\n")
74+
exit(1)
75+
76+
#creates ResourceRecordSets object named from_zone_records (ResourceRecordSets = a collection of resource records)
5677
from_zone_records = from_zone.get_records()
57-
#resource_record_dict will be used to store all resource records
78+
#creates ResourceRecordSets object named to_zone_records (ResourceRecordSets = a collection of resource records)
79+
to_zone_records = to_zone.get_records()
80+
81+
#resource_record_dict will be used to store all resource records that should be transferred
5882
resource_record_dict = {}
83+
#to_zone_existing_resource_record_dict will be used to store all resource records that should be transferred
84+
to_zone_existing_resource_record_dict = {}
85+
86+
#creates a set of changes to be delivered to Route53
87+
to_zone_record_changeset = boto.route53.record.ResourceRecordSets(to_connection, to_zone_id)
88+
89+
for record in to_zone_records:
90+
to_zone_existing_resource_record_dict[record.name] = record
91+
92+
#counts of records - should be replaced by dictionary
93+
uncommitted_change_elements = 0
94+
processed_record_count = 0
95+
migrated_record_count = 0
96+
existing_records_in_to_zone_count = 0
97+
identical_records_in_to_zone_count = 0
98+
different_records_in_to_zone_count = 0
5999

60100
#get records from from_zone
61101
for record in from_zone_records:
@@ -64,15 +104,25 @@ def commit_record_changeset(to_zone_record_changeset):
64104
#print "Existing Record Name: " + record.name
65105
record.name = re.sub(from_zone_name, to_zone_name, record.name)
66106
#print "Modified Record Name: " + record.name
67-
resource_record_dict[record.name] = boto.route53.record.Record(name=record.name, type=record.type, ttl=record.ttl, resource_records=record.resource_records, alias_hosted_zone_id=record.alias_hosted_zone_id, alias_dns_name=record.alias_dns_name, identifier=record.identifier, weight=record.weight, region=record.region)
68-
69-
#commit records to to_zone
70-
uncommitted_change_elements = 0
71-
examined_record_count = 0
72-
migrated_record_count = 0
107+
#test if record exists in to_zone
108+
if record.name in to_zone_existing_resource_record_dict:
109+
existing_records_in_to_zone_count += 1
110+
#compare records in from_domain and to_domain, store result as diff_result
111+
diff_result = diff_record(record.name, record, record.name, to_zone_existing_resource_record_dict)
112+
if diff_result is True:
113+
different_records_in_to_zone_count += 1
114+
sys.stdout.write("Record \"" + record.name + "\" exists in both \"" + from_zone_name + "\" and \"" + to_zone_name + "\" and is different.\n")
115+
elif diff_result is False:
116+
identical_records_in_to_zone_count += 1
117+
sys.stdout.write("Record \"" + record.name + "\" exists in both \"" + from_zone_name + "\" and \"" + to_zone_name + "\" and is identical.\n")
118+
else:
119+
sys.stdout.write("Diff of record " + record.name + " failed.\n")
120+
exit(1)
121+
else:
122+
resource_record_dict[record.name] = boto.route53.record.Record(name=record.name, type=record.type, ttl=record.ttl, resource_records=record.resource_records, alias_hosted_zone_id=record.alias_hosted_zone_id, alias_dns_name=record.alias_dns_name, identifier=record.identifier, weight=record.weight, region=record.region)
73123

74124
for record in resource_record_dict:
75-
examined_record_count += 1
125+
processed_record_count += 1
76126
#if record is an alias record we are not supporting yet
77127
if resource_record_dict[record].alias_dns_name is not None:
78128
sys.stdout.write("Record \"" + resource_record_dict[record].name + "\" is an alias record set and will not be migrated. " + app_name + " does not currently support alias record sets.\n")
@@ -82,7 +132,7 @@ def commit_record_changeset(to_zone_record_changeset):
82132
#DEBUG: print "Uncommitted Record Count:" + str(uncommitted_change_elements)
83133
#if there are 99 uncomitted change elements than they must be committed - Amazon only accepts up to 99 change elements at a given time
84134
#if the number of examined records is equal to the number of records then we can commit as well - we are now done examing records
85-
if uncommitted_change_elements >= 99 or examined_record_count == len(resource_record_dict):
135+
if uncommitted_change_elements >= 99 or processed_record_count == len(resource_record_dict):
86136
#DEBUG: print "Flushing Records:" + str(uncommitted_change_elements)
87137
commit_record_changeset(to_zone_record_changeset)
88138
migrated_record_count += uncommitted_change_elements
@@ -93,5 +143,8 @@ def commit_record_changeset(to_zone_record_changeset):
93143
print "Summary:"
94144
print "Records Migrated from zone: \"" + from_zone_name + "\" to zone: \"" + from_zone_name + "\"."
95145
print "Types of Records Selected for Migration: " + str(record_types_to_migrate) + "."
96-
print "Records Migrated: " + str(migrated_record_count) + "."
97-
print "Records Examined: " + str(examined_record_count) + "."
146+
print "Records processed (records such as Alias records may be processed but not migrated): " + str(processed_record_count)
147+
print "Records migrated: " + str(migrated_record_count) + "."
148+
print "Records not migrated because they already exist in zone \"" + to_zone_name + "\": " + str(existing_records_in_to_zone_count)
149+
print "Records that exist in both \"" + from_zone_name + "\" and \"" + to_zone_name + "\" and are identical: " + str(identical_records_in_to_zone_count)
150+
print "Records that exist in both \"" + from_zone_name + "\" and \"" + to_zone_name + "\" and are different: " + str(different_records_in_to_zone_count)

0 commit comments

Comments
 (0)