Рецепт для capistrano — импорт production базы на девелоперскую машину

в 9:42, , рубрики: capistrano, ruby, ruby on rails, метки: , ,

Иногда возникает ситуация, когда необходимо получить production базу к себе, для разработки и тестирования.
Я написал, как часть гема этот рецепт, сейчас работает только если база на production и development одна и та же (в нашем случае postgresql). При желании можно добавить и другие базы.

Для этой цели (как и для других) нам отлично подойдет Capistrano.

Для того, чтобы использовать рецепт необходимо установить 7zip на сервере и локальной машине:

sudo apt-get --assume-yes install p7zip-full


Добавить этот код в Capfile:

mac_os = `uname -a`.include?("Darwin")
run_local_sudo_psql = mac_os ? "psql -h localhost -U postgres" : "#{sudo} -u postgres psql"
run_local_psql = mac_os ? "psql -h localhost" : "psql"

config = YAML::load(File.open("config/database.yml"))
adapter = config[rails_env]["adapter"]
database = config[rails_env]["database"]
db_username = config[rails_env]["username"]
db_password = config[rails_env]["password"]

local_rails_env = 'development'
local_adapter = config[local_rails_env]["adapter"]
local_database = config[local_rails_env]["database"]
local_db_username = config[local_rails_env]["username"]
local_db_password = config[local_rails_env]["password"]

set :local_folder_path, "tmp/backup" # you can set where to store *.sql.7z files on dev machine
set :timestamp, Time.now.to_i # timestamp in seconds
set :db_file_name, "#{database}-#{timestamp}.sql" # etc. app_production-1332404980.sql
set :db_archive_ext, "7z"

namespace :db do
  task :backup do
    file_name = fetch(:db_file_name)
    archive_ext = fetch(:db_archive_ext)
    dump_file_path = "#{shared_path}/backup/#{file_name}"
    output_file = "#{dump_file_path}.#{archive_ext}"
    run "mkdir -p #{shared_path}/backup"
    if adapter == "postgresql"
      run %{export PGPASSWORD="#{db_password}" && pg_dump -U #{db_username} #{database} > #{dump_file_path}}
      run "cd #{shared_path} && 7z a #{output_file} #{dump_file_path} && rm #{dump_file_path}"
    else
      puts "Cannot backup, adapter #{adapter} is not implemented for backup yet"
    end
    system "mkdir -p #{local_folder_path}"
    download(output_file, "#{local_folder_path}/#{file_name}.#{archive_ext}")
  end
  task :import do
    file_name = "#{db_file_name}.#{db_archive_ext}"
    file_path = "#{local_folder_path}/#{file_name}"
    if local_adapter == "postgresql"
      system "cd #{local_folder_path} && 7z x #{file_name}"
      system %{echo "drop database #{local_database}" | #{run_local_sudo_psql}}
      system %{echo "create database #{local_database} owner #{local_db_username};" | #{run_local_sudo_psql}}
      puts "ENTER your development password: #{local_db_password}"
      system "#{run_local_psql} -U#{local_db_username} #{local_database} < #{local_folder_path}/#{db_file_name}"
      system "rm #{local_folder_path}/#{db_file_name}"
    else
      puts "Cannot import, adapter #{local_adapter} is not implemented for backup yet"
    end
  end
  task :pg_import do
    if adapter == local_adapter
      db.backup
      db.import
    else
      puts "Sorry, but development and production adapters must be equals"
    end
  end
end

Как это работает:

cap db:pg_import

  1. создает на сервере папку "#{project_name}/shared/backup"
  2. делает дамп production базы в эту папку, архивирует ее 7zip
  3. передает по ssh на локальную машину в папку проекта 'tmp/backup'
  4. разархивирует и импортирует в девелоперскую базу ВАЖНО: перед этим делая DROP текущей локальной базы

Автор: qwlk

Поделиться

* - обязательные к заполнению поля