やりたいこと
Serverspecでテストを書いたとき、内部のコマンド結果がみれないので正しくテストできているか不安になったりします。コマンドと結果をファイルに書き出す方法は、別の方がすでに投稿されているのでそれを標準出力に出すようにしてみました。
参考:Serverspec でコマンド実行のエビデンスを取得
この投稿でファイルに書いている部分を、標準出力に出しただけです。
通常の結果表示
Serverspecを普通に実行するとこんな感じに、内部で実行しているコマンドの結果は表示されないです。
[root@console serverspec]# rake spec
/usr/bin/ruby -I/usr/local/share/gems/gems/rspec-core-3.4.2/lib:/usr/local/share/gems/gems/rspec-support-3.4.1/lib /usr/local/share/gems/gems/rspec-core-3.4.2/exe/rspec --pattern spec/localhost/\*_spec.rb
Package "httpd"
should be installed
Service "httpd"
should be enabled
should be running
Port "80"
should be listening
Command "ls -al /"
stdout
should match /bin/
Finished in 0.10108 seconds (files took 0.41086 seconds to load)
5 examples, 0 failures
フォーマット変更後の結果表示
結果表示用のフォーマットをスクリプトで書いて、実行時に指定した場合、コマンドとその結果が標準出力に出るようになります。スクリプトは後述。
参考元だと.rspecファイルでフォーマット等を指定していますが、今回はデバック時だけ詳細表示したかったので、実行時のSPEC_OPTSでフォーマット等を指定するようにしています。
[root@console serverspec]# rake spec SPEC_OPTS="--format ServerspecDebugFormatter --require ./serverspec_debug_formatter.rb"
/usr/bin/ruby -I/usr/local/share/gems/gems/rspec-core-3.4.2/lib:/usr/local/share/gems/gems/rspec-support-3.4.1/lib /usr/local/share/gems/gems/rspec-core-3.4.2/exe/rspec --pattern spec/localhost/\*_spec.rb
Package "httpd"
should be installed
-- command
/bin/sh -c rpm\ -q\ httpd
-- stdout
httpd-2.4.6-40.el7.centos.x86_64
Service "httpd"
should be enabled
-- command
/bin/sh -c systemctl\ --quiet\ is-enabled\ httpd
-- stdout
should be running
-- command
/bin/sh -c systemctl\ is-active\ httpd
-- stdout
active
Port "80"
should be listening
-- command
/bin/sh -c ss\ -tunl\ \|\ grep\ --\ :80\\\
-- stdout
tcp LISTEN 0 128 :::80 :::*
Command "ls -al /"
stdout
should match /bin/
-- command
/bin/sh -c ls\ -al\ /
-- stdout
total 68
dr-xr-xr-x 71 root root 4096 Feb 13 14:51 .
dr-xr-xr-x 71 root root 4096 Feb 13 14:51 ..
-rw-r--r-- 1 root root 0 Feb 6 01:18 .autorelabel
-rwxr-xr-x 1 root root 0 Feb 6 01:18 .dockerenv
-rwxr-xr-x 1 root root 0 Feb 6 01:18 .dockerinit
-rw-r--r-- 1 root root 31 Feb 13 14:32 .rspec
-rw-r--r-- 1 root root 685 Feb 13 12:20 Rakefile
lrwxrwxrwx 1 root root 7 Feb 6 01:22 bin -> usr/bin
dr-xr-xr-x 3 root root 4096 Feb 13 12:32 boot
drwxr-xr-x 15 root root 4380 Feb 11 01:02 dev
drwxr-xr-x 133 root root 4096 Feb 13 12:32 etc
drwxr-xr-x 2 root root 4096 Aug 12 2015 home
lrwxrwxrwx 1 root root 7 Feb 6 01:22 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Feb 6 01:22 lib64 -> usr/lib64
drwx------ 2 root root 4096 Aug 14 2015 lost+found
drwxr-xr-x 2 root root 4096 Aug 12 2015 media
drwxr-xr-x 2 root root 4096 Aug 12 2015 mnt
drwxr-xr-x 3 root root 4096 Feb 10 14:17 opt
dr-xr-xr-x 196 root root 0 Feb 11 01:02 proc
dr-xr-x--- 8 root root 4096 Feb 13 14:31 root
drwxr-xr-x 16 root root 360 Feb 13 15:59 run
lrwxrwxrwx 1 root root 8 Feb 6 01:22 sbin -> usr/sbin
drwxr-xr-x 1 1000 ftp 272 Feb 5 17:17 share
drwxr-xr-x 5 root root 4096 Feb 13 12:29 spec
drwxr-xr-x 2 root root 4096 Aug 12 2015 srv
dr-xr-xr-x 13 root root 0 Feb 10 13:37 sys
drwxrwxrwt 15 root root 4096 Feb 13 15:59 tmp
drwxr-xr-x 46 root root 4096 Feb 6 01:22 usr
drwxr-xr-x 53 root root 4096 Feb 13 12:32 var
-- exit status
0
Finished in 0.09723 seconds (files took 0.39293 seconds to load)
5 examples, 0 failures
フォーマット変更用のスクリプト
デバック時に指定するフォーマット用のrubyスクリプトです。インデントや表示をごにょごにょするようにしていますが、処理的には参考元のスクリプトでファイル出力していたのをputsに変えただけです。
require 'rspec/core/formatters/documentation_formatter'
require 'specinfra'
require 'serverspec/version'
require 'serverspec/type/base'
require 'serverspec/type/command'
class ServerspecDebugFormatter < RSpec::Core::Formatters::DocumentationFormatter
RSpec::Core::Formatters.register self, :example_group_started,
:example_passed, :example_pending, :example_failed
def initialize(output)
super
end
def example_group_started(notification)
@indent = 2 * (@group_level + 2)
super
end
def example_passed(notification)
super
puts_evidence(notification.example)
end
def example_pending(notification)
super
puts_evidence(notification.example)
end
def example_failed(notification)
super
puts_evidence(notification.example, notification.exception)
end
def puts_evidence(example, exception=nil)
# 実行コマンド
puts ' ' * @indent + '-- command'
puts ' ' * @indent + example.metadata[:command]
# 標準出力
if example.metadata[:stdout]
puts ' ' * @indent + '-- stdout'
example.metadata[:stdout].lines do |line|
puts ' ' * @indent + line
end
end
# RSpecのエラーメッセージ
if exception
puts ' ' * @indent + '-- exception'
exception.message.lines do |line|
puts ' ' * @indent + line
end
end
# 標準エラー出力と終了ステータス(commandリソースのみ)
resource = example.metadata[:described_class]
if resource.kind_of? Serverspec::Type::Command
unless resource.stderr.to_s.empty?
puts ' ' * @indent + '-- stderr'
resource.stderr.lines do |line|
puts ' ' * @indent + line
end
end
puts ' ' * @indent + '-- exit status'
puts ' ' * @indent + resource.exit_status.to_s
end
end
end
このスクリプトをこんな風に配置して、
[root@console serverspec]# tree .
.
├── Rakefile
├── serverspec_debug_formatter.rb
└── spec
├── localhost
│ └── sample_spec.rb
└── spec_helper.rb
Serverspec実行時のSPEC_OPTSで指定してやれば、実行コマンド結果を標準出力することができます。
# rake spec SPEC_OPTS="--format ServerspecDebugFormatter --require ./serverspec_debug_formatter.rb"
普段はオプションなしのrake specで実行して、テストを追加したときのデバックや、きちんと証跡を残す時はオプション付きでフォーマットを変えてコマンド結果を表示するとかです。
エラー出力がうまくとれない?
コマンドの標準エラー出力も表示できるはずだったんですが、なぜか標準エラー出力が表示されなかったです。そもそも標準エラー出力をテストする定義Serverspecで書いても、結果がブランクになったりするので環境が悪いのかも。原因がわかったら追記します。