serverspecでWindowsとLinuxを複数台実行する
serverspecでWindows(WinRM)とLinux(SSH)を複数台実行する際の覚書です。
##環境
serverspec側:CentOS7.4 / ruby 2.6.
クライアント側:windows server 2019 / CentOS7.4
ファイル構成
(※)はディレクトリで、印がないのはファイル。
├── Rakefile
├── properties.yaml
└── spec(※)
└── spec_helper.rb
└── linux(※)
└──sample_spec.rb
└── windows(※)
└──sample_spec.rb
各ファイル
#Rakefile
require 'rake'
require 'rspec/core/rake_task'
require 'yaml'
require 'highline/import'
properties = YAML.load_file('properties.yaml')
ENV['TARGET_USER'] = ''
ENV['TARGET_PASSWORD'] = ''
ENV['TARGET_CONNECTION_METHOD'] = ''
ENV['WINRM_USER'] = 'Windowsのアカウント'
ENV['WINRM_PASSWORD'] = 'Windowsのパスワード'
ENV['SSH_USER'] = 'Linuxのアカウント'
ENV['SSH_PASSWORD'] = 'Linuxのパスワード'
task :spec => 'spec:all'
task :default => :spec
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]
if properties[key][:connection_method] == 'winrm'
ENV['TARGET_CONNECTION_METHOD'] = 'winrm'
if properties[key][:user].nil?
ENV['TARGET_USER'] = ENV['WINRM_USER']
else
ENV['TARGET_USER'] = properties[key][:user]
end
if properties[key][:password].nil?
ENV['TARGET_PASSWORD'] = ENV['WINRM_PASSWORD']
else
ENV['TARGET_PASSWORD'] = properties[key][:password]
end
elsif properties[key][:connection_method] == 'ssh'
ENV['TARGET_CONNECTION_METHOD'] = 'ssh'
if properties[key][:user].nil?
ENV['TARGET_USER'] = ENV['SSH_USER']
else
ENV['TARGET_USER'] = properties[key][:user]
end
if properties[key][:password].nil?
ENV['TARGET_PASSWORD'] = ENV['SSH_PASSWORD']
else
ENV['TARGET_PASSWORD'] = properties[key][:password]
end
end
t.pattern = 'spec/{' + properties[key][:roles].join(',') + '}/*_spec.rb'
end
end
end
#properties.yaml
windows-server01:
:roles:
- windows
:connection_method: winrm
:user: ユーザ
:password: パスワード
:hostname: IPアドレス
windows-server02:
:roles:
- windows
:connection_method: winrm
:hostname: IPアドレス #ユーザとパスワードの指定がなければRakefile中の宣言を使用する
centos-server01:
:roles:
- linux
:connection_method: ssh
:hostname: IPアドレス #ユーザとパスワードの指定がなければRakefile中の宣言を使用する
#spec_helper.rb
# coding: utf-8
require 'serverspec'
require 'pathname'
require 'winrm'
require 'net/ssh'
require 'yaml'
RSpec.configure do |c|
puts ''
puts "#### #{ENV['TARGET_HOST']} ####"
c.before :all do
if ENV['TARGET_CONNECTION_METHOD'] == 'winrm'
set :backend, :winrm
if Gem::Version.new(WinRM::VERSION) < Gem::Version.new('2')
winrm = ::WinRM::WinRMWebService.new(endpoint, :ssl, :user => "#{ENV['TARGET_USER']}", :pass => "#{ENV['TARGET_PASSWORD']}", :basic_auth_only => true)
winrm.set_timeout 300 # 5 minutes max timeout for any operation
else
opts = {
user: "#{ENV['TARGET_USER']}",
password: "#{ENV['TARGET_PASSWORD']}",
endpoint: "http://#{ENV['TARGET_HOST']}:5985/wsman",
operation_timeout: 300,
no_ssl_peer_verification: false,
}
Specinfra.configuration.winrm = ::WinRM::Connection.new(opts)
end
elsif ENV['TARGET_CONNECTION_METHOD'] == 'ssh'
set :backend, :ssh
set :sudo_password, ENV['TARGET_PASSWORD']
host = ENV['TARGET_HOST']
options = Net::SSH::Config.for(host)
options[:user] ||= ENV['TARGET_USER']
options[:password] = ENV['TARGET_PASSWORD']
set :ssh_options, options
set :host, options[:host_name] || host
end
end
end