読者です 読者をやめる 読者になる 読者になる

Ruby on Rails と歩む我が人生

Railsプログラマを目指す漢のRailsとの歩みの記録

Serverspec のインストールと基本的な使い方

Ruby プログラミング Rspec Serverspec

はじめに

Infrastructure as Codeを推進するべく、今更感もありますが、テストにServerspecを使用してみたいと思いますよ!

環境

  • Serverspecを実行する方
  • テストを受ける方

本記事で触れること

  • Serverspecのインストール
  • sample_spec.rbを使ったテスト

SSHでのテストとなります。

インストール&セットアップ

Rubyのインストール

ServerspecはRspecを利用したテスティングフレームワークなので、もちろんRubyのインストールが必須となります。

以下のようなスクリプトでも書いてささっとインストールしてしまいましょう。

#!/bin/bash

# rbenvと関連プラグインのダウンロード
cd /opt
git clone https://github.com/sstephenson/rbenv.git
mkdir -p /opt/rbenv/plugins
cd /opt/rbenv/plugins
git clone https://github.com/sstephenson/ruby-build.git

# .bashrcへのrbenv関連設定追加
grep "rbenv global config" ${HOME}/.bashrc > /dev/null 2>&1
if [ $? -ne 0 ]; then
  echo >> ~/.bashrc
  echo "# rbenv global config" >> ~/.bashrc
  echo 'export RBENV_ROOT="/opt/rbenv"' >> ~/.bashrc
  echo 'export PATH="${RBENV_ROOT}/bin:${PATH}"' >> ~/.bashrc
  echo 'eval "$(rbenv init -)"' >> ~/.bashrc
fi

# Ruby関連モジュールのインストール
yum -y install gcc make openssl-devel libffi-devel ruby-devel readline-devel rubygems sqlite-devel bzip2

# Rubyのインストール
/bin/bash -lc "rbenv install 2.3.0"
/bin/bash -lc "rbenv rehash"
/bin/bash -lc "rbenv global 2.3.0"

Serverspecのインストール

インストール&セットアップ方法

Serverspecのインストール
# gem install serverspec
Serverspec初期セットアップ
# serverspec-init

とすると、こんな画面が出てきます。
※{HOSTNAME}の部分は読み替えて下さい。

Select OS type:

      1) UN*X
      2) Windows

    Select number: 1

    Select a backend type:

      1) SSH
      2) Exec (local)

    Select number: 1

    Vagrant instance y/n: n
    Input target host name: {HOSTNAME}
     + spec/
     + spec/{HOSTNAME}/
     + spec/{HOSTNAME}/sample_spec.rb
     + spec/spec_helper.rb

SSH設定

SSHで接続してテストを実行するため、下記コマンドでSSH鍵をリモートホストへ渡します。

# ssh-copy-id ${HOSTNAME}
/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@${HOSTNAME}'s password: ※パスワードを入力

テストの実行

すでにカレントディレクトリには以下のような構成でファイルが生成されているので、このままテストをしてみます。

spec/
spec/{HOSTNAME}/
spec/{HOSTNAME}/sample_spec.rb
spec/spec_helper.rb

以下のコマンドでテストを実行

# rake spec
(in /root/serverspec/work/20170122)
/opt/rbenv/versions/2.2.3/bin/ruby -I/opt/rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rspec-support-3.5.0/lib:/opt/rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/lib /opt/rbenv/versions/2.2.3/lib/ruby/gems/2.2
.0/gems/rspec-core-3.5.4/exe/rspec --pattern spec/${HOSTNAME}/\*_spec.rb

Package "httpd"
  should be installed (FAILED - 1)

Service "httpd"
  should be enabled (FAILED - 2)
  should be running

Port "80"
  should be listening

Failures:

  1) Package "httpd" should be installed
     On host `${HOSTNAME}'
     Failure/Error: it { should be_installed }
       expected Package "httpd" to be installed
       /bin/sh -c rpm\ -q\ httpd
       package httpd is not installed

     # ./spec/${HOSTNAME}/sample_spec.rb:4:in `block (2 levels) in <top (required)>'

  2) Service "httpd" should be enabled
     On host `${HOSTNAME}'
     Failure/Error: it { should be_enabled }
       expected Service "httpd" to be enabled
       /bin/sh -c chkconfig\ --list\ httpd\ \|\ grep\ 3:on

     # ./spec/${HOSTNAME}/sample_spec.rb:12:in `block (2 levels) in <top (required)>'

Finished in 0.83381 seconds (files took 1.49 seconds to load)
4 examples, 2 failures

Failed examples:

rspec ./spec/${HOSTNAME}/sample_spec.rb:4 # Package "httpd" should be installed
rspec ./spec/${HOSTNAME}/sample_spec.rb:12 # Service "httpd" should be enabled

/opt/rbenv/versions/2.2.3/bin/ruby -I/opt/rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rspec-support-3.5.0/lib:/opt/rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/lib /opt/rbenv/versions/2.2.3/lib/ruby/gems/2.2
.0/gems/rspec-core-3.5.4/exe/rspec --pattern spec/${HOSTNAME}/\*_spec.rb failed

テスト結果の検証

まずは実行されたsample_spec.rbを確認

require 'spec_helper'

describe package('httpd'), :if => os[:family] == 'redhat' do
  it { should be_installed }
end

describe package('apache2'), :if => os[:family] == 'ubuntu' do
  it { should be_installed }
end

describe service('httpd'), :if => os[:family] == 'redhat' do
  it { should be_enabled }
  it { should be_running }
end

describe service('apache2'), :if => os[:family] == 'ubuntu' do
  it { should be_enabled }
  it { should be_running }
end

describe service('org.apache.httpd'), :if => os[:family] == 'darwin' do
  it { should be_enabled }
  it { should be_running }
end

describe port(80) do
  it { should be_listening }
end

これは以下のテストとなっていて、且つOS毎に判定して条件分岐しているテスト内容となっています。

  • Apacheがインストールされているか
  • Apacheが起動しているか
  • Apache自動起動設定されているか
  • Port80がリッスンしているか

テスト内容的にはとあるパッケージソフトに入っているApacheなので、通常のApacheはインストールされていない、且つ、起動はしているが自動起動設定はされておらず、ポートはリッスンしているという正しいテスト結果をなっています。

おわりに

はじめてのServerspecでしたが、色々なテストができそうなので自分なりのベスト・プラクティスを構築してInfrastructure as Codeを実施していければと思います!