LoginSignup
14
14

More than 5 years have passed since last update.

ec2のipを動的に取得し、全てのインスタンスにServerspecを実行する

Last updated at Posted at 2015-02-16

やってること

  • 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 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.10010.0.1.10010.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
...

参考

14
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
14