Skip to content

Instantly share code, notes, and snippets.

@IronSavior
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IronSavior/49a6971e181a37ffd7a3 to your computer and use it in GitHub Desktop.
Save IronSavior/49a6971e181a37ffd7a3 to your computer and use it in GitHub Desktop.
Create CNAME records in Route 53 that refer to the running EC2 instance. Can be run at startup or on a cron job.
#!/bin/env ruby
# Create CNAME records in Route 53 that refer to the running EC2 instance
# Unless specified by the first argument, a default TTL of 300 is assumed.
# Instance tags specify CNAMES to be set:
# 'set_cname:0' => 'name.example.com', 'set_cname:1' => 'name2.example.com', etc
# Uses IAM credentials found in the AWS CLI config file:
# ~/.aws/config (use `aws configure` to create)
# Depends on ec2-metadata command to retrieve the current instance ID
# Invoking via rc.local or cron--You may need to set HOME and/or PATH:
# HOME=/root PATH=/opt/aws/bin:$PATH /full/path/to/set_ec2_cnames.rb
# Author: Erik Elmore <erik@erikelmore.com>
# License: Public Domain
require 'aws/ec2'
require 'aws/route_53'
# Fetch credentials from the AWS CLI config file "~/.aws/config"
# You can use the AWS CLI command `aws configure` to create this file.
# This requires ENV['HOME'] to be set (which might not be true during boot)
def aws_config( opts = {} )
opts = {
:profile => :default,
:keys => [:aws_access_key_id, :aws_secret_access_key, :region],
:file => File.expand_path('~/.aws/config')
}.merge opts
rx_for = ->(key){ /^\[#{opts[:profile]}\]\n[^\[]+\n#{key}\s*=\s*([^\s]+)$/m }
find = ->(key, body){ body.match(rx_for.(key)).captures[0] }
body = opts[:body] || File.read(opts[:file])
Hash[ opts[:keys].map{ |key|
[key.to_s.gsub('aws_', '').to_sym, find.(key, body)]
}]
end
def instance_id
%x{ ec2-metadata -i |cut -f2 -d ' ' }.strip
end
ttl = (ARGV[0] || 300).to_i
AWS.config(aws_config)
box = AWS::EC2.new.instances[instance_id]
cnames = box.tags.select{ |tag, *|
tag =~ /^set_cname\b/
}.map{|*, fqdn| fqdn.end_with?('.')? fqdn : fqdn + '.' }
Process.exit 0 if cnames.empty?
r53 = AWS::Route53.new
cnames.each do |cn|
zone = r53.hosted_zones.detect{|z| cn.end_with? z.name }
raise 'Cannot set CNAME %s because no matching Route 53 zone was found.' % cn.chop if zone.nil?
rs = zone.resource_record_sets[cn, 'CNAME']
if rs.exists? && rs.ttl == ttl && box.dns_name == rs.resource_records[0][:value]
puts "No change required for CNAME #{cn}"
next
end
rs.delete if rs.exists?
zone.resource_record_sets.create(
cn,
'CNAME',
:ttl => ttl, :resource_records => [{ :value => box.dns_name }]
)
puts 'Created CNAME %s -> %s with TTL %d' % [cn.chop, box.dns_name, ttl]
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment