lib/beaker/dsl/helpers.rb in beaker-1.16.0 vs lib/beaker/dsl/helpers.rb in beaker-1.17.0
- old
+ new
@@ -1,10 +1,13 @@
# -*- coding: utf-8 -*-
require 'resolv'
require 'inifile'
require 'timeout'
require 'beaker/dsl/outcomes'
+require 'beaker/options'
+require 'hocon'
+require 'hocon/config_error'
module Beaker
module DSL
# This is the heart of the Puppet Acceptance DSL. Here you find a helper
# to proxy commands to hosts, more commands to move files between hosts
@@ -72,23 +75,20 @@
# on :dashboard, "echo hello"
#
# @return [Result] An object representing the outcome of *command*.
# @raise [FailTest] Raises an exception if *command* obviously fails.
def on(host, command, opts = {}, &block)
- unless command.is_a? Command
+ block_on host do | host |
+ if command.is_a? Command
+ command = command.cmd_line(host)
+ end
cmd_opts = {}
+ #add any additional environment variables to the command
if opts[:environment]
cmd_opts['ENV'] = opts[:environment]
end
command = Command.new(command.to_s, [], cmd_opts)
- end
- if host.is_a? String or host.is_a? Symbol
- host = hosts_as(host) #check by role
- end
- if host.is_a? Array
- host.map { |h| on h, command, opts, &block }
- else
@result = host.exec(command, opts)
# Also, let additional checking be performed by the caller.
if block_given?
case block.arity
@@ -98,12 +98,11 @@
#block with arity of 1 or greater, hand back the result object
else
yield @result
end
end
-
- return @result
+ @result
end
end
# The method for executing commands on the default host
#
@@ -177,15 +176,14 @@
# @param [String] to_path A local path to copy *from_path* to.
# @!macro common_opts
#
# @return [Result] Returns the result of the SCP operation
def scp_from host, from_path, to_path, opts = {}
- if host.is_a? Array
- host.each { |h| scp_from h, from_path, to_path, opts }
- else
+ block_on host do | host |
@result = host.do_scp_from(from_path, to_path, opts)
@result.log logger
+ @result
end
end
# Move a local file to a remote host
# @note If using {Beaker::Host} for the hosts *scp* is not
@@ -199,15 +197,14 @@
# @param [String] to_path A remote path to copy *from_path* to.
# @!macro common_opts
#
# @return [Result] Returns the result of the SCP operation
def scp_to host, from_path, to_path, opts = {}
- if host.is_a? Array
- host.each { |h| scp_to h, from_path, to_path, opts }
- else
+ block_on host do | host |
@result = host.do_scp_to(from_path, to_path, opts)
@result.log logger
+ @result
end
end
# Check to see if a package is installed on a remote host
#
@@ -347,11 +344,11 @@
#
# @param opts [Hash]
# @option opts [String] :source The location on the test runners box where the files are found
# @option opts [String] :module_name The name of the module to be copied over
def puppet_module_install_on(host, opts = {})
- Array(host).each do |h|
+ block_on host do | h |
on h, puppet("module install #{opts[:module_name]}")
end
end
# Copy a puppet module from a given source to all hosts under test.
@@ -403,35 +400,18 @@
# @return [Array<Host>] Returns an array of hosts that are still valid
# targets for this tests case.
# @raise [SkipTest] Raises skip test if there are no valid hosts for
# this test case after confinement.
def confine(type, criteria, host_array = nil, &block)
- provided_hosts = host_array ? true : false
hosts_to_modify = host_array || hosts
- criteria.each_pair do |property, value|
- case type
- when :except
- hosts_to_modify = hosts_to_modify.reject do |host|
- inspect_host host, property, value
- end
- if block_given?
- hosts_to_modify = hosts_to_modify.reject do |host|
- yield host
- end
- end
- when :to
- hosts_to_modify = hosts_to_modify.select do |host|
- inspect_host host, property, value
- end
- if block_given?
- hosts_to_modify = hosts_to_modify.select do |host|
- yield host
- end
- end
- else
- raise "Unknown option #{type}"
- end
+ case type
+ when :except
+ hosts_to_modify = hosts_to_modify - select_hosts(criteria, hosts_to_modify, &block)
+ when :to
+ hosts_to_modify = select_hosts(criteria, hosts_to_modify, &block)
+ else
+ raise "Unknown option #{type}"
end
if hosts_to_modify.empty?
logger.warn "No suitable hosts with: #{criteria.inspect}"
skip_test 'No suitable hosts found'
end
@@ -454,10 +434,63 @@
ensure
self.hosts = original_hosts
end
end
+ #Return a set of hosts that meet the given criteria
+ # @param [Hash{Symbol,String=>String,Regexp,Array<String,Regexp>}]
+ # criteria Specify the criteria with which a host should be
+ # considered for inclusion. The key is any attribute
+ # of the host that will be yielded by {Beaker::Host#[]}.
+ # The value can be any string/regex or array of strings/regexp.
+ # The values are compared using [Enumerable#any?] so that if one
+ # value of an array matches the host is considered a match for that
+ # criteria.
+ # @param [Array<Host>] host_array This creatively named parameter is
+ # an optional array of hosts to confine to. If not passed in, this
+ # method will modify {Beaker::TestCase#hosts} in place.
+ # @param [Proc] block Addition checks to determine suitability of hosts
+ # for selection. Each host that is still valid after checking
+ # *criteria* is then passed in turn into this block. The block
+ # should return true if the host matches this additional criteria.
+ #
+ # @return [Array<Host>] Returns an array of hosts that meet the provided criteria
+ def select_hosts(criteria, host_array = nil, &block)
+ hosts_to_select_from = host_array || hosts
+ criteria.each_pair do |property, value|
+ hosts_to_select_from = hosts_to_select_from.select do |host|
+ inspect_host host, property, value
+ end
+ end
+ if block_given?
+ hosts_to_select_from = hosts_to_select_from.select do |host|
+ yield host
+ end
+ end
+ hosts_to_select_from
+ end
+
+ # Return the name of the puppet user.
+ #
+ # @param [Host] host One object that acts like a Beaker::Host
+ #
+ # @note This method assumes puppet is installed on the host.
+ #
+ def puppet_user(host)
+ return host.puppet('master')['group']
+ end
+
+ # Return the name of the puppet group.
+ #
+ # @param [Host] host One object that acts like a Beaker::Host
+ #
+ # @note This method assumes puppet is installed on the host.
+ #
+ def puppet_group(host)
+ return host.puppet('master')['user']
+ end
+
# @!visibility private
def inspect_host(host, property, one_or_more_values)
values = Array(one_or_more_values)
return values.any? do |value|
true_false = false
@@ -487,20 +520,28 @@
# @param [Hash{Symbol=>String}] conf_opts Represents puppet settings.
# Sections of the puppet.conf may be
# specified, if no section is specified the
# a puppet.conf file will be written with the
# options put in a section named after [mode]
+ # @option conf_opts [String] :__commandline_args__ A special setting for
+ # command_line arguments such as --debug or
+ # --logdest, which cannot be set in
+ # puppet.conf. For example:
#
- # There is a special setting for command_line
- # arguments such as --debug or --logdest, which
- # cannot be set in puppet.conf. For example:
- #
# :__commandline_args__ => '--logdest /tmp/a.log'
#
# These will only be applied when starting a FOSS
# master, as a pe master is just bounced.
- #
+ # @option conf_opts [Hash] :__service_args__ A special setting of options
+ # for controlling how the puppet master service is
+ # handled. The only setting currently is
+ # :bypass_service_script, which if set true will
+ # force stopping and starting a webrick master
+ # using the start_puppet_from_source_* methods,
+ # even if it seems the host has passenger.
+ # This is needed in FOSS tests to initialize
+ # SSL.
# @param [File] testdir The temporary directory which will hold backup
# configuration, and other test artifacts.
#
# @param [Block] block The point of this method, yields so
# tests may be ran. After the block is finished
@@ -522,20 +563,47 @@
#
# @api dsl
def with_puppet_running_on host, conf_opts, testdir = host.tmpdir(File.basename(@path)), &block
raise(ArgumentError, "with_puppet_running_on's conf_opts must be a Hash. You provided a #{conf_opts.class}: '#{conf_opts}'") if !conf_opts.kind_of?(Hash)
cmdline_args = conf_opts[:__commandline_args__]
- conf_opts = conf_opts.reject { |k,v| k == :__commandline_args__ }
+ service_args = conf_opts[:__service_args__] || {}
+ conf_opts = conf_opts.reject { |k,v| [:__commandline_args__, :__service_args__].include?(k) }
curl_retries = host['master-start-curl-retries'] || options['master-start-curl-retries']
logger.debug "Setting curl retries to #{curl_retries}"
+ if options[:is_jvm_puppet]
+ confdir = host.puppet('master')['confdir']
+ vardir = host.puppet('master')['vardir']
+
+ if cmdline_args
+ split_args = cmdline_args.split()
+
+ split_args.each do |arg|
+ case arg
+ when /--confdir=(.*)/
+ confdir = $1
+ when /--vardir=(.*)/
+ vardir = $1
+ end
+ end
+ end
+
+ jvm_puppet_opts = { "jruby-puppet" => {
+ "master-conf-dir" => confdir,
+ "master-var-dir" => vardir,
+ }}
+
+ jvm_puppet_conf = File.join("#{host['jvm-puppet-confdir']}", "jvm-puppet.conf")
+ modify_tk_config(host, jvm_puppet_conf, jvm_puppet_opts)
+ end
+
begin
backup_file = backup_the_file(host, host['puppetpath'], testdir, 'puppet.conf')
lay_down_new_puppet_conf host, conf_opts, testdir
- if host['puppetservice']
+ if host.use_service_scripts? && !service_args[:bypass_service_script]
bounce_service( host, host['puppetservice'], curl_retries )
else
puppet_master_started = start_puppet_from_source_on!( host, cmdline_args )
end
@@ -545,20 +613,21 @@
original_exception = RuntimeError.new("PuppetAcceptance::DSL::Helpers.with_puppet_running_on failed (check backtrace for location) because: #{early_exception}\n#{early_exception.backtrace.join("\n")}\n")
raise(original_exception)
ensure
begin
- restore_puppet_conf_from_backup( host, backup_file )
- if host['puppetservice']
+ if host.use_service_scripts? && !service_args[:bypass_service_script]
+ restore_puppet_conf_from_backup( host, backup_file )
bounce_service( host, host['puppetservice'], curl_retries )
else
if puppet_master_started
stop_puppet_from_source_on( host )
else
dump_puppet_log(host)
end
+ restore_puppet_conf_from_backup( host, backup_file )
end
rescue Exception => teardown_exception
begin
if !host.is_pe?
@@ -653,11 +722,11 @@
end
# @!visibility private
def dump_puppet_log(host)
syslogfile = case host['platform']
- when /fedora|centos|el/ then '/var/log/messages'
+ when /fedora|centos|el|redhat|scientific/ then '/var/log/messages'
when /ubuntu|debian/ then '/var/log/syslog'
else return
end
logger.notify "\n*************************"
@@ -685,14 +754,93 @@
new_conf = IniFile.new( puppetconf ).merge( conf_opts )
new_conf
end
+ # Modify the given TrapperKeeper config file.
+ #
+ # @param [Host] host A host object
+ # @param [OptionsHash] options_hash New hash which will be merged into
+ # the given TrapperKeeper config.
+ # @param [String] config_file_path Path to the TrapperKeeper config on
+ # the given host which is to be
+ # modified.
+ # @param [Bool] replace If set true, instead of updating the existing
+ # TrapperKeeper configuration, replace it entirely
+ # with the contents of the given hash.
+ #
+ # @note TrapperKeeper config files can be HOCON, JSON, or Ini. We don't
+ # particularly care which of these the file named by `config_file_path` on
+ # the SUT actually is, just that the contents can be parsed into a map.
+ #
+ def modify_tk_config(host, config_file_path, options_hash, replace=false)
+ if options_hash.empty?
+ return nil
+ end
+
+ new_hash = Beaker::Options::OptionsHash.new
+
+ if replace
+ new_hash.merge!(options_hash)
+ else
+ if not host.file_exist?( config_file_path )
+ raise "Error: #{config_file_path} does not exist on #{host}"
+ end
+ file_string = host.exec( Command.new( "cat #{config_file_path}" )).stdout
+
+ begin
+ tk_conf_hash = read_tk_config_string(file_string)
+ rescue RuntimeError
+ raise "Error reading trapperkeeper config: #{config_file_path} at host: #{host}"
+ end
+
+ new_hash.merge!(tk_conf_hash)
+ new_hash.merge!(options_hash)
+ end
+
+ file_string = JSON.dump(new_hash)
+ create_remote_file host, config_file_path, file_string
+ end
+
+ # The Trapperkeeper config service will accept HOCON (aka typesafe), JSON,
+ # or Ini configuration files which means we need to safely handle the the
+ # exceptions that might come from parsing the given string with the wrong
+ # parser and fall back to the next valid parser in turn. We finally raise
+ # a RuntimeException if none of the parsers succeed.
+ #
# @!visibility private
+ def read_tk_config_string( string )
+ begin
+ return Hocon.parse(string)
+ rescue Hocon::ConfigError
+ nil
+ end
+
+ begin
+ return JSON.parse(string)
+ rescue JSON::JSONError
+ nil
+ end
+
+ begin
+ return IniFile.new(string)
+ rescue IniFile::Error
+ nil
+ end
+
+ raise "Failed to read TrapperKeeper config!"
+ end
+
+ # @!visibility private
def bounce_service host, service, curl_retries = 120
- host.exec puppet_resource( 'service', service, 'ensure=stopped' )
- host.exec puppet_resource( 'service', service, 'ensure=running' )
+ if host.graceful_restarts?
+ apachectl_path = host.is_pe? ? "#{host['puppetsbindir']}/apache2ctl" : 'apache2ctl'
+ host.exec(Command.new("#{apachectl_path} graceful"))
+ else
+ host.exec puppet_resource('service', service, 'ensure=stopped')
+ host.exec puppet_resource('service', service, 'ensure=running')
+ end
curl_with_retries(" #{service} ", host, "https://localhost:8140", [35, 60], curl_retries)
end
# Blocks until the port is open on the host specified, returns false
# on failure
@@ -767,83 +915,80 @@
# @param [Block] block This method will yield to a block of code passed
# by the caller; this can be used for additional
# validation, etc.
#
def apply_manifest_on(host, manifest, opts = {}, &block)
- if host.is_a?(Array)
- return host.map do |h|
- apply_manifest_on(h, manifest, opts, &block)
- end
- end
+ block_on host do | host |
- on_options = {}
- on_options[:acceptable_exit_codes] = Array(opts[:acceptable_exit_codes])
+ on_options = {}
+ on_options[:acceptable_exit_codes] = Array(opts[:acceptable_exit_codes])
- puppet_apply_opts = {}
- puppet_apply_opts[:verbose] = nil
- puppet_apply_opts[:parseonly] = nil if opts[:parseonly]
- puppet_apply_opts[:trace] = nil if opts[:trace]
- puppet_apply_opts[:parser] = 'future' if opts[:future_parser]
- puppet_apply_opts[:modulepath] = opts[:modulepath] if opts[:modulepath]
- puppet_apply_opts[:noop] = nil if opts[:noop]
+ puppet_apply_opts = {}
+ puppet_apply_opts[:verbose] = nil
+ puppet_apply_opts[:parseonly] = nil if opts[:parseonly]
+ puppet_apply_opts[:trace] = nil if opts[:trace]
+ puppet_apply_opts[:parser] = 'future' if opts[:future_parser]
+ puppet_apply_opts[:modulepath] = opts[:modulepath] if opts[:modulepath]
+ puppet_apply_opts[:noop] = nil if opts[:noop]
- # From puppet help:
- # "... an exit code of '2' means there were changes, an exit code of
- # '4' means there were failures during the transaction, and an exit
- # code of '6' means there were both changes and failures."
- if [opts[:catch_changes],opts[:catch_failures],opts[:expect_failures],opts[:expect_changes]].compact.length > 1
- raise(ArgumentError,
- 'Cannot specify more than one of `catch_failures`, ' +
- '`catch_changes`, `expect_failures`, or `expect_changes` ' +
- 'for a single manifest')
- end
+ # From puppet help:
+ # "... an exit code of '2' means there were changes, an exit code of
+ # '4' means there were failures during the transaction, and an exit
+ # code of '6' means there were both changes and failures."
+ if [opts[:catch_changes],opts[:catch_failures],opts[:expect_failures],opts[:expect_changes]].compact.length > 1
+ raise(ArgumentError,
+ 'Cannot specify more than one of `catch_failures`, ' +
+ '`catch_changes`, `expect_failures`, or `expect_changes` ' +
+ 'for a single manifest')
+ end
- if opts[:catch_changes]
- puppet_apply_opts['detailed-exitcodes'] = nil
+ if opts[:catch_changes]
+ puppet_apply_opts['detailed-exitcodes'] = nil
- # We're after idempotency so allow exit code 0 only.
- on_options[:acceptable_exit_codes] |= [0]
- elsif opts[:catch_failures]
- puppet_apply_opts['detailed-exitcodes'] = nil
+ # We're after idempotency so allow exit code 0 only.
+ on_options[:acceptable_exit_codes] |= [0]
+ elsif opts[:catch_failures]
+ puppet_apply_opts['detailed-exitcodes'] = nil
- # We're after only complete success so allow exit codes 0 and 2 only.
- on_options[:acceptable_exit_codes] |= [0, 2]
- elsif opts[:expect_failures]
- puppet_apply_opts['detailed-exitcodes'] = nil
+ # We're after only complete success so allow exit codes 0 and 2 only.
+ on_options[:acceptable_exit_codes] |= [0, 2]
+ elsif opts[:expect_failures]
+ puppet_apply_opts['detailed-exitcodes'] = nil
- # We're after failures specifically so allow exit codes 1, 4, and 6 only.
- on_options[:acceptable_exit_codes] |= [1, 4, 6]
- elsif opts[:expect_changes]
- puppet_apply_opts['detailed-exitcodes'] = nil
+ # We're after failures specifically so allow exit codes 1, 4, and 6 only.
+ on_options[:acceptable_exit_codes] |= [1, 4, 6]
+ elsif opts[:expect_changes]
+ puppet_apply_opts['detailed-exitcodes'] = nil
- # We're after changes specifically so allow exit code 2 only.
- on_options[:acceptable_exit_codes] |= [2]
- else
- # Either use the provided acceptable_exit_codes or default to [0]
- on_options[:acceptable_exit_codes] |= [0]
- end
+ # We're after changes specifically so allow exit code 2 only.
+ on_options[:acceptable_exit_codes] |= [2]
+ else
+ # Either use the provided acceptable_exit_codes or default to [0]
+ on_options[:acceptable_exit_codes] |= [0]
+ end
- # Not really thrilled with this implementation, might want to improve it
- # later. Basically, there is a magic trick in the constructor of
- # PuppetCommand which allows you to pass in a Hash for the last value in
- # the *args Array; if you do so, it will be treated specially. So, here
- # we check to see if our caller passed us a hash of environment variables
- # that they want to set for the puppet command. If so, we set the final
- # value of *args to a new hash with just one entry (the value of which
- # is our environment variables hash)
- if opts.has_key?(:environment)
- puppet_apply_opts['ENV'] = opts[:environment]
- end
+ # Not really thrilled with this implementation, might want to improve it
+ # later. Basically, there is a magic trick in the constructor of
+ # PuppetCommand which allows you to pass in a Hash for the last value in
+ # the *args Array; if you do so, it will be treated specially. So, here
+ # we check to see if our caller passed us a hash of environment variables
+ # that they want to set for the puppet command. If so, we set the final
+ # value of *args to a new hash with just one entry (the value of which
+ # is our environment variables hash)
+ if opts.has_key?(:environment)
+ puppet_apply_opts['ENV'] = opts[:environment]
+ end
- file_path = host.tmpfile('apply_manifest.pp')
- create_remote_file(host, file_path, manifest + "\n")
+ file_path = host.tmpfile('apply_manifest.pp')
+ create_remote_file(host, file_path, manifest + "\n")
- if host[:default_apply_opts].respond_to? :merge
- puppet_apply_opts = host[:default_apply_opts].merge( puppet_apply_opts )
- end
+ if host[:default_apply_opts].respond_to? :merge
+ puppet_apply_opts = host[:default_apply_opts].merge( puppet_apply_opts )
+ end
- on host, puppet('apply', file_path, puppet_apply_opts), on_options, &block
+ on host, puppet('apply', file_path, puppet_apply_opts), on_options, &block
+ end
end
# Runs 'puppet apply' on default host, piping manifest through stdin
# @see #apply_manifest_on
def apply_manifest(manifest, opts = {}, &block)
@@ -851,73 +996,74 @@
end
# @deprecated
def run_agent_on(host, arg='--no-daemonize --verbose --onetime --test',
options={}, &block)
- if host.is_a? Array
- host.each { |h| run_agent_on h, arg, options, &block }
- else
+ block_on host do | host |
on host, puppet_agent(arg), options, &block
end
end
# FIX: this should be moved into host/platform
# @visibility private
def run_cron_on(host, action, user, entry="", &block)
- platform = host['platform']
- if platform.include?('solaris') || platform.include?('aix') then
- case action
- when :list then args = '-l'
- when :remove then args = '-r'
- when :add
- on( host,
- "echo '#{entry}' > /var/spool/cron/crontabs/#{user}",
- &block )
- end
+ block_on host do | host |
+ platform = host['platform']
+ if platform.include?('solaris') || platform.include?('aix') then
+ case action
+ when :list then args = '-l'
+ when :remove then args = '-r'
+ when :add
+ on( host,
+ "echo '#{entry}' > /var/spool/cron/crontabs/#{user}",
+ &block )
+ end
- else # default for GNU/Linux platforms
- case action
- when :list then args = '-l -u'
- when :remove then args = '-r -u'
- when :add
- on( host,
- "echo '#{entry}' > /tmp/#{user}.cron && " +
- "crontab -u #{user} /tmp/#{user}.cron",
- &block )
+ else # default for GNU/Linux platforms
+ case action
+ when :list then args = '-l -u'
+ when :remove then args = '-r -u'
+ when :add
+ on( host,
+ "echo '#{entry}' > /tmp/#{user}.cron && " +
+ "crontab -u #{user} /tmp/#{user}.cron",
+ &block )
+ end
end
- end
- if args
- case action
- when :list, :remove then on(host, "crontab #{args} #{user}", &block)
+ if args
+ case action
+ when :list, :remove then on(host, "crontab #{args} #{user}", &block)
+ end
end
end
end
# This method accepts a block and using the puppet resource 'host' will
# setup host aliases before and after that block.
#
# A teardown step is also added to make sure unstubbing of the host is
# removed always.
#
- # @param machine [String] the host to execute this stub
+ # @param [Host, Array<Host>, String, Symbol] machine One or more hosts to act upon,
+ # or a role (String or Symbol) that identifies one or more hosts.
# @param ip_spec [Hash{String=>String}] a hash containing the host to ip
# mappings
# @example Stub puppetlabs.com on the master to 127.0.0.1
# stub_hosts_on(master, 'puppetlabs.com' => '127.0.0.1')
def stub_hosts_on(machine, ip_spec)
- ip_spec.each do |host, ip|
- logger.notify("Stubbing host #{host} to IP #{ip} on machine #{machine}")
- on( machine,
- puppet('resource', 'host', host, 'ensure=present', "ip=#{ip}") )
- end
+ block_on machine do | host |
+ ip_spec.each do |address, ip|
+ logger.notify("Stubbing address #{address} to IP #{ip} on machine #{host}")
+ on( host, puppet('resource', 'host', address, 'ensure=present', "ip=#{ip}") )
+ end
- teardown do
- ip_spec.each do |host, ip|
- logger.notify("Unstubbing host #{host} to IP #{ip} on machine #{machine}")
- on( machine,
- puppet('resource', 'host', host, 'ensure=absent') )
+ teardown do
+ ip_spec.each do |address, ip|
+ logger.notify("Unstubbing address #{address} to IP #{ip} on machine #{host}")
+ on( host, puppet('resource', 'host', address, 'ensure=absent') )
+ end
end
end
end
# This method accepts a block and using the puppet resource 'host' will
@@ -941,12 +1087,14 @@
# global options hash
def stub_forge_on(machine, forge_host = nil)
#use global options hash
forge_host ||= options[:forge_host]
@forge_ip ||= Resolv.getaddress(forge_host)
- stub_hosts_on(machine, 'forge.puppetlabs.com' => @forge_ip)
- stub_hosts_on(machine, 'forgeapi.puppetlabs.com' => @forge_ip)
+ block_on machine do | host |
+ stub_hosts_on(host, 'forge.puppetlabs.com' => @forge_ip)
+ stub_hosts_on(host, 'forgeapi.puppetlabs.com' => @forge_ip)
+ end
end
# This wraps the method `stub_hosts` and makes the stub specific to
# the forge alias.
#
@@ -1022,36 +1170,40 @@
end
return false
end
#stops the puppet agent running on the host
+ # @param [Host, Array<Host>, String, Symbol] agent One or more hosts to act upon,
+ # or a role (String or Symbol) that identifies one or more hosts.
def stop_agent_on(agent)
- vardir = agent.puppet['vardir']
- agent_running = true
- while agent_running
- result = on agent, "[ -e '#{vardir}/state/agent_catalog_run.lock' ]", :acceptable_exit_codes => [0,1]
- agent_running = (result.exit_code == 0)
- sleep 2 unless agent_running
- end
+ block_on agent do | host |
+ vardir = agent.puppet['vardir']
+ agent_running = true
+ while agent_running
+ result = on host, "[ -e '#{vardir}/state/agent_catalog_run.lock' ]", :acceptable_exit_codes => [0,1]
+ agent_running = (result.exit_code == 0)
+ sleep 2 unless agent_running
+ end
- # The agent service is `pe-puppet` everywhere EXCEPT certain linux distros on PE 2.8
- # In all the case that it is different, this init script will exist. So we can assume
- # that if the script doesn't exist, we should just use `pe-puppet`
- result = on agent, "[ -e /etc/init.d/pe-puppet-agent ]", :acceptable_exit_codes => [0,1]
- agent_service = (result.exit_code == 0) ? 'pe-puppet-agent' : 'pe-puppet'
+ # The agent service is `pe-puppet` everywhere EXCEPT certain linux distros on PE 2.8
+ # In all the case that it is different, this init script will exist. So we can assume
+ # that if the script doesn't exist, we should just use `pe-puppet`
+ result = on agent, "[ -e /etc/init.d/pe-puppet-agent ]", :acceptable_exit_codes => [0,1]
+ agent_service = (result.exit_code == 0) ? 'pe-puppet-agent' : 'pe-puppet'
- # Under a number of stupid circumstances, we can't stop the
- # agent using puppet. This is usually because of issues with
- # the init script or system on that particular configuration.
- avoid_puppet_at_all_costs = false
- avoid_puppet_at_all_costs ||= agent['platform'] =~ /el-4/
- avoid_puppet_at_all_costs ||= agent['pe_ver'] && version_is_less(agent['pe_ver'], '3.2') && agent['platform'] =~ /sles/
+ # Under a number of stupid circumstances, we can't stop the
+ # agent using puppet. This is usually because of issues with
+ # the init script or system on that particular configuration.
+ avoid_puppet_at_all_costs = false
+ avoid_puppet_at_all_costs ||= agent['platform'] =~ /el-4/
+ avoid_puppet_at_all_costs ||= agent['pe_ver'] && version_is_less(agent['pe_ver'], '3.2') && agent['platform'] =~ /sles/
- if avoid_puppet_at_all_costs
- on agent, "/etc/init.d/#{agent_service} stop"
- else
- on agent, puppet_resource('service', agent_service, 'ensure=stopped')
+ if avoid_puppet_at_all_costs
+ on agent, "/etc/init.d/#{agent_service} stop"
+ else
+ on agent, puppet_resource('service', agent_service, 'ensure=stopped')
+ end
end
end
#stops the puppet agent running on the default host
# @see #stop_agent_on
@@ -1066,35 +1218,38 @@
retry_command("Wait for #{hostname} to be in the console", dashboard, "! curl --sslv3 -k -I https://#{dashboard}/nodes/#{hostname} | grep '404 Not Found'")
end
# Ensure the host has requested a cert, then sign it
#
- # @param [Host] host The host to sign for
+ # @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon,
+ # or a role (String or Symbol) that identifies one or more hosts.
#
# @return nil
# @raise [FailTest] if process times out
def sign_certificate_for(host)
- if [master, dashboard, database].include? host
+ block_on host do | host |
+ if [master, dashboard, database].include? host
- on host, puppet( 'agent -t' ), :acceptable_exit_codes => [0,1,2]
- on master, puppet( "cert --allow-dns-alt-names sign #{host}" ), :acceptable_exit_codes => [0,24]
+ on host, puppet( 'agent -t' ), :acceptable_exit_codes => [0,1,2]
+ on master, puppet( "cert --allow-dns-alt-names sign #{host}" ), :acceptable_exit_codes => [0,24]
- else
+ else
- hostname = Regexp.escape host.node_name
+ hostname = Regexp.escape host.node_name
- last_sleep = 0
- next_sleep = 1
- (0..10).each do |i|
- fail_test("Failed to sign cert for #{hostname}") if i == 10
+ last_sleep = 0
+ next_sleep = 1
+ (0..10).each do |i|
+ fail_test("Failed to sign cert for #{hostname}") if i == 10
- on master, puppet("cert --sign --all"), :acceptable_exit_codes => [0,24]
- break if on(master, puppet("cert --list --all")).stdout =~ /\+ "?#{hostname}"?/
- sleep next_sleep
- (last_sleep, next_sleep) = next_sleep, last_sleep+next_sleep
- end
+ on master, puppet("cert --sign --all"), :acceptable_exit_codes => [0,24]
+ break if on(master, puppet("cert --list --all")).stdout =~ /\+ "?#{hostname}"?/
+ sleep next_sleep
+ (last_sleep, next_sleep) = next_sleep, last_sleep+next_sleep
+ end
+ end
end
end
#prompt the master to sign certs then check to confirm the cert for the default host is signed
#@see #sign_certificate_for
@@ -1102,19 +1257,24 @@
sign_certificate_for(default)
end
# Get a facter fact from a provided host
#
- # @param [Host] host The host to query the fact for
+ # @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon,
+ # or a role (String or Symbol) that identifies one or more hosts.
# @param [String] name The name of the fact to query for
# @!macro common_opts
#
# @return String The value of the fact 'name' on the provided host
# @raise [FailTest] Raises an exception if call to facter fails
def fact_on(host, name, opts = {})
result = on host, facter(name, opts)
- result.stdout.chomp if result.stdout
+ if result.kind_of?(Array)
+ result.map { |res| res.stdout.chomp }
+ else
+ result.stdout.chomp
+ end
end
# Get a facter fact from the default host
# @see #fact_on
def fact(name, opts = {})
@@ -1198,10 +1358,10 @@
# @return [String] module name
def parse_for_modulename(root_module_dir)
module_name = nil
if File.exists?("#{root_module_dir}/metadata.json")
logger.debug "Attempting to parse Modulename from metadata.json"
- module_json = JSON.parse (File.read "#{root_module_dir}/metadata.json")
+ module_json = JSON.parse(File.read "#{root_module_dir}/metadata.json")
if(module_json.has_key?('name'))
module_name = get_module_name(module_json['name'])
end
end
if !module_name && File.exists?("#{root_module_dir}/Modulefile")