Chef の database cookbook でハマった話
こんにちは、エンジニアの小笠原です。
最近は Chef で開発環境の構築なんかやってるわけですが、database cookbook の利用でハマったので小ネタ的に。
結論からいうと、rubyのコードくらい読めるようになっておこうね、という話でしかないんですが。。
前提
- Heroku を使うことが多いので、RDBMS は基本 PostgreSQL
- 開発環境もできるだけ構成を本番環境に合わせて構築したい
- ローカル開発環境構築は基本 VirtualBox + Vagrant + Chef + Test-kitchen
- DB のユーザ作ったりデータベース作ったりは database cookbook で出来る
- 筆者は Ruby 経験ほぼなし
ハマったこと
postgresql cookbook での PostgreSQL の設定、database cookbook 使って稼働してる PostgreSQL への CREATE USER/GRANT, CREATE DATABASE 共に、それぞれ単体では問題なくできました。
が、双方を一緒に実行させようとするとエラーを吐いて止まります。
.kitchen.yml にはこう記述してる状態。
suites: - name: default run_list: - recipe[postgresql::server] - recipe[init_db]
init_db cookbook のレシピで、include_recipe database::postgresql
して DB ユーザの生成なんかを記述してるわけですね。
で、kitchen setup
すると、
(前略) [2014-07-16T01:09:18+00:00] ERROR: Exception handlers complete [2014-07-16T01:09:18+00:00] FATAL: Stacktrace dumped to /tmp/kitchen/cache/chef-stacktrace.out Chef Client failed. 15 resources updated in 711.501939185 seconds [2014-07-16T01:09:18+00:00] ERROR: execute[generate pg gem Makefile] (postgresql::ruby line 89) had an error: Mixlib::ShellOut::ShellCommandFailed: Expected process to exit with [0], but received '1' ---- Begin output of PATH=$PATH:/usr/pgsql-9.3/bin /opt/chef/embedded/bin/ruby extconf.rb ---- STDOUT: checking for pg_config... no checking for libpq-fe.h... no STDERR: No pg_config... trying anyway. If building fails, please try again with --with-pg-config=/path/to/pg_config Can't find the 'libpq-fe.h header *** extconf.rb failed *** (後略)
と怒られました。
なんで単体で動いたものが組み合わせると動かなくなるん? Chef って記述した順にシーケンシャルに実行してくれるんじゃないの?とまったく Chef を理解してない感丸出しで調査スタート。
単体で動いてたものが組み合わせると動かなくなった謎については、Engine Yardさんのブログが紐解いてくれました。
単体で database cookbook 動かしてた時は既に postgresql cookbook のおかげでインストールされてた libpq が、組み合わせた場合はコンパイル(か run_action 実行)時にはまだインストールされてない為エラーになった、と。
さてじゃぁ、どうやってあらかじめ libpq をインストールすれば良いんだろう?と考えてもわからなかったので、仕方なくソースコードを読みます。
エラーの発生した箇所は、出力されてるログからわかります。
Cookbook Trace: --------------- /tmp/kitchen/cookbooks/postgresql/recipes/ruby.rb:95:in `rescue in rescue in from_file' /tmp/kitchen/cookbooks/postgresql/recipes/ruby.rb:57:in `rescue in from_file' /tmp/kitchen/cookbooks/postgresql/recipes/ruby.rb:24:in `from_file' /tmp/kitchen/cookbooks/database/recipes/postgresql.rb:20:in `from_file' /tmp/kitchen/cookbooks/init_prj/recipes/default.rb:13:in `from_file'
ん? database cookbook って実際の DB の cookbook を呼び出してるのね。
まぁともかく追っていくと、postgresql/recipes/ruby.rb は、どうやら pg gem をビルドしてインストールするレシピのようですね。
で、95行目でエラーになってると。
lib_builder = execute 'generate pg gem Makefile' do # [COOK-3490] pg gem install requires full path on RHEL command "PATH=$PATH:/usr/pgsql-#{node['postgresql']['version']}/bin #{RbConfig.ruby} extconf.rb" cwd ext_dir action :nothing end lib_builder.run_action(:run)
lib_builder.run_action(:run)
が 95行目です。
んー、ということは、ここまでに libpq がインストールされれば良いと。
コードを遡って行くと、
node['postgresql']['client']['packages'].each do |pg_pack| resources("package[#{pg_pack}]").run_action(:install) end
という記述を見つけました。
こいつは postgresql::client レシピでインストールするパッケージを指定する attribute じゃないですか。
というわけで、 .kitchen.yml に以下のように libpq-dev パッケージ(Ubuntu14.04)のインストール指定を追加したところ、無事エラーなく動いてくれました。
attributes: postgresql: client: packages: ["libpq-dev", "postgresql-client-9.3"]
まとめ
- Chefのレシピは上から下にシーケンシャルに実行されるわけじゃない
- 困ったらソースコード読もう
コメント