DBが存在しないときにDBを作成するChefレシピを作ったときの試行錯誤メモ

開発サーバ用のcookbookを作る際に、MySQLのDBが存在しないときにDBを作成したかったときの試行錯誤メモ

opscode-cookbooks/wordpressのDB作成部分を参考にというかほぼそのまま流用

使用したboxは

http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.4-i386-v20130731.box

やりたいこと

  1. MySQLのインストールと起動
  2. DBユーザの作成
  3. DBの作成
  4. テーブルの作成

1.MySQLのインストールと起動

package "mysql-server" do
    action :install
end

service "mysqld" do
    action [ :enable, :start ]
    supports :status => true, :restart => true, :reload => true
end

2.DBユーザの作成

GRANT文をまとめたgrants.sql.erbをtemplatesに格納しておき、/tmpにUPの後、mysqlコマンドで流し込む。

grants.sql.erbの中身

GRANT ALL ON <%= @database %>.* TO '<%= @user %>'@'localhost' IDENTIFIED BY '<%= @password %>';
GRANT ALL ON <%= @database %>.* TO '<%= @user %>'@'%' IDENTIFIED BY '<%= @password %>';
FLUSH PRIVILEGES;

レシピに追加

execute "mysql-create-user" do
    command "/usr/bin/mysql -u root --password=\"#{node['example']['db']['rootpass']}\"  < /tmp/grants.sql"
    action :nothing
end

template "/tmp/grants.sql" do
    owner "root"
    group "root"
    mode "0600"
    variables(
        :user     => node['example']['db']['user'],
        :password => node['example']['db']['pass'],
        :database => node['example']['db']['database']
    )
    notifies :run, "execute[mysql-create-user]", :immediately
end

executeリソースではaction :nothingで実行せず、templateリソースでnotifiesを使ってexecuteリソースを実行させる

3.DBの作成

Mysql::list_dbsを利用して、DBの存在チェックを行い、なければmysqladminコマンドでDBを作成する。

package "mysql-devel" do
    action :install
end.

chef_gem "mysql" do
    action :nothing
    subscribes :install, "package[mysql-devel]", :immediately
end

execute "mysql-create-database" do
    command "/usr/bin/mysqladmin -u root create #{node['example']['db']['database']}"
    not_if do
        require 'rubygems'
        Gem.clear_paths
        require 'mysql'
        m = Mysql.new(node['example']['db']['host'], "root", node['example']['db']['rootpass'])
        m.list_dbs.include?(node['example']['db']['database'])
    end
end

executeリソースのnot_ifにあるrubyプログラム部で、Mysqlライブラリを使うためには、chefを動かしているrubyに対して、インストールする必要がある。
そこで、chef_gemリソースを使う。

またgem install msyqlの際にmysqlのヘッダファイルが必要になるので、mysql-develもインストールする。

しかしそれだけだと、最初のpackage “mysql-devel”よりも先に、chef_gemリソースが実行されてしまうので、

================================================================================
Error executing action `install` on resource 'chef_gem[mysql]'
================================================================================

Gem::Installer::ExtensionBuildError
-----------------------------------
ERROR: Failed to build gem native extension.

というエラーになってしまう。
そこで、subscribesを使って、package mysql-develを実行した後に、即時実行するように指定する。

4.テーブルの作成

2.と同様にCREATE TABLES文をまとめたtables.sqlをfilesに格納しておき、/tmpにUPの後、mysqlコマンドで流し込む。
3.と同様にテーブルがなければ実行するようにしたが、tables.sqlがアップ済みなら実行されないので冗長かもしれない。

execute "mysql-create-tables" do
    command "/usr/bin/mysql -u root #{node['example']['db']['database']} < /tmp/tables.sql"
    action :nothing
    only_if do
        require 'rubygems'
        Gem.clear_paths
        require 'mysql'
        m = Mysql.new(node['example']['db']['host'], "root", node['example']['db']['rootpass'])
        begin
            m.select_db(node['example']['db']['database'])
            m.list_tables.empty?
        rescue Mysql::Error
            return false
        end
    end
end

cookbook_file "/tmp/tables.sql" do
    owner "root"
    group "root"
    mode "0600"
    notifies :run, "execute[mysql-create-tables]", :immediately
end

注釈

  • node[‘example’]~はattributesのdefault.rbで定義した値
    default['example']['db']['user'] = 'username'
    default['example']['db']['pass'] = 'password'
    default['example']['db']['database'] = 'database-name'
    default['example']['db']['host'] = 'localhost'
    default['example']['db']['rootpass'] = ''
    

    exampleのところはクックブック名に置き換える。
    rootpassが何もないのは、インストール後のデフォルトではrootのパスワードはないため

  • grants.sqlやtables.sqlは/tmpではなくてきちんとしたところにUPしたほうがいい
  • 同様のことは、opscode-cookbooks/databaseを使えばできる。

参考になったページ

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中