=begin = myrds.rb *Copyright*:: (C) 2013 by Novu, LLC *Author(s)*:: Tamara Temple *Since*:: 2013-05-01 *License*:: MIT *Version*:: 0.0.1 == Description Restore an RDS database snapshot =end require 'methadone' require 'fog' module NewBackup class MyRds include Methadone::CLILogging # Initialize the class with options def initialize(options={}) debug "#{self.class}##{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: Options: #{options}" @options = options end # Maximum number of tries to wait for database servers to be ready MAX_TRIES = 3 # Restore a snapshot of the target database yielding the database to the block def restore(&block) connect do |connection| get_rds(connection) do |rds_server| retrieve_snapshot(rds_server) do |snapshot| restore_db(connection,snapshot) do |db| yield db end end end end end # Establishes a connection to AWS RDS and yeilds a block on the connection def connect(&block) raise "no block given in #{self.class}#connect" unless block_given? aws = @options[:aws] debug "AWS Options: #{aws}" fog_options = { :aws_access_key_id => aws[:access_key], :aws_secret_access_key => aws[:secret_key], :region => aws[:rds_region]} Fog.timeout = @options[:fog][:timeout] yield Fog::AWS::RDS.new(fog_options) end # Get the RDS server def get_rds(connection) debug "#{self.class}##{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: rds instance_id: #{@options[:rds][:instance_id]}\nConnection servers: #{connection.servers}" rds_server = connection.servers.get(@options[:rds][:instance_id]) raise "No RDS server!" if rds_server.nil? yield rds_server end # Retrieve a snapshot def retrieve_snapshot(rds_server, &block) begin rds_server.snapshots.new(:id => snap_name).save new_snapshot = rds_server.snapshots.get(snap_name) 1.upto(MAX_TRIES) do |i| debug "#{self.class}##{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: waiting for new snapshot, try ##{i}" new_snapshot.wait_for { ready? } end yield new_snapshot ensure unless @options[:debug] new_snapshot.destroy unless new_snapshot.nil? end end end # Restore the snapshot to a database def restore_db(connection, snapshot, &block) begin connection. restore_db_instance_from_db_snapshot(snapshot.id, backup_server_id, {"DBSubnetGroupName" => @options[:rds][:subnet_group], "DBInstanceClass" => @options[:rds][:instance_type]} ) backup_server = connection.servers.get(backup_server_id) 1.upto(MAX_TRIES) do |i| debug "#{self.class}##{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: waiting for backup server, try ##{i}" backup_server.wait_for { ready? } end yield MySqlCmds.new(backup_server.endpoint['Address'], @options[:mysql][:username], @options[:mysql][:password], @options[:mysql][:database], @options[:mysql][:obfuscate_script]) ensure unless @options[:debug] backup_server.destroy unless backup_server.nil? end end end # Return the snapshot name def snap_name "s3-dump-snap-#{@options[:timestamp]}".tap do |t| debug "#{self.class}##{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: Snap Name: #{t}" end end # Return the backup server id def backup_server_id "#{@options[:rds][:instance_id]}-s3-dump-server-#{@options[:timestamp]}".tap do |t| debug "#{self.class}##{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: Backup Server ID: #{t}" end end end end