2011/06/14

Chefでサーバのセットアップ・管理作業を楽チンにしよう~実践編その2~


前回紹介したスパムメールがさらに進化して「メアド変えたのでよろしく!」的な内容になってて、この人らPDCA実践してるわ―、と感心してしまったhiroshiです。

「3.レシピを書いたりする」の途中で終わった前回の続きです。

phpのインストールに必要なパッケージをインストールするところで終わっていましたので、次はphpのインストールです。

ここでphpをインストールする条件として
  • インストールされてない
  • 規定のバージョンと違う
  • 想定のコンパイルオプションと違う
場合にインストールし直してね、と定義したいと思います。

主なところはこんな感じです。

{chef-repo}cookbooks/php/recipes/default.rb
# バージョンのチェックを行い、バージョンが想定と違っていたらインストールを実行する
# サーバ稼働中の予期しないアップグレードを防ぐため、/usr/local/src/PHP_VERSION_CHECK_REQUIRED
# というファイルが存在する場合のみ処理が行われる。
buildtool_check_version "php" do
  action :check
  input '|/usr/local/bin/php -v'
  regex /^PHP ([0-9.]+)/
  version node[:php][:version]
  only_if "cat /usr/local/src/PHP_VERSION_CHECK_REQUIRED"
  notifies :create, "cookbook_file[/usr/local/src/#{node[:php][:tarball]}]", :immediately
  notifies :install, "buildtool_make_install[php]", :immediately
  pecl_packages.each do |package_name, install_name|
        if node[:php][:extension][package_name.to_sym] then
        notifies :run, "execute[pecl-install-#{package_name}-force]", :immediately
        end
  end
end

# PHPのコンパイルオプションが変わっている場合はインストールを実行する
# サーバ稼働中の予期しない再コンパイルを防ぐため、/usr/local/src/PHP_VERSION_CHECK_REQUIRED
# というファイルが存在する場合のみ処理が行われる。
# ただしPHPがインストールされていない場合は必ずインストールが実行される。
file "/usr/local/src/PHP_CONFIG_OPTION" do
  content node[:php][:config_option]
  only_if "cat /usr/local/src/PHP_VERSION_CHECK_REQUIRED || ! /usr/local/bin/php -v"
  notifies :create, "cookbook_file[/usr/local/src/#{node[:php][:tarball]}]", :immediately
  notifies :install, "buildtool_make_install[php]", :immediately
end

cookbook_file "/usr/local/src/#{node[:php][:tarball]}" do
  action :nothing
  source node[:php][:tarball]
  mode "0644"
end

buildtool_make_install "php" do
  action :nothing
  tarball node[:php][:tarball]
  srcdir "php-#{node[:php][:version]}"
  config_option node[:php][:config_option]
  notifies :restart, "service[httpd]"
end



4ブロックありますが、それぞれ以下の役割です。
  • バージョンチェック
  • コンパイルオプションチェック
  • インストールファイルの展開
  • インストール

最初のブロックのバージョンチェック部分からいってみます。
buildtool_check_version "php" do

とありますが、buildtool_check_versionは自前で定義したResourceです。
自前定義のResourceです。で終わるのもなんなので、ここでまた横道にそれてbuildtoolの説明をサックリしてみたいと思います。

buildtoolもcookbookのひとつです。
{chef-repo}/cookbook/buildtool/
に定義があります。

上述のbuildtool_check_versionについては、
{chef-repo}/cookbook/buildtool/resources/check_version.rb
actions :check
# バージョンチェックをする Resource の定義

attribute :input, :kind_of => String, :required => true
attribute :regex, :kind_of => Regexp, :required => true
attribute :version, :kind_of => String, :required => true
とresourcesに定義をし

{chef-repo}/cookbook/buildtool/providers/check_version.rb
action :check do
  begin
    versionstring = IO.read(new_resource.input)
    if new_resource.regex =~ versionstring
      version = $1
      if version != new_resource.version
        Chef::Log.info("Version check for #{new_resource.name}: expected=#{new_resource.version}, actual=#{version}")
        new_resource.updated_by_last_action(true)
      end
    else
      Chef::Log.info("Version check failed: '#{versionstring}' is not match #{new_resource.regex}")
      new_resource.updated_by_last_action(true)
    end
  rescue
    Chef::Log.info("Version check failed: #{$!}")
    new_resource.updated_by_last_action(true)
  end
end
とprovidersに実際の動作を記述します。

providersにあるnew_resourceにはresourcesで定義したattributeがあり、その中身は
buildtool_check_version "php" do
  action :check
  input '|/usr/local/bin/php -v' #ココ!
  regex /^PHP ([0-9.]+)/     #ココ!
  version node[:php][:version]  #ココ!
と、利用時に指定した値が入ります。

このあたりの構成が分かれば、check_version.rbが何しているかはrubyがわからなくてもなんとなくわかるかと思います。ぼくもrubyわかんないし。

ちなみに最後の
version node[:php][:version]


{chef-repo}cookbooks/php/attributes/default.rb
default[:php][:version] = "5.x.x"
default[:php][:tarball] = "php-" + default[:php][:version] + ".tar.bz2"
default[:php][:config_option] = "--with-libdir=lib64 \
~後略~
とここに書いた値が基本的には入ります。node[]で取れるの値ですが、設定できる場所は複数箇所あって優先順位があるので気をつけてください。詳しくは公式のこの辺を参照してみてください。

あと、気づいた人もいると思いますが、このbuildtool自体もRecipeの1つなのでbuildtool_check_versionをここで使うには、事前に
include_recipe "buildtool"
しておく必要があります。

と、横道にそれてたら、このブロックの最初の5行まで追えたので次は

only_if "cat /usr/local/src/PHP_VERSION_CHECK_REQUIRED"
ですね。

これはこのブロックのコメントに書いてあるとおりです。

いやー、コメントっていいですね!

ちなみにウチで「変数宣言」とかいうコメント書いたらグラウンド10週か腕立て200回させられるので注意してください。しかもグラウンド探すところからですからけっこうキツイです。


あっ、もうだめ!今日はここまででカンベンしてください!


では、またまた続きは次回に!