#!/bin/env ruby require 'rubygems' gem 'aws-sdk' require 'aws-sdk' require 'optparse' access_key_id = nil secret_access_key = nil hosted_zone_name = nil record_name = nil record_ttl = 300 record_value = `wget -q -O - checkip.dyndns.org|sed -e 's/.*Current IP Address: //' -e 's/<.*$//'`.chomp record_kind = "A" timeout_count = 10 timeout_wait = 5 opt = OptionParser.new opt.on('-a', '--access-key-id=VAL') { |v| access_key_id = v } opt.on('-s', '--secret-access-key=VAL') { |v| secret_access_key = v } opt.on('-z', '--hosted-zone-name=VAL') { |v| hosted_zone_name = v } opt.on('-r', '--record-name=VAL') { |v| record_name = v } opt.on('-v', '--record-value=VAL', "default:#{record_value}") { |v| record_value = v } opt.on('-t', '--record-ttl=VAL', "default:#{record_ttl}") { |v| record_ttl = v } opt.on('-k', '--record-kind=VAL', "default:#{record_kind}") { |v| record_kind = v } opt.on('-c', '--timeout-count=VAL', "default:#{timeout_count}") { |v| timeout_count = v.to_i } opt.on('-w', '--timeout-wait=VAL', "default:#{timeout_wait}") { |v| timeout_wait = v.to_i } opt.parse!(ARGV) if hosted_zone_name.nil? || record_name.nil? raise "option is necessary, use --help option" end if record_value.empty? raise "can't get public ip" end r53 = AWS::Route53.new(:access_key_id => access_key_id, :secret_access_key => secret_access_key, :proxy_uri => ENV['HTTP_PROXY'] || ENV['http_proxy']) resp = r53.client.list_hosted_zones target_id = resp[:hosted_zones].find { |x| x[:name] == hosted_zone_name }[:id] record_list = r53.client.list_resource_record_sets(:hosted_zone_id => target_id, :start_record_name => record_name) target_record = record_list[:resource_record_sets].find { |record| record[:name] == record_name } if target_record && (target_record[:resource_records].nil? || target_record[:resource_records].size != 1 || target_record[:type] != record_kind) raise "record is already exist and can't override" end if target_record && (target_record[:resource_records][0][:value] == record_value) puts "record already exist and setting is unnecessary, you should delete exist record by hand" exit end request = { :hosted_zone_id => target_id, :change_batch => { :changes => [{ :action => "CREATE", :resource_record_set => { :name => record_name, :type => record_kind, :ttl => record_ttl, :resource_records => [{ :value => record_value }] } }] } } if target_record request[:change_batch][:changes].unshift({ :action => "DELETE", :resource_record_set => target_record }) end change_result = r53.client.change_resource_record_sets(request) change_result[:change_info][:id] timeout_count.times do break if change_result[:change_info][:status] == "INSYNC" sleep timeout_wait change_result = r53.client.get_change(:id => change_result[:change_info][:id]) end if change_result[:change_info][:status] != "INSYNC" raise "timeout to update record, status is #{change_result[:change_info][:status]}" end