Serverspec環境構築手順

## 概要
Serverspecとは、サーバーの状態、設定などのテストを自動化するツールです。
RubyのRSpecのような使い方ができます。
実行するにはrubyが必要になります。

今回はその構築手順を書きます。
specの書き方についてはこちらを。
[Serverspec書き方](http://qiita.com/Esfahan/items/becdc7fee1ed44675567)


## 環境
- ruby 2.3.3.
- rake 12.0.0
- serverspec 2.38.0

## 環境構築手順
rubyがインストールされていることが前提となります。
関連：[rbenv, rubyのインストール](http://qiita.com/Esfahan/items/1a497fe75405561ef433#ruby-on-rails%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89%E3%83%A1%E3%83%A2---rbenv-ruby-mysql%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)

### gemのインストール
適当にserverspec用のディレクトリを作成して、Gemfileを作成して `bundle install` してください。

```rb:Gemfile
source "https://rubygems.org"

gem 'serverspec'
gem 'rake'
gem 'highline'
```

```bash
$ bundle install --path vendor/bundle
```

### Serverspecのインストール
このコマンドで必要なファイルと、サンプルのテストコードが作成される。
サンプルは不要であれば削除してください。

```bash
$ bundle exec serverspec-init
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: example.com
 + spec/
 + spec/example.com/
 + spec/example.com/sample_spec.rb
 + spec/spec_helper.rb
 + Rakefile
 + .rspec
```

`Vagrant instance y/n: y` にすると、テスト実行時に自動で `vagrant up` されて、
その中でテストが実行されるというようなことができるみたいだが、未確認。
参考：[vagrant-serverspecを使ってサーバをテストする。](http://ksaito11.hatenablog.com/entry/2016/01/24/192806)

### test実行
テストコードができたら、下記コマンドでテストを実行してください。
`ASK_SUDO_PASSWORD` はテスト対象サーバーでsudoをする必要があるなら付けてください。
もしくは環境変数として`export SUDO_PASSWORD=xxxx`をセットしてください。

```
$ bundle exec rake
$ ASK_SUDO_PASSWORD=1 bundle exec rake
```

RSpecのように、テストの成功、失敗が表示されます。

```bash
Finished in 0.4053 seconds (files took 0.23084 seconds to load)
73 examples, 0 failures
```

## 複数ホストに対応
前述の方法では、テスト対象サーバーが一つのときにしか対応できません。
下記の方法であれば、同じテストを、複数台のサーバーへ流すことができます。

以下のファイルを書き換えます。

### Rakefile

```rb:Rakefile
require 'rake'
require 'rspec/core/rake_task'
require 'yaml'
require 'highline/import'

argv = ARGV
env = argv.length < 2 ? 'development' : argv[1]

case env
when 'production' then
  yaml_file = 'production.yml'
when 'staging' then
  yaml_file = 'staging.yml'
when 'development' then
  yaml_file = 'development.yml'
else
  puts 'Error: Invalid argument, choose one out of production, staging, development'
  exit(1)
end

properties = YAML.load_file("properties/#{yaml_file}")

ENV['SSH_USER'] = ask("Enter ssh user: ") { |q| q.echo = true }
ENV['SSH_PASSWORD'] = ask("Enter ssh password: ") { |q| q.echo = false }

desc "Run serverspec to all hosts"
task :serverspec => 'serverspec:all'

namespace :serverspec do
  task :all => properties.keys.map {|key| 'serverspec:' + key }
  properties.keys.each do |key|
    desc "Run serverspec to #{key}"
    RSpec::Core::RakeTask.new(key.to_sym) do |t|
      ENV['TARGET_HOST'] = properties[key][:hostname]
      t.pattern = 'spec/{' + properties[key][:roles].join(',') + '}/*_spec.rb'
      t.fail_on_error = false
    end
  end
end
```

### spec/spec_helper.rb

```rb:spec/spec_helper.rb
require 'serverspec'
require 'pathname'
require 'net/ssh'
require 'yaml'

set :backend, :ssh
set :path, '/sbin:/usr/sbin:$PATH'

RSpec.configure do |c|
  c.before :all do
    set :host, ENV['TARGET_HOST']
    options = Net::SSH::Config.for(c.host)
    options[:user] = ENV['SSH_USER']
    options[:password] = ENV['SSH_PASSWORD']
    set :ssh_options, options
  end
end
```

### properties.yml
新規に作る。チェック対象のホストを記載する。
環境ごとにファイルを作る。

- properties/production.yml
- properties/staging.yml
- properties/development.yml

```yaml:properties/production.yml
sample-host-01:
  :roles:
    - pc/nginx
    - pc/firewall
  :hostname: sample-host-01.com

sample-host-02:
  :roles:
    - pc/nginx
    - pc/firewall
  :hostname: sample-host-02.com
```


#### hostname
テスト対象サーバーの接続先情報。IPアドレスでもOK。

#### roles
実施するテスト項目。上記の例だと、
下記のディレクトリの下にある `*_spec.rb` を全て実行する。

- spec/pc/nginx
- spec/pc/firewall

### テスト実行
実行コマンドは、 `bundle exec rake` ではなく下記になります。

```bash
$ bundle exec rake serverspec {production | staging | development}
```


specの書き方はこちら
[Serverspec書き方](http://qiita.com/Esfahan/items/becdc7fee1ed44675567)


以上

## 参考
http://serverspec.org/
[さくらのナレッジ 「Serverspec」を使ってサーバー環境を自動テストしよう](http://knowledge.sakura.ad.jp/tech/2596/)
[serverspec v2で複数ホストにrole別にtest実行](http://kidooom.hatenadiary.jp/entry/2015/02/10/154830)
[Serverspecで複数ホストのテストをする時、途中でfailしても、最後までspecを実行させる。](http://qiita.com/haazime/items/1cfab4e1e34b23f20ce1)