Chef Cookbook 開発環境の近況

Chef の高い学習コストを払い終えたのかやっとしっくりき始めたけど、Cookbook の開発環境についてはまだまだしっくりには程遠い。いまのところこんな感じというのをシェア。

Vagrant でたてたローカルの VM で Cookbook でやりたいことを直接試して、いい感じになったら serverspec でテストを書いて通るようになったら vagrant-sahara でロールバック後、Cookbook に置き換える感じです。ServerSpec でのテストはきれいにかけて Chef 依存もなく気に入っているけど、attributes の値を変えたときに正しく反映されるかなどは書けず、他のテストツールも合わせて使わないとなあと感じてる。test-kitchen も気になってて見た感じはこのスタイルを一枚の yaml にまとめられる程度の印象で触れていない。

不満はとにかく Vagrant が遅いこと。VirtualBox が遅いのかと思い、vagrant-lxc を試してみたけどあまり変わらなかった(バグってるのでそのままは使えない。VM へのプロビジョンがもう少しでも高速化できれば Guard も使っていきたいけど現状では難しい印象。
serverspec-init で生成される spec_helper.rb では素直に vagrant ssh-config を毎回実行しているけど、これに20秒程度かかっていてどうしようもない感じだったので以下のように修正している。これですぐテストが走るようにはなる。

require 'serverspec'
require 'pathname'
require 'net/ssh'

include Serverspec::Helper::Ssh
# include Serverspec::Helper::DetectOS
# DetectOS をやめて決め打ちにすることで数秒短縮できる
include Serverspec::Helper::Debian

SSH_CONFIG_FILE = '.vagrant-ssh-config'

...

      # `vagrant ssh-config` がとてつもなく遅いので結果をキャッシュしている
      # Multi-VM でうまくいくかは試していない
      unless File.exists?(SSH_CONFIG_FILE)
        system("vagrant ssh-config > #{SSH_CONFIG_FILE}")
      end
      config = File.open(SSH_CONFIG_FILE).read
      if config != ''
        config.each_line do |line|
          if match = /HostName (.*)/.match(line)
            c.host = match[1]
          elsif  match = /User (.*)/.match(line)
            user = match[1]
          elsif match = /IdentityFile (.*)/.match(line)
            options[:keys] =  [match[1].gsub(/"/,'')]
          elsif match = /Port (.*)/.match(line)
            options[:port] = match[1]
          end
        end
      end