LoginSignup
24
24

More than 5 years have passed since last update.

Chefでgitとコンテンツ同期しつつ更新時だけスクリプト実行する

Last updated at Posted at 2013-07-29

この記事は最終更新から1年以上経過しています。 気をつけてね。

ウェブのコンテンツをGitで管理している際に、Webサーバ上でGitリポジトリをチェックしつつ、同期して何かスクリプトを実行する。という手順をChefのレシピで実行してみます。

手順におこす

まずやりたいことをスクリプト(台本)にしましょう。

  1. 初回はgit clone してシェルスクリプトを流す
  2. 定期的にgit ls-remoteして新しいものをチェックする
  3. ls-remote の結果、最新がローカルのリポジトリと違ったらpull
  4. pull があったらシェルスクリプト実行

まあbashで十分な内容です。4なんかは gitのhookを使うやり方もありますね。
ただ従来bashや他のスクリプト型言語で作られている実行手順はレシピにしてchef-applyで実行すると読みやすい内容で十分な結果を得ることができます。

chef-apply用のレシピ

Chef11からCookbook形式にまとめること無くレシピを実行できるchef-applyというユーティリティが追加されました。
先程の台本をレシピにするとこうなります。

apply.rb
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 が呼び出されているのがわかります。

ShellOut(chef-apply)
$ 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 と判断されていますね。

ShellOut(chef-apply)
# 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のリソースが呼ばれているのがわかります。

ShellOut(chef-apply)
$ 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

24
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
24