Test Kitchen の Shell Verifier で Serverspec による Cookbook テストを行う #getchef #serverspec
★ 23
2015年12月現在、Test Kitchen で Chef Cookbook のテストを行うのは busser-serverspec を媒介とした Serverspec がデファクトスタンダードとなっています(RubyGems.org 調べ: busser-serverspec:132万DL, busser-bats:28万DL, busser-rspec:7万DL)。
本稿では、Cookbook テストを行うための媒介として従来の busser 機構の代わりに、2015年7月に公開された Shell Verifier (2015年12月に Test Kitchen 本体にマージ)を用いる方法を見てみます。
busser のおさらい
Test Kitchen + busser + busser-serverspec + Serverspec による Cookbook テストの挙動を確認しておきましょう。
この例では Kitchen Driver に Vagrant (VirtualBox)、Kitchen Provisioner に chef-solo を使うとします。他の Driver や Provisioner でも変わらないでしょう。テストケースは Serverspec で作っているとします。
まず、Test Kitchen を実行すると、Vagrant (VirtualBox) を用いて、Cookbook を適用するための Chef Node を作成します。そちらに Cookbook を転送し、Chef-Solo で Node に適用・収束を行います。
収束が完了したら、Test Kitchen は RubyGems.org から busser gem などを Chef Node にインストールします。インストールされた busser は、テストケースが Serverspec で作られていることをディレクトリから判別し、RubyGems.org から busser-serverspec gem を Chef Node にインストールします。Test Kitchen は Chef Node にテストケースをアップロードし、busser-serverspec は localhost すなわち Chef Node に対して Serverspec を実行します。
これで、Serverspec による Chef Cookbook のテストを実現しています。
busser 機構によるテストの問題点として、次が挙げられるでしょう。
- busser や busser-serverspec を毎回 Chef Node に RubyGems.org から取得してインストールするため時間がかかる、あるいはネットワークの疎通を気にする必要がある。
- テストを busser 下という特殊な状況で実行するため、バグか仕様かわからない現象に悩まされる(issues)。または操作に自由が効かない(Pull Requests)。
busser は、もともとネットワーク機能を持たないようなテストスイートでも Cookbook のテストが行えるように、Chef Node 内に隔離環境を作ってテストを行う仕組みなので、ある意味仕方のない面があるかもしれません。
一方、Serverspec は SSH をはじめとしてさまざまなネットワーク機能を備えているため、ホスト側で Serverspec を実行してやれば、busser を仲介役に置く必要がありません。これを実現するのが Shell Verifier です。
Shell Verifier とは
Test Kitchen + Shell Verifier + Serverspec による Cookbook テストの挙動を確認しておきましょう。
Verifier とは Test Kitchen 1.4.0 で導入された仕組みで、Cookbook の Verify ステップを行う部位をプラガブルにしたものです。実は busser もこの Verifier から呼び出されています。
この例でも同様に、Kitchen Driver に Vagrant (VirtualBox)、Kitchen Provisioner に chef-solo を使うとします。他の Driver や Provisioner でも変わらないでしょう。テストケースは Serverspec で作っているとします。
ここでもやはり Test Kitchen を実行すると、Vagrant (VirtualBox) を用いて、Cookbook を適用するための Chef Node を作成します。そちらに Cookbook を転送し、Chef-Solo で Node に適用・収束を行います。
収束が完了したら、Test Kitchen は .kitchen.yml にて Shell Verifier として指定したコマンドを実行します。ここでは Serverspec (rspec) を実行したとしましょう。Serverspec は Chef Node に対して SSH 接続、すなわちリモートホストに対してテストケースを実行します。
この方法だと、収束した Chef Node は(Cookbook テストが終われば破棄するとはいえ)クリーンな状態に置かれ、ローカルマシン側は既にインストールされているであろう Serverspec を Cookbook テストのたびに再インストールする必要もありません。
Serverspec による Cookbook テストを行うならば、busser + busser-serverspec に比べて、Shell Verifier がいかに単純に行えるかがわかると思います。
Shell Verifier で実際に Cookbook テストを行う
では実際に Shell Verifier を使ったテストを行います。Cookbook は こちら です。テストの前に、Shell Verifier に具体的な部位を見ていきましょう。
.kitchen.yml:
verifier:
name: shell
command: rspec -c -f d -I serverspec serverspec/apache2-take_spec.rb
Verify ステップで Shell Verifier を使い、どのようなコマンドを実行するか指定しています。
serverspec/apache2-take_spec.rb:
require 'spec_helper'
%w{ apache2 git-core curl unzip }.each do |i|
describe package( i ) do
it { should be_installed }
end
end
:
(中略)
:
何の変哲もない Serverspec のテストケースです。busser で使っているものと違いはありません。言い換えると、流用できるということです。
require 'serverspec'
set :backend, :ssh
options = Net::SSH::Config.for(host)
options[:host_name] = ENV['KITCHEN_HOSTNAME']
options[:user] = ENV['KITCHEN_USERNAME']
options[:port] = ENV['KITCHEN_PORT']
options[:keys] = ENV['KITCHEN_SSH_KEY']
set :host, options[:host_name]
set :ssh_options, options
set :env, :LANG => 'C', :LC_ALL => 'C'
ここでは Serverspec が Chef Node に SSH ログインするための設定を行っています。
Shell Verifier が KITCHEN_HOSTNAME、KITCHEN_USERNAME、KITCHEN_PORT、KITCHEN_SSH_KEY の環境変数に Chef Node に SSH ログインするための情報を格納するので、ここで取り出して設定しています。
では、実際に Test Kitchen を実行したログは次の通りです。
% kitchen test
-----> Starting Kitchen (v1.4.2)
-----> Cleaning up any prior instances of
-----> Destroying
Finished destroying
-----> Testing
-----> Creating
:
(中略)
:
-----> Converging
:
(中略)
:
-----> Installing Chef Omnibus (install only if missing)
:
(中略)
:
Finished converging
-----> Setting up
Finished setting up
-----> Verifying
[Shell] Verify on instance=#
Package "apache2"
should be installed
Package "git-core"
should be installed
Package "curl"
should be installed
Package "unzip"
should be installed
Service "apache2"
should be enabled
should be running
Port "8080"
should be listening
File "/etc/apache2/ports.conf"
should be file
should be owned by "root"
should be grouped into "root"
should be mode 644
File "/etc/apache2/sites-available/default.conf"
should be file
should be owned by "root"
should be grouped into "root"
should be mode 644
File "/etc/apache2/ports.conf"
should contain "NameVirtualHost *:8080"
should contain "Listen 8080"
File "/etc/apache2/sites-available/default.conf"
should contain "
File "/etc/apache2/sites-enabled/default.conf"
should be linked to "../sites-available/default.conf"
File "/var/www/index.html"
should be file
should contain "Welcome to my top page"
File "/var/www/img"
should be directory
Finished in 1.07 seconds (files took 1.98 seconds to load)
22 examples, 0 failures
Finished verifying
Finished testing
-----> Kitchen is finished. (2m44.09s)
%
あっさりするほど簡単に Serverspec による Cookbook テストが完了しました。
まとめ
Serverspec による Cookbook テストを行うのに、busser と busser-serverspec による方法をおさらいした後、Shell Verifier を使う方法を見てみました。圧倒的に後者が簡単・簡便であることがわかると思います。また Infrataster や Capybara のようなテストスイートは Shell Verifier から呼び出すのが有効と思います。
率直に言って、busser による回りくどい方法を使わずに Serverspec で Cookbook がテストできるため、作者でありながらすっかり busser-serverspec を使わなくなりました。Add shell verifier Pull Request や Chef Meetup ( featuring Docker ) の質疑応答にてマージに向けて積極的に動いたのも、busser-serverspec を使わなくてもよくなることのメリットがあまりにも大きかったためです。
この場を借りて、Shell Verifier 作者の Yukihiko SAWANOBORI さんをはじめ、筆者以外のマージに尽力してくださった方に感謝します。
参考文献
CL LAB Mail Magazine
メールアドレス: 登録
※登録後メールに記載しているリンクをクリックして認証してください。