Импорт базы данных Mysql с использованием Ruby / Chef Recipe для Vagrant - PullRequest
7 голосов
/ 15 мая 2011

Я пишу сценарий chef для автоматизации настройки среды разработки. Я могу создать базу данных и предоставить ей привилегии, но я пытаюсь найти способ импортировать файл дампа mysql в только что созданную базу данных.

Мой код для предоставления доступа:

ruby_block "Execute grants" do
  block do

    require 'rubygems'
    Gem.clear_paths
    require 'mysql'

    m = Mysql.new('localhost', "root", node[:mysql][:server_root_password])
    m.query("GRANT ALL ON *.* TO 'root'@'10.0.0.1' IDENTIFIED BY '#{node[:mysql][:server_root_password]}'")
    m.query('FLUSH PRIVILEGES')
end
end

и я надеялся, что смогу сделать следующий запрос #m.query("-u root -p root db_name < /project/db/import.sql")

но это просто дает мне ошибку.

Я не сделал много Руби, так что мне было трудно это понять. Кто-нибудь знает, как я могу это сделать?

Ответы [ 3 ]

5 голосов
/ 08 июля 2013

Если это ошибка пути к файлу и вы используете chef solo, попробуйте использовать путь, указанный в solo.rb , например:

/tmp/chef-solo/site-cookbooks/path_to_file.sql

Как общее примечание, рассмотрите возможность использования базы данных поваренной книги для задач управления пользователями и базами данных mysql. После того, как вы настроите необходимые зависимости поваренной книги, вы можете поместить подобный код в основной рецепт default.rb :

# externalize conection info in a ruby hash
mysql_connection_info = {
  :host => "localhost",
  :username => 'root',
  :password => node['mysql']['server_root_password']
}

# drop if exists, then create a mysql database named DB_NAME
mysql_database 'DB_NAME' do
  connection mysql_connection_info
  action [:drop, :create]
end

# query a database from a sql script on disk
mysql_database "DB_NAME" do
  connection mysql_connection_info
  sql { ::File.open("/tmp/chef-solo/site-cookbooks/main/path/to/sql_script.sql").read }
  action :query
end

#or import from a dump file
mysql_database "DB_NAME" do
  connection mysql_connection_info
  sql "source /tmp/chef-solo/site-cookbooks/main/path/to/sql_dump.sql;"
end

Последний не проверял, потому что хранение файла базы данных в каталоге chef действительно замедляет работу.

См. Также: Импорт файла SQL в mysql

3 голосов
/ 20 мая 2011

Вы можете создать резервную копию из клиента командной строки MySQL, но не из запроса SQL. Вам нужно выполнить команду из оболочки. Я считаю, что ресурс execute может помочь вам:

http://wiki.opscode.com/display/chef/Resources#Resources-Execute

1 голос
/ 21 июля 2015

Я не совсем Ruby, но мне удалось заставить Chef импортировать большой файл .sql, используя инструмент командной строки mysql. Задачи, которые мне нужно было решить:

  • Импорт файла .sql в диапазоне сотен МБ (YMMV, если вам нужны ГБ или ТБ)
  • Идемпотентность - запускать импорт можно только в том случае, если файл .sql изменился
  • Не передавать учетные данные в MySQL в качестве параметров команды (из соображений безопасности)

Сначала я создал .my.cnf шаблон файла для передачи учетных данных:

шаблоны / по умолчанию / .my.cnf.erb

[client]
host=<%= @host %>
user=<%= @user %>
password="<%= @password %>"

Затем я добавил в свой рецепт ресурс, который будет заполнять шаблон:

Рецепты / импорт-db.rb

template '/root/.my.cnf' do
  mode 0600
  variables({
    :host => 'localhost',
    :user => 'root',
    :password => node[:your_cookbook][:db][:root_password],
  })
end

(где node[:your_cookbook][:db][:root_password] - это атрибут, содержащий корневой пароль MySQL)

Примечание по безопасности : для простоты я делаю импорт как пользователь root. Если импортируемый файл .sql не из надежного источника, вам нужно будет запустить mysql как пользователь с ограниченными правами и подключиться к MySQL с пользователем с ограниченными правами доступа, который имеет доступ только к рассматриваемой базе данных.

Наконец, я добавил еще один ресурс в рецепт, который фактически выполняет импорт:

backup_sql = '/path/to/the/db-backup.sql'
db_last_modified = "/etc/db-#{node[:your_cookbook][:db][:name]}.lastmodified"

execute 'restore backup' do
  command "mysql #{node[:your_cookbook][:db][:name]} <'#{backup_sql}' && touch '#{db_last_modified}'"
  not_if { FileUtils.uptodate?(db_last_modified, [backup_sql]) }
end

(Где node[:your_cookbook][:db][:name] - имя базы данных MySQL, которая будет восстановлена.)

...