CL LAB

HOME > CL LAB > Chef > Test Kitchen の Shell Verifier で Serverspec による Cookbook テストを行う #getchef #serverspec

Test Kitchen の Shell Verifier で Serverspec による Cookbook テストを行う #getchef #serverspec

 ★ 16

この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。

2015年12月現在、Test KitchenChef 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 テストの挙動を確認しておきましょう。

busser

この例では 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 から呼び出されています。

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 で使っているものと違いはありません。言い換えると、流用できるということです。

serverspec/spec_helper.rb:

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_HOSTNAMEKITCHEN_USERNAMEKITCHEN_PORTKITCHEN_SSH_KEY の環境変数に Chef Node に SSH ログインするための情報を格納するので、ここで取り出して設定しています。

では、実際に Test Kitchen を実行したログは次の通りです。

% kitchen test
-----> Starting Kitchen (v1.4.2)
-----> Cleaning up any prior instances of <default-ubuntu-1404>
-----> Destroying <default-ubuntu-1404>...
       Finished destroying <default-ubuntu-1404> (0m0.00s).
-----> Testing <default-ubuntu-1404>
-----> Creating <default-ubuntu-1404>...
    :
    (中略)
    :
-----> Converging <default-ubuntu-1404>...
    :
    (中略)
    :
-----> Installing Chef Omnibus (install only if missing)
    :
    (中略)
    :
       Finished converging <default-ubuntu-1404> (1m50.56s).
-----> Setting up <default-ubuntu-1404>...
       Finished setting up <default-ubuntu-1404> (0m0.00s).
-----> Verifying <default-ubuntu-1404>...
       [Shell] Verify on instance=#<Kitchen::Instance:0x00000002e56878> with state={:hostname=>"127.0.0.1", :port=>"2222", :username=>"vagrant", :ssh_key=>"/home/d-higuchi/github/apache2-take/.kitchen/kitchen-vagrant/kitchen-apache2-take-default-ubuntu-1404/.vagrant/machines/default/virtualbox/private_key", :last_action=>"setup"}


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 "<VirtualHost *:8080>"

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 <default-ubuntu-1404> (0m3.13s).
       Finished testing <default-ubuntu-1404> (2m43.59s).
-----> Kitchen is finished. (2m44.09s)
%

あっさりするほど簡単に Serverspec による Cookbook テストが完了しました。

まとめ

Serverspec による Cookbook テストを行うのに、busser と busser-serverspec による方法をおさらいした後、Shell Verifier を使う方法を見てみました。圧倒的に後者が簡単・簡便であることがわかると思います。また InfratasterCapybara のようなテストスイートは 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

CL LABの情報を逃さずチェックしよう!

メールアドレスを登録すると記事が投稿されるとメールで通知します。

メールアドレス: 登録

※登録後メールに記載しているリンクをクリックして認証してください。

Related post