ようへいの日々精進XP

よかろうもん

今更だけど capistrano と chef-solo を組み合わせて複数の EC2 インスタンスをセットアップして serverspec を使ってテストする

はじめに

  • 前回 は EC2 上に capistranoChef-solo を使ってインスタンスをセットアップした
  • セットアップしたインスタンスserverspec を使って cookbook が正しく適用されているかを確認する
  • EC2 の場合には動的な IP アドレス、ホスト名が適用されるのでちょっと工夫が必要

ポイント

  • どのようにして動的にアサインされる EC2 インスタンスのホスト名を取得して spec ファイル(ディレクトリ)を作成するか

アプローチ

インスタンスの情報を取得する

EC2 インスタンスtag を利用して特定インスタンスのみの情報を取得する場合には以下のようにすれば取得出来る。

servers = AWS.ec2.instances.select {|i| i.tags[:Name] == 'setup' && i.status == :running}.map(&:dns_name)

tag の名前が setup のインスタンス情報から PublicDNS の情報を取得する。

f:id:inokara:20140201071508p:plain

上記のように配列で取得出来る。余談だが pry 便利。

spec ファイルのテンプレートを生成

cookbook から spec ファイルが生成出来れば*1とても嬉しいが、唯一、ここだけ(厳密には .ssh/config の設定も)が手作業となってしまう。spec ファイルを動的に生成する為のテンプレートを以下のように作成する。(既に serverspec-init で初期ディレクトリは作成されている状態)

mkdir spec_template
vim spec_template/check_spec.rb

check_spec.rb の中身は以下のとおり。とりあえずパッケージのインストール状態のみを確認。

require 'spec_helper'

describe package('nginx') do
  it { should be_installed }
end

describe package('php5') do
  it { should be_installed }
end

describe package('mysql-server') do
  it { should be_installed }
end

spec テンプレートから EC2 インスタンス用に spec を作成する

以下のようなスクリプトを実行して spec ファイルを生成する。

#!/usr/bin/env ruby

require 'fileutils'
require 'aws-sdk'
require 'yaml'

# aws の access_key 等を YAML ファイルに指定する
config = YAML.load(File.read("#{ENV['HOME']}/path/to/config.yml"))
AWS.config(config)
#
ORIG = "./spec_template"
SPEC = "./spec"
#
servers = AWS.ec2.instances.select {|i| i.tags[:Name] == 'setup' && i.status == :running}.map(&:dns_name)
servers.each do |server|
  puts "Created #{SPEC}/#{server}/check_spec.rb"
  FileUtils.cp_r("#{ORIG}","#{SPEC}""/""#{server}") unless FileTest.exist?("#{server}")
end

実行すると以下のように spec 以下にインスタンスPublicDNS 名でディレクトリが作成され spec ファイル(check_spec.rb) がコピーされている。

f:id:inokara:20140201072421p:plain

おお。

.ssh/config の設定

もう一つの手作業である ~/.ssh/config を以下のように設定する。(但し、一度設定してしまえば良い)

Host ec2-*
  User ubuntu
  IdentityFile /path/to/keyfile

テスト

以下のようにテストを実行する。

rake spec

を実行すると以下のようにテストが行われる。

f:id:inokara:20140201080531p:plain

ちなみに fuubar という gem をインストールして ~/.rspec ファイルに以下を記述すると...

--color --format Fuubar

以下のようにちょっとだけ見栄えが良くなる(進捗がパーセンテージで表示される)。

f:id:inokara:20140201080917p:plain

ホントに気持ちだけ。


さいごに

この記事を書いていたら serverspecOpen Source Rookies of the Year 2013 という賞を受賞されたという記事を拝見してこりゃあ素晴らしいと感動しつつ、serverspecls とか cat のように一般的なツールの一つになってきてるなーと感じた。また、今回、spec ファイルの生成についてちょっとしたスクリプトを書いたりして拡張が簡単に出来るのは、serverspec 自体がそれぞれの利用環境に応じて適切に拡張出来るような柔軟な作りになっているからなんだろうなと感じた。

今更感が満載だったけど、capistranoChef-solo を組み合わせることで複数ホストの構築がお手軽に出来るようになった。また、aws-sdk を使うことでインスタンスの操作も capistrano 経由で行えるようになった。capistrano で何でもかんでもラッピングしてしまうのもあまり好ましいとは思わないが、サーバー構築に纏わる各種操作を出来るだけ統一することが出来るという点ではメリットは...あるよね...きっと...。

*1:出来ていた...