この記事は最終更新から1年以上経過しています。 気をつけてね。
ウェブのコンテンツをGitで管理している際に、Webサーバ上でGitリポジトリをチェックしつつ、同期して何かスクリプトを実行する。という手順をChefのレシピで実行してみます。
手順におこす
まずやりたいことをスクリプト(台本)にしましょう。
- 初回はgit clone してシェルスクリプトを流す
- 定期的にgit ls-remoteして新しいものをチェックする
- ls-remote の結果、最新がローカルのリポジトリと違ったらpull
- pull があったらシェルスクリプト実行
まあbash
で十分な内容です。4なんかは gitのhookを使うやり方もありますね。
ただ従来bashや他のスクリプト型言語で作られている実行手順はレシピにしてchef-apply
で実行すると読みやすい内容で十分な結果を得ることができます。
chef-apply用のレシピ
Chef11からCookbook形式にまとめること無くレシピを実行できるchef-apply
というユーティリティが追加されました。
先程の台本をレシピにするとこうなります。
bash 'after_sync_script' do
action :nothing
flags '-x'
code <<-__EOL__
install -o www -g www -m 0600 /usr/local/project/index.html /usr/local/www/index.html
install -o www -g www -m 0600 /usr/local/project/title.jpg /usr/local/www/title.jpg
__EOL__
end
git '/usr/local/project' do
action :sync
repository 'file:///root/git_work'
notifies :run, 'bash[after_sync_script]'
end
リソース:bash 'after_sync_script'
action :nothing
がポイントです、通常何もしませんが他から呼べるようにリソースとして定義だけしておきます。
中身はgitを同期したあとに実行したい、インストールスクリプトのサンプルですね。
リソース:git '/usr/local/project'
gitのリモートリポジトリを/usr/local/project
にも置きましょうというリソースです。
action :sync
なので同期ですね、リモート側に更新があったらpull(fetch&checkouy)してくれます。
最後にあるnotifies :run, 'bash[after_sync_script]'
で、このリソースに更新があった場合 先程のbashを:run
してくれということを記述しています。
実行の様子
初回
最初の実行なのでローカルのリポジトリ、/usr/local/project
ディレクトリはありません。
gitのcloneとcheckoutが実行されて、 bash[after_sync_script] action run
が呼び出されているのがわかります。
$ chef-apply apply.rb
Recipe: (chef-apply cookbook)::(chef-apply recipe)
* bash[after_sync_script] action nothing (skipped due to action :nothing)
* git[/usr/local/project] action sync
- clone from file:///root/git_work into /usr/local/project
- checkout ref 4518501d9787c68a94150be5065ed62a7db103d3 branch HEAD
* bash[after_sync_script] action run
- execute "bash" -x "/tmp/chef-script20130729-67139-2jdojy"
git更新なしの2回目以降
リモートリポジトリに変更がないので、なにも起こりません。
リソースgit[/usr/local/project]
が up to date と判断されていますね。
# chef-apply apply.rb
Recipe: (chef-apply cookbook)::(chef-apply recipe)
* bash[after_sync_script] action nothing (skipped due to action :nothing)
* git[/usr/local/project] action sync (up to date)
gitに更新があった場合
gitの更新分をsyncして、bashのリソースが呼ばれているのがわかります。
$ chef-apply apply.rb
Recipe: (chef-apply cookbook)::(chef-apply recipe)
* bash[after_sync_script] action nothing (skipped due to action :nothing)
* git[/usr/local/project] action sync
- set up remote tracking branches for file:///root/git_work at origin
- fetch updates for origin
* bash[after_sync_script] action run
- execute "bash" -x "/tmp/chef-script20130729-76349-1yi7vfw"
あとはchef-applyをcronにでも放り込んでおけばOKですね。
おわりに
bashのややこしいシェルスクリプトをchef-applyで置き換えるとスッキリするケースは結構あるんじゃないでしょうか。メンテする行数が少なくなれば品質の低下も抑えられるのでお奨めです。
なお今回紹介したgit リソースには沢山のオプションがあり、単純にsyncするほか.gitを除去したり、ブランチを指定したりとそこそこ色々なノウハウをそのままレシピにすることができるよう工夫がされています。
Git: Opscode Docs
http://docs.opscode.com/resource_git.html