やってること
- ec2のipを動的に取得
- 取得したipに対し、Serverspecを実行するtaskを動的に定義
- 上記のtaskを全て実行するtaskを定義
- awsのaccess key情報が環境変数で指定されてない場合、ec2の情報を取得しない
前提及び筆者の環境
- aws-sdkはv1を使用
-
vagrant
というホストに対して実行するspecが予め存在している
$ ls -la spec
-rw-r--r-- 1 nekogeruge staff 640 2 16 14:34 spec_helper.rb
drwxr-xr-x 4 nekogeruge staff 136 1 13 17:42 vagrant
- ec2に実行するspecは
vagrant
と同じものを使用する - Serverspecを実行したいインスタンスには、踏み台サーバを介した多段sshを使用して接続しており、下記のような
.ssh/config
が書いてある
Host bastion
HostName 99.999.99.999
Port 22
User ec2-user
IdentityFile ~/.ssh/bastion.pem
TCPKeepAlive yes
PasswordAuthentication no
Host 10.0.1.*
Port 22
User ec2-user
IdentityFile ~/.ssh/internal.pem
ProxyCommand ssh bastion -W %h:%p
Rakefile
require 'rake'
require 'rspec/core/rake_task'
require 'aws-sdk-v1'
#
# AWSのaccess key情報が環境変数に含まれている時のみ
# ec2のipを取得する
#
if ENV['AWS_ACCESS_KEY_ID'] && ENV['AWS_SECRET_ACCESS_KEY']
AWS.config(
{
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
region: 'ap-northeast-1'
}
)
ec2_hosts = AWS.ec2.instances.select { |i| i.status == :running }.map(&:private_ip_address)
end
task :spec => 'spec:all'
task :default => :spec
namespace :spec do
targets = []
Dir.glob('./spec/*').each do |dir|
next unless File.directory?(dir)
targets << File.basename(dir)
end
task :all => targets
task :default => :all
#
# 取得したec2のipのtaskを作成
#
if ec2_hosts
ec2_hosts.each do |host|
desc "Run serverspec tests to ec2 {host}"
RSpec::Core::RakeTask.new(host.to_sym) do |t|
ENV['TARGET_HOST'] = host
t.pattern = "spec/vagrant/*_spec.rb"
end
end
#
# 上で作成したtaskを全て実行する
# spec:ec2というtaskを作成
#
desc "Run serverspec tests to all ec2 host"
task :ec2 => ec2_hosts.map { |host| "spec:#{host}" }
end
targets.each do |target|
desc "Run serverspec tests to #{target}"
RSpec::Core::RakeTask.new(target.to_sym) do |t|
ENV['TARGET_HOST'] = target
t.pattern = "spec/#{target}/*_spec.rb"
end
end
end
実行
- aws関連の環境変数無し
$ rake -T
rake spec:vagrant # Run serverspec tests to vagrant
- 有り
-
envchain使用
- 例として
aws_staging
というnamespaceを使用しています
- 例として
-
envchain使用
$ envchain aws_staging rake -T
rake spec:10.0.1.100 # Run serverspec tests to ec2 10.0.1.100
rake spec:10.0.1.101 # Run serverspec tests to ec2 10.0.1.101
rake spec:10.0.1.102 # Run serverspec tests to ec2 10.0.1.102
rake spec:ec2 # Run serverspec tests to all ec2 host
rake spec:vagrant # Run serverspec tests to vagrant
-
rake spec:ec2
を実行すると、10.0.1.100
、10.0.1.100
、10.0.1.102
に対してServerspecを実行するtaskが順番に実行される
$ envchain aws_staging rake spec:ec2
...
問題点と解決策
実行してみると、specの結果にipが表示されない。
spec_helper.rb
に下記を追記することにより、結果にホスト名及びipが表示されるようになる
spec_helper.rb
puts "\nHost: #{ENV['TARGET_HOST']}"
$ envchain aws_staging rake spec:ec2
Host: 10.0.1.100
...
Host: 10.0.1.101
...
Host: 10.0.1.102
...