• このエントリーをはてなブックマークに追加

【serverspec】エビデンス(実行結果)をファイルに残す方法

  • このエントリーをはてなブックマークに追加

zaco muraです。
最近、新システムのリリースに向けて検証をしているんですが、1ヶ月~2ヶ月とけっこう長い時間かかってしまいます。しかし忙しい現代人にそんな稼働は難しい。。。ということで検証の自動化に取り組んでいます。

背景

いろいろ調べたところ、Serverspecが流行っている?らしいという噂を聞いたので使ってみることに。
(自分はrubyに詳しくないので)苦労しつつも検証コードを書いてみて動くようになったものの、気になることが。

問題点

OKの場合のコマンド実行結果が表示されないこと。(↓こんな感じ)
20150421
つまり、”どういう実行結果だったからOKと判断したのか”が後から見るとわからないことです。
(もちろん、検証用コードを見ればわかりますが、そもそも検証用コードが正しい自信が無いので。w)

解決方法

結論から言うと、概ね解決できた。
RSpecのフォーマットを変えるオプション?を使えばうまくいきました。
参考URL : http://qiita.com/ohtsuka1317/items/984041a1b94131547a21
※言うまでもないですが、自己責任でお願いします。

前提条件

OS : CentOS 5.11 x86_64
ruby : 2.0.0p598
serverspec : 2.7.1
specinfra : 2.11.10
RSpec : 3.1.0

実行結果

以下のようなファイルができるようになります。

# cat test_result/20150421_124330/evidence.txt
============== Command "runlevel"==========================
###command
 runlevel

###stdout
N 3

###res_stderr

###exit_status
exit_status:0

表示される内容としては、
 ・テスト内容(検証コード内の”describe”の内容)
 ・実行コマンド
 ・標準出力
 ・標準エラー
 ・コマンドの戻り値
になります。

変更手順

変更を加えるのは以下3つのファイルです。

.rspec

# vim .rspec
#--------------------------
--color
--format ServerspecAuditFormatter
--require ./serverspec_audit_formatter.rb
#--------------------------

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'
require 'specinfra/backend/ssh'
require 'specinfra/backend/extension/ssh_su'

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)

    # 出力先ディレクトリを {ホスト名}/{テスト名}/{連番} で作成
    now_time = Time.now
    @dir = "./test_result/#{ENV['EXEC_TIME']}"
    FileUtils.mkdir_p(@dir)

    # 実行内容をファイル出力
    Dir.chdir("./test_result/#{ENV['EXEC_TIME']}") do
      # 実行コマンド
      File.open('evidence.txt', 'a') do |f|
        f.puts "============== " + example.example_group.top_level_description + "=========================="
        if example.metadata[:command].nil? == false
          f.puts "###command\n"  + example.metadata[:command].gsub('\\','')[145..-1] + "\n" # <-- gsubはエスケープ文字の"\"を消して見やすくするため。[145..-1]は環境変数の設定など、共通部分を極力表示させたくないので。"145"という文字数は環境に合わせて修正してください。
        end
        if example.metadata[:stdout].nil? == false
          f.puts "\n###stdout\n"
          f.puts(example.metadata[:stdout])
        end
        if example.metadata[:stderr].nil? == false
          f.puts "\n###stderr\n"
          f.puts(example.metadata[:stderr])
        end
        if exception.nil? == false
          f.puts "\n###exception\n"
          f.puts(exception.message)
        end
        resource = example.metadata[:described_class]
        if resource.kind_of? Serverspec::Type::Command
          f.puts "\n###res_stderr\n"
          f.puts(resource.stderr) unless resource.stderr.to_s.empty?
          f.puts "\n###exit_status\n"
          f.puts('exit_status:' + resource.exit_status.to_s)
        end
      end
    end
  end
end

Rakefile

ENV['EXEC_TIME'] = Time.now.strftime("%Y%m%d_%H%M%S").to_s #環境変数を定義するところに追記する

実行結果

以下のように、実行ディレクトリの下にエビデンスファイルが作成されます。

# cat test_result/20150421_124856/evidence.txt 
# ↑test_resultという共通ディレクトリの下にYYYYMMDD_HHMMSSのディレクトリができます

課題

・全く正規的ではない(無駄な繰り返しが多い=ダサい)
・serverspecの実行結果自体が保存されない

とりあえず、うまくいったのでこれで検証をしています。
課題点は今後解決するということで。

スポンサーリンク
Sponsords Link
  • このエントリーをはてなブックマークに追加

ZacoDesign

スポンサーリンク
Sponsords Link