Skip to content

Instantly share code, notes, and snippets.

@Aethelflaed
Created October 3, 2015 08:51
Show Gist options
  • Save Aethelflaed/c0a538260b2b6f30da3a to your computer and use it in GitHub Desktop.
Save Aethelflaed/c0a538260b2b6f30da3a to your computer and use it in GitHub Desktop.
scalingo mongo backup command
#!/usr/bin/env ruby
require 'bundler'
require 'thor'
class Database < Thor
desc 'restore BACKUP_PATH', 'Restore the database with given backup'
option :port, default: '27017'
option :host, default: '127.0.0.1'
option :database
def restore(backup_path)
execute "echo 'db.dropDatabase();' | mongo #{options[:database]}"
execute "mongorestore -h #{options[:host]} -p #{options[:port]} -d #{options[:database]} #{backup_path}"
end
desc 'backup BACKUP_PATH', 'Backup the production database using scalingo'
option :scalingo_app
option :tunnel_port, default: 20000
option :var_name, default: 'DB_URI'
option :identity, default: '~/.ssh/id_rsa'
def backup(path)
puts 'Fetching env variables...'
env = Hash[execute("scalingo -app #{options[:scalingo_app]} env").split("\n").map{|line| line.split('=', 2)}]
db_uri = env[options[:var_name]]
opts = "--port #{options[:tunnel_port]}"
opts += " --identity #{options[:identity]}" if options[:identity]
puts 'Establishing db tunnel...'
command = "scalingo -app #{options[:scalingo_app]} db-tunnel #{opts} #{options[:var_name]}"
puts "$ #{command}"
read, write = IO.pipe
pid = spawn(command, out: write)
puts 'Waiting 1 second for tunnel to establish'
sleep(1)
if Process.waitpid(pid, Process::WNOHANG)
$stderr.puts 'Unable to establish tunnel.'
return
end
# Ignore first line
read.gets
second_line = read.read_nonblock(50)
if second_line =~ /password/ # ssh asks for passphrase
print second_line
puts read.getc
puts 'Waiting for tunnel to establish'
read.gets
end
userpass, hostdb = db_uri[10..-1].split('@')
user, password = userpass.split(':')
db = hostdb.split('/').last
execute("mongodump -u #{user} -p #{password} -h 127.0.0.1:#{options[:tunnel_port]} -d #{db} -o #{path} --numThreads 1")
ensure
read.close if read
write.close if write
if pid
if !Process.waitpid(pid, Process::WNOHANG)
puts 'Closing db-tunnel...'
Process.kill('INT', pid)
end
end
Process.wait
end
no_commands do
def execute(command)
puts "$ #{command}"
`#{command}`
end
end
end
Database.start(ARGV)
source 'https://rubygems.org'
ruby '2.0.0'
gem 'thor'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment