knife-solo 0.2.0 で rsync エラーによって苦しまないためのたったひとつの方法

結論としては、0.2.0 以降のバージョンを使いましょう。今現在は github から持ってきて使いましょう、ということです(挨拶)

昨日、Jenkins cookbook のバグ潰しをしていたら、@chiastolite さんからこんなことを教えてもらいました。

手元の環境では発生しなかったので、どういうことだろう? と思って調べてみたところ、knife-solo 0.2.0 が原因でした。
何度か試行錯誤していたらこんなエラーが出てきました*1

$ knife solo cook -p 2222 -i ~/.vagrant.d/insecure_private_key vagrant@localhost
Checking Chef version...
rsync: delete_file: unlink(runit-2.1.1/runit.spec) failed: Permission denied (13)
rsync: delete_file: unlink(runit-2.1.1/runit-2.1.1-term-hup-option.patch) failed: Permission denied (13)
rsync: delete_file: unlink(runit-2.1.1/runit-2.1.1-runsvdir-path-cleanup.patch) failed: Permission denied (13)
rsync: delete_file: unlink(runit-2.1.1/runit-2.1.1-etc-service.patch) failed: Permission denied (13)
rsync: delete_file: unlink(runit-2.1.1/build.sh) failed: Permission denied (13)
rsync: delete_file: unlink(runit-2.1.1/README.markdown) failed: Permission denied (13)
cannot delete non-empty directory: runit-2.1.1
rsync error: some files could not be transferred (code 23) at /SourceCache/rsync/rsync-42/rsync/main.c(992) [sender=2.6.9]
ERROR: RuntimeError: Failed to launch command rsync -rl  --rsh="ssh vagrant@localhost -i /Users/tkomiya/.vagrant.d/insecure_private_key -p 2222" --delete --exclude revision-deploys --exclude tmp --exclude '.*'  ./ :/tmp/chef-solo

このエラーについて細かく調べていくと、こんな動きだということが分かりました。

  1. knife solo init で生成される solo.rb では file_cache_path が /tmp/chef-solo になっている
  2. knife solo cook を実行すると、rsync を使って /tmp/chef-solo にファイルを転送する
  3. 引き続き、root 権限で chef-solo が実行される
  4. run_list に一時ファイルを使う cookbook を含む場合、キャッシュファイルが /tmp/chef-solo 以下に作成される。もちろんオーナーは root。
  5. knife solo cook が正常に終わる

こんなかんじで、初回の実行は正常に終わるのですが、もう一度 knife solo cook を実行すると動きが変わります。

  1. もう一度 knife solo cook を実行する
  2. knife solo cook は rsync を使って /tmp/chef-solo にファイルを転送しようとする
  3. --delete オプションが指定されてるけど、root 所有のキャッシュファイルが削除できない
  4. _人人人人人人_
  5. > 突然の死 <
  6.  ̄Y^Y^Y^Y^Y ̄

というわけで、キャッシュファイルを作成する cookbook が含まれていると、
二度と knife solo cook が実行できなくなるという謎の状態に陥ることが分かりました。

かなりクリティカルな問題なので、github 上にある最新版では直っているだろうと調べてみたところ、
当然ながら(?) 既にこの問題は解決していました。

ディレクトリ構造が代わった knife-solo 0.3.0 (未リリース)

どう解決しているのか、というとディレクトリ構造がガラッと変わっています。
これまでは chef-solo を実行するディレクトリとして /tmp/chef-solo を利用していたのですが、
0.3.0 では ~/chef-solo に変更になっています。
また、solo.rb では file_cache_path が明示的に指定されていないため、
デフォルト値である /var/chef/cache が利用されます。
追記(4/18 11:20) 0.3.0 からは設定ファイルが solo.rb から .chef/knife.rb に変更されました。solo.rb は対象ホスト内で生成されるように切り替わっています。要注意です。

ここで構成が変わったのが聞いており、cookbooks などの構成ファイル群を転送する際にエラーが発生しなくなっていました。

というわけで、結論としては、0.2.0 以降のバージョンを使いましょう。
今現在は 0.3.0 はリリースされていないので、github から持ってきて使いましょう。

*1:使っている cookbook は github の jenkins cookbook とその依存 cookbooks です