class Kitchen::Verifier::Serverspec

Serverspec verifier for Kitchen.

Public Instance Methods

bundler_cmd() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 340
def bundler_cmd
  config[:bundler_path] ? "#{config[:bundler_path]}/bundle" : '$(which bundle)'
end
bundler_local_cmd() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 344
def bundler_local_cmd
  config[:bundler_path] ? "#{config[:bundler_path]}/bundle" : 'bundle'
end
call(state) click to toggle source

(see Base#call)

# File lib/kitchen/verifier/serverspec.rb, line 52
def call(state)
  info("[#{name}] Verify on instance=#{instance} with state=#{state}")
  sleep_if_set
  merge_state_to_env(state)
  if config[:remote_exec]
    debug('Running Serverspec on remote server')
    if config[:default_pattern]
      create_sandbox
      sandbox_dirs = [ sandbox_path ]
    end
    instance.transport.connection(state) do |conn|
      conn.execute(install_command)
      if config[:default_pattern]
        info("Transferring files to #{instance.to_str}")
        conn.upload(sandbox_dirs, config[:root_path])
        debug('Transfer complete')
      end
      conn.execute(serverspec_commands)
    end
    cleanup_sandbox if config[:default_pattern]
  else
    debug('Running Serverspec locally on workstation')
    config[:default_path] = Dir.pwd if config[:default_path] == '/tmp/kitchen'
    install_command
    serverspec_commands
  end
  debug("[#{name}] Verify completed.")
end
chef_data_dir?(base, file) click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 423
def chef_data_dir?(base, file)
  file =~ %r{^#{base}/(data|data_bags|environments|nodes|roles)/}
end
color() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 376
def color
  config[:color] ? '-c' : nil
end
create_sandbox() click to toggle source

(see Base#create_sandbox)

Calls superclass method
# File lib/kitchen/verifier/serverspec.rb, line 93
def create_sandbox
  super
  prepare_suites
end
custom_serverspec_command() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 335
def custom_serverspec_command
  return config[:custom_serverspec_command] if config[:custom_serverspec_command]
  config[:serverspec_command]
end
env_vars() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 309
def env_vars
  return nil if config[:env_vars].none?
  cmd = nil
  if !config[:remote_exec]
    config[:env_vars].map do |k, v|
      info("Environment variable #{k} value #{v}")
      ENV[k.to_s] = v.to_s
    end
  else
    cmd = config[:env_vars].map { |k, v| "#{k}=#{v}" }.join(' ')
    debug(cmd)
  end
  cmd
end
fi_test_serverspec_installed() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 281
def fi_test_serverspec_installed
  config[:test_serverspec_installed] ? 'fi' : nil
end
gem_proxy_parm() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 372
def gem_proxy_parm
  http_proxy ? "--http-proxy #{http_proxy}" : nil
end
http_proxy() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 364
def http_proxy
  config[:http_proxy]
end
https_proxy() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 368
def https_proxy
  config[:https_proxy]
end
install_bundler() click to toggle source

private

# File lib/kitchen/verifier/serverspec.rb, line 170
      def install_bundler
        if config[:remote_exec]
          <<-INSTALL
            if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ] || [ -f /etc/oracle-release ] || ( [ -f /etc/os-release ] && grep -q 'Amazon Linux 2' /etc/os-release ); then
              echo '-----> Installing os provided bundler package'
              #{sudo_env('yum')} -y install rubygem-bundler
            else
              echo '-----> Installing bundler via rubygems'
              if [ \"$(#{sudo('gem')} list bundler -i)\" = \"true\" ]; then
                echo "Bundler already installed"
              else
                if [ \"$(#{sudo('gem')} list bundler -i)\" = \"false\" ]; then
                  #{sudo_env('gem')} install #{gem_proxy_parm} --no-ri --no-rdoc bundler
                else
                  echo "ERROR: Ruby not installed correctly"
                  exit 1
                fi
              fi
            fi
          INSTALL
        else
          begin
            require 'bundler'
          rescue LoadError
            shellout `gem install --no-ri --no-rdoc  bundler`
          end
        end
      end
install_command() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 127
      def install_command
        info('Installing with custom install command') if config[:custom_install_command]
        return config[:custom_install_command] if config[:custom_install_command]
        if config[:remote_exec]
          info('Installing ruby, bundler and serverspec remotely on server')
          <<-INSTALL
            #{config[:additional_install_command]}
            if [ ! $(which ruby) ]; then
              echo '-----> Installing ruby, will try to determine platform os'
              if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ] || [ -f /etc/oracle-release ]; then
                #{sudo_env('yum')} -y install ruby
              else
                if [ -f /etc/system-release ] && grep -q 'Amazon Linux' /etc/system-release; then
                  #{sudo_env('yum')} -y install ruby
                else
                  #{sudo_env('apt-get')} -y update
                  #{sudo_env('apt-get')} -y install ruby
                fi
              fi
            fi
            #{install_bundler}
            if [ -d #{config[:default_path]} ]; then
              #{install_serverspec}
              #{install_runner}
            else
              echo "ERROR: Default path '#{config[:default_path]}' does not exist"
              exit 1
            fi
          INSTALL
        else
          info('Installing bundler and serverspec locally on workstation')
          if config[:additional_install_command]
            c = config[:additional_install_command]
            shellout c
          end
          install_bundler
          install_serverspec
          install_runner
        end
      end
install_gemfile() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 247
      def install_gemfile
        if config[:gemfile]
          <<-INSTALL
          #{read_gemfile}
          INSTALL
        else
          <<-INSTALL
          #{sudo('rm')} -f #{config[:default_path]}/Gemfile
          #{sudo('echo')} "source 'https://rubygems.org'" >> #{config[:default_path]}/Gemfile
          #{sudo('echo')} "gem 'net-ssh','~> 3'"  >> #{config[:default_path]}/Gemfile
          #{sudo('echo')} "gem 'serverspec'" >> #{config[:default_path]}/Gemfile
          INSTALL
        end
      end
install_runner() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 199
      def install_runner
        return unless config[:require_runner]
        raise ActionFailed, 'Serverspec Runners only for remote execution' unless config[:remote_exec]
        <<-INSTALL
          if [ ! -f #{config[:default_path]}/#{runner_filename} ]; then
            #{sudo_env('curl')} -o #{config[:default_path]}/#{runner_filename} #{config[:runner_url]}
          fi
        INSTALL
      end
install_serverspec() click to toggle source

rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity

# File lib/kitchen/verifier/serverspec.rb, line 210
      def install_serverspec
        if config[:remote_exec]
          <<-INSTALL
              #{test_serverspec_installed}
              #{install_gemfile}
              BUNDLE_CMD=#{bundler_cmd}
              echo "---> BUNDLE_CMD variable is: ${BUNDLE_CMD}"
              #{sudo_env('')} $BUNDLE_CMD install --gemfile=#{config[:default_path]}/Gemfile
            #{fi_test_serverspec_installed}
          INSTALL
        else
          if config[:test_serverspec_installed]
            begin
              require 'serverspec'
              return
            rescue LoadError
              info('serverspec not installed installing ...')
            end
          end
          unless config[:gemfile]
            gemfile = "#{config[:default_path]}/Gemfile"
            unless File.exist?(gemfile)
              File.open(gemfile, 'w') do |f|
                f.write("source 'https://rubygems.org'\ngem 'net-ssh','~> 2.9.4'\ngem 'serverspec'")
              end
            end
          end
          gemfile = config[:gemfile] if config[:gemfile]
          begin
            shellout "#{bundler_local_cmd} install --gemfile=#{gemfile}"
          rescue
            raise ActionFailed, 'Serverspec install failed'
          end
          nil
        end
      end
local_suite_files() click to toggle source

Returns an Array of test suite filenames for the related suite currently residing on the local workstation. Any special provisioner-specific directories (such as a Chef roles/ directory) are excluded.

@return [Array<String>] array of suite files @api private

# File lib/kitchen/verifier/serverspec.rb, line 433
def local_suite_files
  base = File.join(config[:test_base_path], config[:suite_name])
  glob = File.join(base, '*/**/*')
  Dir.glob(glob).reject do |f|
    chef_data_dir?(base, f) || File.directory?(f)
  end
end
merge_state_to_env(state) click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 403
def merge_state_to_env(state)
  env_state = { :environment => {} }
  env_state[:environment]['KITCHEN_INSTANCE'] = instance.name
  env_state[:environment]['KITCHEN_PLATFORM'] = instance.platform.name
  env_state[:environment]['KITCHEN_SUITE'] = instance.suite.name
  state.each_pair do |key, value|
    env_state[:environment]['KITCHEN_' + key.to_s.upcase] = value.to_s
    ENV['KITCHEN_' + key.to_s.upcase] = value.to_s
    info("Environment variable #{'KITCHEN_' + key.to_s.upcase} value #{value}")
  end
  # if using a driver that uses transport expose those too
  %w[username password ssh_key port].each do |key|
    next if instance.transport[key.to_sym].nil?
    value = instance.transport[key.to_sym].to_s
    ENV['KITCHEN_' + key.to_s.upcase] = value
    info("Transport Environment variable #{'KITCHEN_' + key.to_s.upcase} value #{value}")
  end
  config[:shellout_opts].merge!(env_state)
end
prepare_suites() click to toggle source

Copies all test suite files into the suites directory in the sandbox.

# File lib/kitchen/verifier/serverspec.rb, line 442
def prepare_suites
  base = File.join(config[:test_base_path], config[:suite_name])
  debug("Creating local sandbox of all test suite files in #{base}")
  local_suite_files.each do |src|
    dest = File.join(sandbox_suites_dir, src.sub("#{base}/", ''))
    FileUtils.mkdir_p(File.dirname(dest))
    FileUtils.cp(src, dest, :preserve => true)
  end
end
read_gemfile() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 262
def read_gemfile
  data = "#{sudo('rm')} -f #{config[:default_path]}/Gemfile\n"
  f = File.open(config[:gemfile], 'r')
  f.each_line do |line|
    data = "#{data}#{sudo('echo')} \"#{line}\" >> #{config[:default_path]}/Gemfile\n"
  end
  f.close
  data
end
remove_default_path() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 272
def remove_default_path
  info('Removing default path') if config[:remove_default_path]
  config[:remove_default_path] ? "rm -rf #{config[:default_path]}" : nil
end
rspec_bash_cmd() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 348
def rspec_bash_cmd
  config[:rspec_path] ? "#{config[:rspec_path]}/rspec" : '$(which rspec)'
end
rspec_cmd() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 305
def rspec_cmd
  config[:require_runner] ? "ruby #{config[:default_path]}/#{runner_filename}" : "#{rspec_path}rspec"
end
rspec_commands() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 285
def rspec_commands
  info('Running Serverspec')
  if config[:default_pattern]
    if config[:remote_exec]
      info("Using default pattern #{config[:root_path]}/suites/serverspec/*_spec.rb")
      config[:patterns] = ["#{config[:root_path]}/suites/serverspec/*_spec.rb"]
    else
      info("Using default pattern #{config[:test_base_path]}/#{config[:suite_name]}/serverspec/*_spec.rb")
      config[:patterns] = ["#{config[:test_base_path]}/#{config[:suite_name]}/serverspec/*_spec.rb"]
    end
  end
  if config[:require_runner]
    "#{env_vars} #{sudo_env(rspec_cmd)} #{color} -f #{config[:format]} --default-path  #{config[:default_path]} #{rspec_path_option} #{config[:extra_flags]}"
  elsif config[:remote_exec]
    config[:patterns].map { |s| "#{env_vars} #{sudo_env('')} $RSPEC_CMD #{color} -f #{config[:format]} --default-path  #{config[:default_path]} #{config[:extra_flags]} -P #{s}" }.join(';')
  else
    config[:patterns].empty? ? '' : "#{env_vars} #{sudo_env(rspec_cmd)} #{color} -f #{config[:format]} --default-path  #{config[:default_path]} #{config[:extra_flags]} #{config[:patterns].map { |s| "-P #{s}" }.join(' ')}"
  end
end
rspec_path() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 352
def rspec_path
  config[:rspec_path] ? "#{config[:rspec_path]}/" : nil
end
rspec_path_option() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 356
def rspec_path_option
  config[:rspec_path] ? "--rspec-path #{config[:rspec_path]}/" : nil
end
run_command() click to toggle source

for legacy drivers.

# File lib/kitchen/verifier/serverspec.rb, line 82
def run_command
  sleep_if_set
  serverspec_commands
end
runner_filename() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 360
def runner_filename
  File.basename(config[:runner_url])
end
sandbox_suites_dir() click to toggle source

@return [String] path to suites directory under sandbox path @api private

# File lib/kitchen/verifier/serverspec.rb, line 454
def sandbox_suites_dir
  File.join(sandbox_path, 'suites')
end
serverspec_commands() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 98
      def serverspec_commands
        if config[:remote_exec]
          if custom_serverspec_command
            <<-INSTALL
            #{custom_serverspec_command}
            INSTALL
          else
            <<-INSTALL
            #{config[:additional_serverspec_command]}
            mkdir -p #{config[:default_path]}
            cd #{config[:default_path]}
            RSPEC_CMD=#{rspec_bash_cmd}
            echo "---> RSPEC_CMD variable is: ${RSPEC_CMD}"
            #{rspec_commands}
            #{remove_default_path}
            INSTALL
          end
        elsif custom_serverspec_command
          shellout custom_serverspec_command
        else
          if config[:additional_serverspec_command]
            c = config[:additional_serverspec_command]
            shellout c
          end
          c = rspec_commands
          shellout c
        end
      end
setup_cmd() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 87
def setup_cmd
  sleep_if_set
  install_command
end
shellout(command) click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 390
def shellout(command)
  command = command.strip
  info("Running command: #{command}")
  cmd = Mixlib::ShellOut.new(command, config[:shellout_opts])
  cmd.live_stream = config[:live_stream]
  cmd.run_command
  begin
    cmd.error!
  rescue Mixlib::ShellOut::ShellCommandFailed
    raise ActionFailed, "Command #{command.inspect} failed for #{instance.to_str}"
  end
end
sleep_if_set() click to toggle source

Sleep for a period of time, if a value is set in the config.

@api private

# File lib/kitchen/verifier/serverspec.rb, line 383
def sleep_if_set
  config[:sleep].to_i.times do
    print '.'
    sleep 1
  end
end
sudo_env(pm) click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 324
def sudo_env(pm)
  if config[:remote_exec]
    s = https_proxy ? "https_proxy=#{https_proxy}" : nil
    p = http_proxy ? "http_proxy=#{http_proxy}" : nil
    p || s ? "#{sudo('env')} #{p} #{s} #{pm}" : sudo(pm).to_s
  else
    # TODO: handle proxies
    pm
  end
end
test_serverspec_installed() click to toggle source
# File lib/kitchen/verifier/serverspec.rb, line 277
def test_serverspec_installed
  config[:test_serverspec_installed] ? "if [ \"$(#{sudo('gem')} list serverspec -i)\" = \"false\" ]; then" : nil
end