Skip to content

Instantly share code, notes, and snippets.

@anselm-helbig
Forked from prein/copy_dns_zones.rb
Last active July 20, 2016 17:04
Show Gist options
  • Save anselm-helbig/fe5c2db97b4f2d897b3e5ff02887e1b0 to your computer and use it in GitHub Desktop.
Save anselm-helbig/fe5c2db97b4f2d897b3e5ff02887e1b0 to your computer and use it in GitHub Desktop.
Copy DNS zones from CloudFlare to Route53
#!/usr/bin/env ruby
require "bundler/inline"
gemfile do
gem "rubyflare"
gem "route53"
end
require "yaml"
credentials = YAML.load(File.read("credentials.yml"))
cloudflare_conn = Rubyflare.connect_with(
credentials['cloudflare']['email'],
credentials['cloudflare']['api_key']
)
r53_conn = Route53::Connection.new(
credentials['aws']['access_key'],
credentials['aws']['secret_key']
)
module CloudFlare
# Get all zones (domains)
def self.zones(connection)
connection.get("zones", per_page: 1).results.map { |record|
Zone.new(record, connection)
}
end
Zone = Struct.new(:record, :connection) do
def name
record[:name]
end
def id
record[:id]
end
def dns_records
connection.get("zones/#{id}/dns_records", per_page: 1000).results.map { |r|
DnsRecord.new(r, connection)
}
end
end
DnsRecord = Struct.new(:record, :connection) do
def self.build(record, connection)
case record[:type]
when "MX"
MxRecord
else
DnsRecord
end.new(record, connection)
end
def name
record[:name] + "."
end
def type
record[:type]
end
def content
record[:content]
end
def matches?(other)
self.name == other.name &&
self.type == other.type &&
self.content == other.content
end
def to_route53(r53_zone)
Route53::DNSRecord.new(name, type, "60", [content], r53_zone)
end
end
class MxRecord < DnsRecord
def name
"#{cf_record[:priority]} #{cf_record[:name]}."
end
end
end
# Iterate over zones, and their records and create them in r53
CloudFlare.zones.each do |cf_zone|
mx_content = Hash.new { |h, k| h[k] = [] }
# Check if the zone exists already
puts "checking if #{cf_zone.name} zone exists in r53 - will create it only if it doesn't"
r53_zone = Array(r53_conn.get_zones(cf_zone.name)).first
unless r53_zone
r53_zone = Route53::Zone.new("#{cf_zone.name}.", nil, r53_conn)
# Create a zone in route53
puts "creating new zone in r53: #{cf_zone.name}."
resp = r53_zone.create_zone
exit 1 if resp.error?
while resp.pending?
sleep 1
end
end
# get the zone records
r53_zone_records = r53_zone.get_records
cf_zone_dns_records = cloudflare_conn.get("zones/#{cf_zone[:id]}/dns_records", per_page: 1000)
cf_zone_dns_records.results.each do |cf_record|
unless r53_zone.get_records.find { |r53_record|
r53_record.name == "#{cf_record[:name]}." &&
r53_record.type == cf_record[:type] &&
r53_record.values == cf_record[:content]
}
case cf_record[:type]
when "SOA", "NS"
next
when "MX"
mx_content[cf_record[:name]] << "#{cf_record[:priority]} #{cf_record[:name]}."
else
# Check if it doesn't exist in Route53 yet
puts "checking if #{cf_record[:name]} #{cf_record[:type]} record exists in r53 - will create it only if it doesn't"
unless r53_zone_records.find { |r53_record|
r53_record.name == "#{cf_record[:name]}." &&
r53_record.type == cf_record[:type] &&
r53_record.values.include?(cf_record[:content])
}
puts "creating #{cf_record[:type]} record named #{cf_record[:name]} in #{cf_zone[:name]} zone with content #{cf_record[:content]}"
# Create a new record within our newly created r53 zone.
new_record = Route53::DNSRecord.new("#{cf_record[:name]}.",cf_record[:type],"60",["#{cf_record[:content]}"],r53_zone)
new_record.create
end
end
end
end
mx_content.each do |mx_record_name, mx_record_content|
# Check if it doesn't exist in Route53 yet
puts "checking if #{mx_record_name} MX record exists in r53 - will create it only if it doesn't"
unless r53_zone_records.find { |r53_record|
r53_record.name == "#{mx_record_name}." &&
r53_record.type == "MX" &&
r53_record.values == mx_record_content.uniq
}
puts "creating MX record named #{mx_record_name} with in #{cf_zone[:name]} zone with content #{mx_record_content}"
# Create a new MX record within our newly created r53 zone.
new_mx_record = Route53::DNSRecord.new("#{mx_record_name}.","MX","60",mx_record_content.uniq,r53_zone)
new_mx_record.create
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment