こしごぇ(B)

旧:http://d.hatena.ne.jp/koshigoeb/

Chef 実践入門(3) テスト

Chef実践入門 ~コードによるインフラ構成の自動化 (WEB+DB PRESS plus)

Chef実践入門 ~コードによるインフラ構成の自動化 (WEB+DB PRESS plus)

写経しつつ現状にあわせて修正なども。継続的インテグレーションは略。

Test Kitchen

  • CentOS 5.10(x86_64), 6.5(x86_64) で動作
  • analog コマンドが /usr/bin/analog に配置され実行可能
  • Analog のバージョンは 6.0

クックブック作成

$ knife cookbook create analog -o .
$ cd analog

レシピ

$ cat <<\EOF > recipes/default.rb
case node[:platform]
when 'centos'
  platform_version = node[:platform_version].to_f

  if platform_version >= 6.0
    rpmfile = 'analog-6.0.4-1.x86_64.rpm'
  elsif platform_version >= 5.0
    rpmfile = 'analog-6.0.4-1.el5.i386.rpm'
  else
    raise 'This recipe can not be applied to this environment!!'
  end

  remote_file "#{Chef::Config[:file_cache_path]}/#{rpmfile}" do
    source "http://www.iddl.vt.edu/~jackie/analog/#{rpmfile}"
  end

  package 'perl' do
    action :install
  end

  package 'analog' do
    action :install
    source "#{Chef::Config[:file_cache_path]}/#{rpmfile}"
    provider Chef::Provider::Package::Rpm
  end
end
EOF

Test Kitchen インストール

$ cat <<EOF > Gemfile
source 'https://rubygems.org'

gem 'test-kitchen', '~> 1.2.0'
gem 'kitchen-vagrant', group: :integration
gem 'berkshelf'
EOF
$ bundle
$ bundle exec kitchen init
      create  .kitchen.yml
      create  test/integration/default
$ vi .kitchen.yml
$ cat .kitchen.yml
---
driver:
  name: vagrant

provisioner:
  name: chef_solo

platforms:
  - name: centos-6.5
  - name: centos-5.10

suites:
  - name: default
    run_list:
      - recipe[analog::default]
    attributes:

テスト

Bats でテストを記述

$ cat <<\EOF test/integration/default/bats/basic_test.bats
@test "ファイルが正しい場所にインストールされている" {
    ls -la /usr/bin/analog
}

@test "ファイルに実行権限がある" {
    test -x /usr/bin/analog
}

@test "ファイルは正しいバージョンである" {
    /usr/bin/analog 2>/dev/null | grep "analog 6.0"
}
EOF

minitest でテストを記述

$ cat <<\EOF > test/integration/default/minitest/analog_spec.rb
require 'minitest/autorun'

describe 'Winning' do
  it 'should exist' do
    assert File.exists? '/usr/bin/analog'
  end

  it 'should be executable' do
    assert File.executable? '/usr/bin/analog'
  end

  it 'shouls be right version' do
    assert system("/usr/bin/analog 2>/dev/null | grep 'analog 6.0' 1>/dev/null")
  end
end
EOF

serverspec でテストを記述

$ cat <<\EOF > test/integration/default/serverspec/localhost/default_spec.rb
require 'serverspec'

include Serverspec::Helper::Exec
include Serverspec::Helper::DetectOS

RSpec.configure do |c|
  c.before :all do
    c.os = backend(Serverspec::Commands::Base).check_os
  end
  c.path = '/sbin:/usr/sbin'
end

describe package('analog') do
  it { should be_installed }
end

describe file('/usr/bin/analog') do
  it { should be_file }
  it { should be_mode 755 }
end

describe command("/usr/bin/analog 2>/dev/null | grep 'analog 6.0'") do
  it { should return_exit_status 0 }
end
EOF

テストを実行

$ bundle exec kitchen test

kitchen test は以下のコマンドを組み合わせたもの。

  1. kitchen create
  2. kitchen setup
  3. kitchen converge
  4. kitchen verify
  5. kitchen destroy

毎回インスタンス作成から実行すると時間がかかるので、converge -> verify を繰り返すと良いとの事。

  • --destroy=never
  • --destroy=always