opscodeのphpのcookbookを解説してみる
みなさんお料理頑張ってますか?僕は毎日cookbookのrecipeみながらkitchenでknife使ってChef気分です(意味不明)。 今日はopscodeが提供しているphpのcookbookをみて中身を解説したいと思います。 コードはここです。https://github.com/opscode-cookbooks/php(なお、build-essentialとxmlとmysqlのcookbookに依存性がありますので、それぞれ入手してください)
この記事の目的は、標準的なcookbookの構成の把握とopscodeでのcookbookの作り方の紹介とそれを利用したカスタマイズ方法を紹介することです。
ディレクトリ構成
まずソースコードのディレクトリ構成をみてみます。当たり前ですが通常のcookbookのディレクトリ構成と同じです。├── CHANGELOG.md
├── CONTRIBUTING
├── Gemfile
├── LICENSE
├── README.md
├── attributes
├── metadata.rb
├── providers
├── recipes
├── resources
├── templates
└── test
attributes
attributes ではレシピの中で使う変数が定義されています。ここでの設定値は、実際にChef-ClientやChef-Soloを動かすときに値を上書きできます。 attributes/default.rb を抜粋したものが以下になります。lib_dir = kernel['machine'] =~ /x86_64/ ? 'lib64' : 'lib'
default['php']['install_method'] = 'package'
default['php']['directives'] = {}
case node["platform_family"]
when "rhel", "fedora"
default['php']['conf_dir'] = '/etc'
default['php']['ext_conf_dir'] = '/etc/php.d'
default['php']['fpm_user'] = 'nobody'
default['php']['fpm_group'] = 'nobody'
default['php']['ext_dir'] = "/usr/#{lib_dir}/php/modules"
if node['platform_version'].to_f < 6 then
default['php']['packages'] = ['php53', 'php53-devel', 'php53-cli', 'php-pear']
else
default['php']['packages'] = ['php', 'php-devel', 'php-cli', 'php-pear']
end
when "debian"
default['php']['conf_dir'] = '/etc/php5/cli'
default['php']['ext_conf_dir'] = '/etc/php5/conf.d'
default['php']['fpm_user'] = 'www-data'
default['php']['fpm_group'] = 'www-data'
default['php']['packages'] = ['php5-cgi', 'php5', 'php5-dev', 'php5-cli', 'php-pear']
else
default['php']['conf_dir'] = '/etc/php5/cli'
default['php']['ext_conf_dir'] = '/etc/php5/conf.d'
default['php']['fpm_user'] = 'www-data'
default['php']['fpm_group'] = 'www-data'
default['php']['packages'] = ['php5-cgi', 'php5', 'php5-dev', 'php5-cli', 'php-pear']
end
default['php']['url'] = 'http://us.php.net/distributions'
default['php']['version'] = '5.3.10'
default['php']['checksum'] = 'ee26ff003eaeaefb649735980d9ef1ffad3ea8c2836e6ad520de598da225eaab'
default['php']['prefix_dir'] = '/usr/local'
default['php']['configure_options'] = %W{--prefix=#{php['prefix_dir']}
--with-libdir=#{lib_dir}
--with-config-file-path=#{php['conf_dir']}
--with-config-file-scan-dir=#{php['ext_conf_dir']}
(中略)
--with-mysql
--with-mysqli=/usr/bin/mysql_config
--with-mysql-sock
--with-sqlite3
--with-pdo-mysql
--with-pdo-sqlite}
3行目で、このcookbookのデフォルトのインストール手段はパッケージ(Redhat系ならyum Debian系ならapt-get)を使ってインストールすることにしています。このinstall_method
の値は、実際のレシピで読み込むモジュールの切り替えのために使われています。この値を外部から’source’に設定すればtarballをダウンロードして自前でビルドします。
case文の箇所では、OSの種類を判定して、ディレクトリ名やユーザー名やインストールするパッケージを切り分けています。特にrhelファミリーの場合はバージョンが5までの場合と6以降の場合でインストールするパッケージを変えることになっています。よく見て頂くと分かりますが、ここでインストールしているパッケージにマルチバイト文字を扱うのに必須なmbstring用のモジュールが入っていません。したがって外部からこのdefault[‘php’][‘packages’]の値を書き換える(設定する)必要があります。例えば
{ :php => {:packages => ["php", "php-devel", "php-cli", "php-pear", "php-mbstring"] }}
な感じになります。もっとも、このpackagesの値がOSのバージョンによって異なっているため、外部からハードコードな値を設定するのが適切ではない可能性もあります。その場合は別のcookbookを新たに作成した上で、このopscodeのrecipeをinclude_recipeを使って読み込んだ上で、値を上書きするアプローチになります(最後に解説します)。
最後のブロックはtarballをダウンロードしてインストールする場合に使われます。なんかPHPのバージョンが古い気がしますが、この値も外部から書き換えられます。その際は併せてchecksumも指定する必要があります。またconfigureオプションのデフォルト値もここで設定されています。
recipes
recipesの中は以下のような構成になっています。├── default.rb
├── module_apc.rb
├── module_curl.rb
├── module_fileinfo.rb
├── module_fpdf.rb
├── module_gd.rb
├── module_ldap.rb
├── module_memcache.rb
├── module_mysql.rb
├── module_pgsql.rb
├── module_sqlite3.rb
├── package.rb
└── source.rb
phpをインストールしようとした際に最初に参照されるのがdefault.rbです。
include_recipe "php::#{node['php']['install_method']}"
# update the main channels
php_pear_channel 'pear.php.net' do
action :update
end
php_pear_channel 'pecl.php.net' do
action :update
end
このソースはシンプルです。というのも、先ほどattributesで設定されたinstall_method
に応じて違うレシピを読み込んでいるからです。デフォルトではpackage.rbが読み込まれます。phpをソースからインストールするように
{ :php => { :install_method => "source" }}
としている場合は、source.rbが読み込まれます。ちなみにソースからインストールしようとするとlibmcrypt-develが標準のyumレポジトリからインストールできないので、そのままのconfigureオプションだとインストールに失敗します(ヽ(`Д´#)ノ ムキー!!)。
パッケージでのインストールの場合は、package.rbが利用されますがこちらもシンプルです。
node['php']['packages'].each do |pkg|
package pkg do
action :install
end
end
template "#{node['php']['conf_dir']}/php.ini" do
source "php.ini.erb"
owner "root"
group "root"
mode "0644"
end
予めattributesで指定しておいたpackagesの配列の値にしたがってpackageをインストールします。yumかapt-getかは自動で判断されます。その上で、予め用意されているphp.iniのテンプレートに値を埋め込んで配置します。 なお、このディレクトリにあるmodule_*.rb
はphpの様々なモジュールを個別にインストールできるようにしたものです。例えばmemcache用のモジュールをインストールしたければ、runlistの設定などでphp::module_memcache
を追加してください。他も同様です。ただし、このmodule_*.rb
は非推奨モジュールになっておりいずれ廃止されるとのことです(READMEにあります。ご指摘感謝>@iakioさん)
templates
設定ファイルのひな形はtemplatesの中に配置します。templatesディレクトリは以下のような構成です。├── centos
│ └── php.ini.erb
├── debian
│ └── php.ini.erb
├── default
│ ├── extension.ini.erb
│ └── php.ini.erb
├── redhat
│ └── php.ini.erb
└── ubuntu
└── php.ini.erb
どのディレクトリの中のテンプレートを利用するかは、設定対象のOSによって判断されます。該当するものがない場合はdefaultの中のものが利用されます。CentOSの場合、変数が自動で代入される箇所は以下になります。
extension_dir = "< %= node['php']['ext_dir'] %>"
< % node['php']['directives'].each do |directive, value| -%>
< %= "#{directive}=\"#{value}\"" %>
< % end -%>
最初の行は拡張モジュールを配置するディレクトリで、/usr/lib/php/modulesまたは/usr/lib64/php/modules になります。このパスもattributesの中で設定されます。 またattributesの中でdefault[‘php’][‘directives’] = {}と設定されていますが、この値を外部から指定すればそれが、 キー=“値"の形でphp.iniに書き込まれます。
resourcesとproviders
resourceとproviderによって独自の処理を追加することができます。 ここでは、pearとpear_channelという2つが定義されています。中身はソースを見て頂くと分かりやすいですが、実際にサーバ上でおこなうコマンドをゴリゴリと書いています。 それによってrecipes/default.rbにあるphp_pear_channel 'pear.php.net' do
action :update
end
のような処理を実行することができます。また自分で
php_pear "PhpDocumentor" do
preferred_state "stable"
version "1.4.3"
action :install
end
のような処理を書くこともできます(他のcookbookでやる場合はinclude_recipeでここで紹介しているphpのcookbookを設定する必要はあります)
ちょっと応用
ここで紹介したopscodeのphpのcookbookを使ってさらに自分用にカスタマイズする方法を紹介します。 まずは、opscodeのcookbookがおいてあるのと同じ階層に新しいcookbookを作ります。knifeコマンドを使う場合はこんな感じ (cookbookの名前はかなり適当ですw)knife cookbook create oreore_php -o .
次に依存関係を定義するために、metadeta.rbを編集します。追加するのは最終行です。 これによってphpのcookbookで定義されているresourceを含めて全て利用可能です。
name 'oreore_php'
maintainer 'ryuzee'
maintainer_email 'ryuzee@gmail.com'
license 'All rights reserved'
description 'Installs/Configures oreore_php'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '0.1.0'
depends "php"
次にrecipeを作成(recipes/default.rb)します。中身は以下のようにしてください (冒頭のファイルコメントは省略)。
include_recipe "php"
そして自分用のattributeの設定(attributes/default.rb)をします。今回はデフォルトのタイムゾーンを東京にしたいのと、インストールするパッケージを増やしたいので以下のようにします。
default['php']['directives'] = { "date.timezone" => "Asia/Tokyo" }
case node["platform_family"]
when "rhel", "fedora"
if node['platform_version'].to_f < 6 then
default['php']['packages'] = ['php53', 'php53-devel', 'php53-cli', 'php53-mbstring', 'php-pear']
else
default['php']['packages'] = ['php', 'php-devel', 'php-cli', 'php-mbstring', 'php-pear']
end
end
以上で準備が完了です。作ったoreore_phpのcookbookを適用してみてください(Vagrant+Chef-soloが簡単です)
アジャイルコーチングやトレーニングを提供しています
株式会社アトラクタでは、アジャイル開発に取り組むチーム向けのコーチングや、認定スクラムマスター研修などの各種トレーニングを提供しています。ぜひお気軽にご相談ください。
詳細はこちら