require 'open3' module Siringa # Generate dump file name # # @return [String] def self.dump_file_name "#{Siringa.configuration.dumps_path}/db_#{Time.now.strftime('%Y%m%d%H%M%S')}.dump" end # Create a DB dump # # @param [String] dump path # @return [Object] def self.dump_to(dump_path) result = {} case adapter_config[:adapter] when "mysql", "mysql2" _, result[:error], result[:status] = Open3.capture3(mysql_dump_command(adapter_config[:host], adapter_config[:database], adapter_config[:username], adapter_config[:password], dump_path)) when "sqlite3" _, result[:error], result[:status] = Open3.capture3(sqlite_dump_command(adapter_config[:database], dump_path)) else raise NotImplementedError, "Unknown adapter type '#{adapter_config[:adapter]}'" end { :status => result[:status].success?, :error => result[:error], :dump_path => dump_path } end # Restore from a DB dump # # @param [String] dump path # @return [Object] def self.restore_from(dump_path) result = {} case adapter_config[:adapter] when "mysql", "mysql2" _, result[:error], result[:status] = Open3.capture3(mysql_restore_command(adapter_config[:host], adapter_config[:database], adapter_config[:username], adapter_config[:password], dump_path)) when "sqlite3" _, result[:error], result[:status] = Open3.capture3(sqlite_restore_command(adapter_config[:database], dump_path)) else raise NotImplementedError, "Unknown adapter type '#{adapter_config[:adapter]}'" end { :status => result[:status].success?, :error => result[:error], :dump_path => dump_path } end # Delete oldest dump files, keep 5 dump files # # @param [Array] file names # @return [Boolean] def self.keep_five_dumps(dump_files) if dump_files.length > 5 dump_files.first(dump_files.length - 5).each { |f| File.delete(f) } return true else return false end end # Retrieve a collection of dump files sorted by creation date # # @return [Array] def self.ordered_dumps Dir.glob("#{Siringa.configuration.dumps_path}/db_*.dump").sort_by { |f| File.mtime(f) } end private # Return a string with the dump command for MySql # # @param host [String] # @param database [String] # @param username [String] # @param password [String] # @param dump_path [String] # @return [String] def self.mysql_dump_command(host, database, username, password, dump_path) "/usr/bin/env mysqldump -h#{host} -u#{username} #{password_param(password)} #{database} > #{dump_path}" end # Return a string with the restore command for MySql # # @param host [String] # @param database [String] # @param username [String] # @param password [String] # @param dump_path [String] # @return [String] def self.mysql_restore_command(host, database, username, password, dump_path) "/usr/bin/env mysql -h#{host} -u#{username} #{password_param(password)} #{database} < #{dump_path}" end # Return a string with the password parameter # # @param password [String] # @return [String] def self.password_param(password) !password.nil? ? "-p#{password}" : "" end # Return a string with the dump command for Sqlite # # @param database [String] # @param dump_path [String] # @return [String] def self.sqlite_dump_command(database, dump_path) "/usr/bin/env sqlite3 #{database} '.backup #{dump_path}'" end # Return a string with the restore command for Sqlite # # @param database [String] # @param dump_path [String] # @return [String] def self.sqlite_restore_command(database, dump_path) "/usr/bin/env sqlite3 #{database} '.restore #{dump_path}'" end # Return ActiveRecord adapter config # # @return [Hash] def self.adapter_config ActiveRecord::Base.connection.instance_values["config"] end end