Skip to content

Instantly share code, notes, and snippets.

@mscottford
Created May 24, 2010 18:52
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save mscottford/412271 to your computer and use it in GitHub Desktop.
Uses the Rackspace Apps control panel website to update the DNS A record for a subdomain.
#!/usr/bin/ruby
require 'rubygems'
require 'steam'
require 'net/http'
require 'resolv'
require 'mail'
class DnsUpdateBot
def initialize
# assumes that the HtmlUnit jar files are stored in an htmlunit directory
Steam.config[:html_unit][:java_path] = File.dirname(__FILE__) + '/htmlunit/lib'
@browser = Steam::Browser.create
end
def login(username, password)
@browser.get('https://cp.rackspace.com')
sanity_check
@browser.fill_in('username', :with => username)
@browser.fill_in('password', :with => password)
@browser.click_button('login')
sanity_check
end
# record_type is expected to be one of :a, :cname, :url, :frame or :txt
def update_dns_entry(domain, hostname, record_type, address)
@browser.get("https://cp.rackspace.com/no-borders/domains/domains/dns/dnsRecords.asp?domain=#{domain}")
address_field = @browser.locate_in_browser(:field, :xpath => ".//*[@id='nonMailRecordTable']/descendant::input[@value='#{hostname}']/parent::td/parent::tr/descendant::select[contains(@name, 'Type')]/option[@selected and @value='#{record_type.to_s.upcase}']/parent::select/parent::td/parent::tr/descendant::input[contains(@name, 'Address')]")
address_field.setText(address) rescue address_field.setValueAttribute(address)
@browser.click_button('Save')
sanity_check
raise "Update failed" unless @browser.response.body.include?('Your records have been successfully updated!')
end
private
def sanity_check
raise "Something went wrong" unless @browser.response.status == 200
end
end
class PublicIpBot
def fetch
try_three_times do
Net::HTTP.get(URI.parse('http://whatismyip.org'))
end
end
private
def try_three_times
raise "A block is required" unless block_given?
result = nil
attempt_count = 1
was_attempt_successful = false
while (not was_attempt_successful) and (attempt_count < 3)
begin
result = yield
was_attempt_successful = true
rescue
attempt_count += 1
end
end
result
end
end
begin
public_ip_bot = PublicIpBot.new
unless public_ip_bot.fetch == Resolv.getaddress('home.example.com')
dns_bot = DnsUpdateBot.new
dns_bot.login('user_name', 'sekret')
dns_bot.update_dns_entry('example.com', 'home', :a, public_ip_bot.fetch)
end
rescue Exception => error
Mail.defaults do
delivery_method :smtp, {
:address => 'smtp.example.com',
:domain => 'smtp.example.com',
:user_name => 'robot@example.com',
:password => 'sekret',
:authentication => nil,
:enable_starttls_auto => true
}
end
mail = Mail.new do
from 'robot@example.com'
to 'you@example.com'
subject '[alert] ip update failure'
body error.to_s
end
mail.deliver
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment