猫と一緒にガジェットライフ♪ムチャ(@mutoj_rdm821)です。
Chefというのは、サーバー(主にLinux)の設定やミドルウェアのインストール及び構成などをRubyのコードで記述して自動化するプラットフォームです。今回はピンポイントではまった事を書くだけなので、もう少し詳しく知りたい方は以下の記事をご覧下さい。完璧にまとまっています。
→chef-solo - Chefを読んで実行するための全知識 – Qiita
今回ご紹介するのは、databaseクックブックを使ってPostreSQLを構成しようとしたときにはまった事とその解決方法です。しかしながら、確認したところこの問題は2014年5月5日時点で既に修正されている(後述)ので、今だと発生しないと思います。とはいえ、せっかくなので記事にしておきます。
databaseクックブックとは
既にインストールされているPostgreSQL、MySQL、SQLServerに対して、ユーザーの追加・削除・権限付与、データベースの作成・削除、SQLの投入を行う事ができます。
それぞれのセットアップについては個々にクックブックが配布されています。
CentOS上でPostgreSQLを構成しようとするとエラー
レシピを書いて実行すると、以下のエラーが発生しました。
Chef::Exceptions::Package: packagelibpq-dev had an error: Chef::Exceptions::Package: No version s pecified, and no candidate version available for libpq-dev
libpq-devというのは、Debian用のパッケージです。なぜかCentOSなのにこれを入れようとして、存在しないので落ちてしまっていました。
詳しく追っていくと、内部で別の”postgresql”というクックブックを呼び出していて、その中のrecipes/ruby.rbでエラーが起きているようでした。以下はchef(chef-solo)の出力をdebugにした時の内容です。
================================================================================
Error executing action `install` on resource 'package[libpq-dev]'
================================================================================
SystemExit
----------
exit
Cookbook Trace:
---------------
/tmp/chef-repo/site-cookbooks/postgresql/recipes/ruby.rb:54:in `rescue in from_file'
/tmp/chef-repo/site-cookbooks/postgresql/recipes/ruby.rb:24:in `from_file'
/tmp/chef-repo/cookbooks/database/recipes/postgresql.rb:20:in `from_file'
/tmp/chef-repo/xxxxxxxxxxxxxxxxxxxx/recipes/database.rb:14:in `from_file'
Resource Declaration:
---------------------
# In /tmp/chef-repo/site-cookbooks/postgresql/recipes/ruby.rb
~略~
Compiled Resource:
------------------
# Declared in /tmp/chef-repo/site-cookbooks/postgresql/recipes/ruby.rb:52:in `rescue in from_file'
package("libpq-dev") do
action [:nothing]
retries 0
retry_delay 2
package_name "libpq-dev"
cookbook_name :postgresql
recipe_name "ruby"
end
================================================================================
Recipe Compile Error in /tmp/chef-repo/xxxxxxxxxxxxxx/recipes/database.rb
================================================================================
SystemExit
----------
package[libpq-dev] (postgresql::ruby line 52) had an error: SystemExit: exit
Cookbook Trace:
---------------
47: resources("package[#{pg_pack}]").run_action(:install)
48: end
49: require 'rbconfig'
50:
51:
52: package "libpq-dev" do
53: action :nothing
54>> end.run_action(:install)
55:
56: begin
57: chef_gem "pg"
58: rescue Gem::Installer::ExtensionBuildError => e
59: # Are we an omnibus install?
60: raise if RbConfig.ruby.scan(%r{(chef|opscode)}).empty?
61: # Still here, must be omnibus. Lets make this thing install!
62: Chef::Log.warn 'Failed to properly build pg gem. Forcing properly linking and retrying (omnibus fix)'
63: gem_dir = e.message.scan(%r{will remain installed in ([^ ]+)}).flatten.first
Relevant File Content:
----------------------
/tmp/chef-repo/site-cookbooks/postgresql/recipes/ruby.rb:
~略~
最後のCookbook Trace:の所を見ると、確かにlibpq-devを入れようとして落ちてます。Chefでは実行されているOSを判別することもできるのですが、ここでは判定が行われていませんでした。
※この問題自体は1年以上前に修正がコミットされていたようですが、mastarにマージされたのが2週間ほど前だったようです(;´∀`)
どう対処したか
エラーの部分だけを見ても分かりませんが、この前にpostgresqlを操作するためのRubyのライブラリ(gem)の”pg”をrequireしようとして、失敗した場合(インストールされていない場合)に該当コードに到達することが分かりました。
なので、自分で作ったレシピの方で先にpgをインストールしてしまえばOKでした。
しかし、このpgというgemはネイティブコードを含んでいて、インストール時にコンパイルが必要となります。そのためにオプションを与えてやらないといけません。具体的には”pg-config”というコマンドへのパスです。
書いたレシピが以下の内容です。
pg_config_path = "/usr/pgsql-#{node['postgresql']['version']}/bin/pg_config"
require 'rbconfig'
gem_package "pg" do
gem_binary "#{RbConfig::CONFIG['bindir']}/gem"
options("-- --with-pg-config=#{pg_config_path}")
action :install
end
パスの探し方は、別の何かのクックブックを参考にしてこのようにしました。
gem_packageリソースのオプションで、gem_binaryとoptionsを指定しています。
「先にpg入れておけばいいじゃん」と思うかもしれませんが、chefが実行に使うRubyの環境は専用に保持していて、普通にログインしてgemコマンドでインストールしても効果はありません。まあそのchef用環境(CentOSだと/var/opt/chef/以下だったか)に対してインストールすればよいのですが、それだとchefで構成する意味が無くなってしまいます。
Chefの公式コミュニティで配布されているクックブックはこうした小さなバグがあって、しかも長いこと放置されているものもあったりで大変でした。
次回はappilcation_javaというクックブックで遭遇した問題について書こうと思います。
それではみなさまよきガジェットライフを(´∀`)ノ



