Serverspecでインフラテストを自動化したのは良いんだけど、 RSpecのテスト結果でOKと出ただけで本当に信用して良いのか……? という心配性の人のために、Serverspecが内部でどんなコマンドを打って、どんな出力を見て結果を判定したかを記録に残してみます。
SSHバックエンドかつcommand
,file
,service
リソースでしか試していません。SSHバックエンドなら大体大丈夫だと思いますが……
手順
普通に
serverspec-init
でSSHを選んでサンプルを作成した後、以下のファイルを作成し、
./formatters/serverspec_audit_formatter.rb
require 'rspec/core/formatters/documentation_formatter'
require 'specinfra'
require 'serverspec/version'
require 'serverspec/type/base'
require 'serverspec/type/command'
require 'fileutils'
class ServerspecAuditFormatter < RSpec::Core::Formatters::DocumentationFormatter
RSpec::Core::Formatters.register self, :example_group_started,
:example_passed, :example_pending, :example_failed
def initialize(output)
super
@seq = 0
end
def example_group_started(notification)
@seq = 0 if @group_level == 0
super
end
def example_passed(notification)
save_evidence(notification.example)
super
end
def example_pending(notification)
save_evidence(notification.example)
super
end
def example_failed(notification)
save_evidence(notification.example, notification.exception)
super
end
def save_evidence(example, exception=nil)
# 以下のように、トップレベルに結果ディレクトリ名として使う名称を指定する前提
# describe "テストケース1" do
# describe command('hostname') do
# its(:stdout) { should ... }
# end
# end
name = example.example_group.top_level_description
# 出力先ディレクトリを {ホスト名}/{テスト名}/{連番} で作成
host = ENV['TARGET_HOST'] || Specinfra.configuration.host
@seq += 1
d = "audit/#{host}/#{name}/#{@seq}"
FileUtils.mkdir_p(d)
# 実行内容をファイル出力
Dir.chdir(d) do
# 実行コマンド
File.write('command.txt', example.metadata[:command])
# 標準出力
File.write('stdout.txt', example.metadata[:stdout]) if example.metadata[:stdout]
# RSpecのエラーメッセージ
File.open('exception.txt', 'w') {|f| f.puts exception.message } if exception
# 標準エラー出力と終了ステータス(commandリソースのみ)
resource = example.metadata[:described_class]
if resource.kind_of? Serverspec::Type::Command
File.write('stderr.txt', resource.stderr) unless resource.stderr.to_s.empty?
File.write('exit_status.txt', resource.exit_status)
end
end
end
end
.rspec ファイルも以下のように変更します。
.rspec
--color
--format ServerspecAuditFormatter
--require ./formatters/serverspec_audit_formatter.rb
出力結果
この状態で以下のようなテストを流すと……
./spec/host1/sample_spec.rb
require 'spec_helper'
describe 'テストケース1' do
describe command('hostname') do
its(:stdout) { should match /^host1$/ }
end
end
./audit/host1/テストケース1/1/ ディレクトリに、
command.txt
sudo -p 'Password: ' /bin/sh -c hostname
stdout.txt
host1<改行>
のような結果が保存されます。