class Backupper
Constants
- VERSION
Public Class Methods
new(conf_file_path)
click to toggle source
# File lib/backupper/backupper.rb, line 19 def initialize(conf_file_path) conf = YAML.load_file(conf_file_path) @default = conf['default'] || {} @mailer = conf['mailer'] || {} @conf = conf.select { |k, v| !%w[default mailer].include?(k) && (v['disabled'].nil? || v['disabled'] == false) } @report = {} @logger = SSHKit::Formatter::Pretty.new($stdout) end
Public Instance Methods
backup!(only_these_keys = nil)
click to toggle source
# File lib/backupper/backupper.rb, line 28 def backup!(only_these_keys = nil) filtered_conf = @conf filtered_conf = @conf.slice(*only_these_keys) if only_these_keys filtered_conf.each do |k, options| @logger.info "[#{Time.now}] ⬇️ backing up #{k}..." o, err = setup_options(options) if err error(k, err) @logger.error err next end begin download_dump( key: k, adapter: o['adapter'], url: o['url'], password: o['password'], database: o['database'], db_username: o['db_username'], db_password: o['db_password'], dump_options: o['dump_options'], outdir: o['outdir'], extra_copy: o['extra_copy'] ) rescue SSHKit::Runner::ExecuteError => e error(k, e.to_s) @logger.error e end end send_report_email! end
download_dump(key:, adapter: 'mysql', url:, password: nil, database:, db_username: 'root', db_password: nil, dump_options: nil, outdir:, extra_copy: nil)
click to toggle source
# File lib/backupper/backupper.rb, line 60 def download_dump(key:, adapter: 'mysql', url:, password: nil, database:, db_username: 'root', db_password: nil, dump_options: nil, outdir:, extra_copy: nil) t = Process.clock_gettime(Process::CLOCK_MONOTONIC) path = nil filename = "#{key}__#{database}.sql.bz2" tempfile = File.join('/tmp', filename) dumpname = "#{Time.now.strftime('%Y-%m-%d_%H-%M-%S')}__#{filename}" path = File.join(outdir, dumpname) on(url) do |client| client.password = password execute 'set -o pipefail; ' + DumpCommand.send(adapter, database: database, username: db_username, password: db_password, dump_options: dump_options, outfile: tempfile) download! tempfile, path execute :rm, tempfile end extra_copy = check_dir(extra_copy) FileUtils.cp(path, extra_copy) if extra_copy @report[key] = { path: File.absolute_path(path), size: (File.size(path).to_f / 2**20).round(2), time: (Process.clock_gettime(Process::CLOCK_MONOTONIC) - t).round(2) } @report[key].merge!({ extra_copy: File.absolute_path(File.join(extra_copy, dumpname)) }) if extra_copy end
Private Instance Methods
check_dir(dirpath)
click to toggle source
# File lib/backupper/backupper.rb, line 117 def check_dir(dirpath) return nil if dirpath.nil? unless File.exist?(dirpath) begin FileUtils.mkdir_p(dirpath) rescue StandardError => _e return nil end end return File.dirname(dirpath) unless File.directory?(dirpath) return dirpath end
error(key, error)
click to toggle source
# File lib/backupper/backupper.rb, line 113 def error(key, error) @report[key] = { error: error } end
send_report_email!()
click to toggle source
# File lib/backupper/backupper.rb, line 103 def send_report_email! if @report.any? && @mailer['from'] && @mailer['to'] && @mailer['password'] begin Mailer.send(from: @mailer['from'], to: @mailer['to'], password: @mailer['password'], report: @report) rescue Net::SMTPAuthenticationError => e @logger.error e end end end
setup_options(options)
click to toggle source
# File lib/backupper/backupper.rb, line 85 def setup_options(options) o = @default.merge(options) o['outdir'] = check_dir(o['dump'].to_s) return nil, 'Invalid directory where to save database dump' unless o['outdir'] return nil, 'Please specify the database name!' unless o['database'] return nil, 'Please specify the host!' unless o['host'] o['url'] = o['host'] o['url'] = "#{o['username']}@#{o['url']}" if o['username'] o['url'] = "#{o['url']}:#{o['port']}" if o['port'] o['adapter'] ||= 'mysql' unless DumpCommand.respond_to?(o['adapter']) return nil, "Cannot handle adapter '#{o['adapter']}'" end return o, nil end