はじめに
Infrastructure as Codeを推進するべく、今更感もありますが、テストにServerspecを使用してみたいと思いますよ!
環境
- Serverspecを実行する方
- ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]
- CentOS Linux release 7.2.1511 (Core)
- テストを受ける方
- ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]
- CentOS release 6.8 (Final)
本記事で触れること
- 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を実施していければと思います!