Module: Beaker::DSL::Helpers

Included in:
Beaker::DSL
Defined in:
lib/beaker/dsl/helpers.rb

Overview

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 and execute remote scripts, confine test cases to certain hosts and prepare the state of a test case.

To mix this is into a class you need the following:

  • a method hosts that yields any hosts implementing Host‘s interface to act upon.

  • a method logger that yields a logger implementing Logger‘s interface.

  • the module Roles that provides access to the various hosts implementing Host‘s interface to act upon

  • the module Wrappers the provides convenience methods for Command creation

Instance Method Summary collapse

Instance Method Details

#apply_manifest(manifest, opts = {}, &block) ⇒ Object

Runs ‘puppet apply’ on default host, piping manifest through stdin

See Also:



763
764
765
# File 'lib/beaker/dsl/helpers.rb', line 763

def apply_manifest(manifest, opts = {}, &block)
  apply_manifest_on(default, manifest, opts, &block)
end

#apply_manifest_on(host, manifest, opts = {}, &block) ⇒ Object

Runs ‘puppet apply’ on a remote host, piping manifest through stdin

Parameters:

  • host (Host)

    The host that this command should be run on

  • manifest (String)

    The puppet manifest to apply

  • opts (Hash{Symbol=>String}) (defaults to: {})

    Options to alter execution.

  • block (Block)

    This method will yield to a block of code passed by the caller; this can be used for additional validation, etc.

Options Hash (opts):

  • :silent (Boolean) — default: false

    Do not produce log output

  • :acceptable_exit_codes (Array<Fixnum>) — default: [0]

    An array (or range) of integer exit codes that should be considered acceptable. An error will be thrown if the exit code does not match one of the values in this list.

  • :environment (Hash{String=>String}) — default: {}

    These will be treated as extra environment variables that should be set before running the command.

  • :parseonly (Boolean) — default: false

    If this key is true, the “–parseonly” command line parameter will be passed to the ‘puppet apply’ command.

  • :trace (Boolean) — default: false

    If this key exists in the Hash, the “–trace” command line parameter will be passed to the ‘puppet apply’ command.

  • :acceptable_exit_codes (Array<Integer>) — default: [0]

    The list of exit codes that will NOT raise an error when found upon command completion. If provided, these values will be combined with those used in :catch_failures and :expect_failures to create the full list of passing exit codes.

  • :catch_failures (Boolean) — default: false

    By default ‘puppet –apply` will exit with 0, which does not count as a test failure, even if there were errors or changes when applying the manifest. This option enables detailed exit codes and causes a test failure if `puppet –apply` indicates there was a failure during its execution.

  • :catch_changes (Boolean) — default: false

    This option enables detailed exit codes and causes a test failure if ‘puppet –apply` indicates that there were changes or failures during its execution.

  • :expect_changes (Boolean) — default: false

    This option enables detailed exit codes and causes a test failure if ‘puppet –apply` indicates that there were no resource changes during its execution.

  • :expect_failures (Boolean) — default: false

    This option enables detailed exit codes and causes a test failure if ‘puppet –apply` indicates there were no failure during its execution.



697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
# File 'lib/beaker/dsl/helpers.rb', line 697

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

  on_options = {}
  on_options[:acceptable_exit_codes] = Array(opts[:acceptable_exit_codes])

  args = ["--verbose"]
  args << "--parseonly" if opts[:parseonly]
  args << "--trace" if opts[:trace]

  # 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]].select{|x|x}.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]
    args << '--detailed-exitcodes'

    # We're after idempotency so allow exit code 0 only.
    on_options[:acceptable_exit_codes] |= [0]
  elsif opts[:catch_failures]
    args << '--detailed-exitcodes'

    # 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]
    args << '--detailed-exitcodes'

    # 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]
    args << '--detailed-exitcodes'

    # 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)
    args << { :environment => opts[:environment]}
  end

  file_path = host.tmpfile('apply_manifest.pp')
  create_remote_file(host, file_path, manifest + "\n")
  args << file_path
  on host, puppet( 'apply', *args), on_options, &block
end

#check_for_package(host, package_name) ⇒ Boolean

Check to see if a package is installed on a remote host

Parameters:

  • host (Host)

    A host object

  • package_name (String)

    Name of the package to check for.

Returns:

  • (Boolean)

    true/false if the package is found



213
214
215
# File 'lib/beaker/dsl/helpers.rb', line 213

def check_for_package host, package_name
  host.check_for_package package_name
end

#confine(type, criteria, host_array = nil, &block) ⇒ Array<Host>

Note:

This will modify the TestCase#hosts member in place unless an array of hosts is passed into it and TestCase#logger yielding an object that responds like Logger#warn, as well as Outcomes#skip_test, and optionally TestCase#hosts.

Limit the hosts a test case is run against

Examples:

Basic usage to confine to debian OSes.

confine :to, :platform => 'debian'

Confining to anything but Windows and Solaris

confine :except, :platform => ['windows', 'solaris']

Using additional block to confine to Solaris global zone.

confine :to, :platform => 'solaris' do |solaris|
  on( solaris, 'zonename' ) =~ /global/
end

Parameters:

  • type (Symbol)

    The type of confinement to do. Valid parameters are :to to confine the hosts to only those that match criteria or :except to confine the test case to only those hosts that do not match criteria.

  • criteria (Hash{Symbol,String=>String,Regexp,Array<String,Regexp>})

    Specify the criteria with which a host should be considered for inclusion or exclusion. The key is any attribute of the host that will be yielded by 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.

  • host_array (Array<Host>) (defaults to: nil)

    This creatively named parameter is an optional array of hosts to confine to. If not passed in, this method will modify TestCase#hosts in place.

  • block (Proc)

    Addition checks to determine suitability of hosts for confinement. 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.

Returns:

  • (Array<Host>)

    Returns an array of hosts that are still valid targets for this tests case.

Raises:

  • (SkipTest)

    Raises skip test if there are no valid hosts for this test case after confinement.



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/beaker/dsl/helpers.rb', line 349

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
  end
  if hosts_to_modify.empty?
    logger.warn "No suitable hosts with: #{criteria.inspect}"
    skip_test 'No suitable hosts found'
  end
  self.hosts = hosts_to_modify
  hosts_to_modify
end

#confine_block(type, criteria, host_array = nil, &block) ⇒ Object

Ensures that host restrictions as specifid by type, criteria and host_array are confined to activity within the passed block. TestCase#hosts is reset after block has executed.

See Also:



389
390
391
392
393
394
395
396
397
398
399
# File 'lib/beaker/dsl/helpers.rb', line 389

def confine_block(type, criteria, host_array = nil, &block)
  begin
    original_hosts = self.hosts.dup
    confine(type, criteria, host_array)

    yield

  ensure
    self.hosts = original_hosts
  end
end

#create_remote_file(hosts, file_path, file_content, opts = {}) ⇒ Result

Note:

This method uses Tempfile in Ruby’s STDLIB as well as #scp_to.

Create a remote file out of a string

Parameters:

  • hosts (Host, #do_scp_to)

    One or more hosts (or some object that responds like Host#do_scp_from.

  • file_path (String)

    A remote path to place file_content at.

  • file_content (String)

    The contents of the file to be placed.

  • opts (Hash{Symbol=>String}) (defaults to: {})

    Options to alter execution.

Options Hash (opts):

  • :silent (Boolean) — default: false

    Do not produce log output

  • :acceptable_exit_codes (Array<Fixnum>) — default: [0]

    An array (or range) of integer exit codes that should be considered acceptable. An error will be thrown if the exit code does not match one of the values in this list.

  • :environment (Hash{String=>String}) — default: {}

    These will be treated as extra environment variables that should be set before running the command.

Returns:

  • (Result)

    Returns the result of the underlying SCP operation.



267
268
269
270
271
272
273
# File 'lib/beaker/dsl/helpers.rb', line 267

def create_remote_file(hosts, file_path, file_content, opts = {})
  Tempfile.open 'beaker' do |tempfile|
    File.open(tempfile.path, 'w') {|file| file.puts file_content }

    scp_to hosts, tempfile.path, file_path, opts
  end
end

#curl_on(host, cmd, opts = {}, &block) ⇒ Object

Run a curl command on the provided host(s)

Parameters:

  • host (Host, Array<Host>, String, Symbol)

    One or more hosts to act upon, or a role (String or Symbol) that identifies one or more hosts.

  • cmd (String, Command)

    The curl command to execute on host.

  • block (Proc)

    Additional actions or assertions.

  • opts (Hash{Symbol=>String}) (defaults to: {})

    Options to alter execution.

Options Hash (opts):

  • :silent (Boolean) — default: false

    Do not produce log output

  • :acceptable_exit_codes (Array<Fixnum>) — default: [0]

    An array (or range) of integer exit codes that should be considered acceptable. An error will be thrown if the exit code does not match one of the values in this list.

  • :environment (Hash{String=>String}) — default: {}

    These will be treated as extra environment variables that should be set before running the command.



994
995
996
997
998
999
1000
# File 'lib/beaker/dsl/helpers.rb', line 994

def curl_on(host, cmd, opts = {}, &block)
  if options.is_pe? #check global options hash
    on host, "curl --sslv3 %s" % cmd, opts, &block
  else
    on host, "curl %s" % cmd, opts, &block
  end
end

#curl_with_retries(desc, host, url, desired_exit_codes, max_retries = 60, retry_interval = 1) ⇒ Object



874
875
876
# File 'lib/beaker/dsl/helpers.rb', line 874

def curl_with_retries(desc, host, url, desired_exit_codes, max_retries = 60, retry_interval = 1)
  retry_command(desc, host, "curl #{url}", desired_exit_codes, max_retries, retry_interval)
end

#deploy_package_repo(host, path, name, version) ⇒ Object

Note:

To ensure the repo configs are available for deployment, you should run ‘rake pl:jenkins:deb_repo_configs` and `rake pl:jenkins:rpm_repo_configs` on your project checkout

Deploy packaging configurations generated by github.com/puppetlabs/packaging to a host.

Parameters:

  • host (Host)
  • path (String)

    The path to the generated repository config files. ex: /myproject/pkg/repo_configs

  • name (String)

    A human-readable name for the repository

  • String[ (String[ version The version of the project, as used by the packaging tools. This can be determined with `rake pl:print_build_params` from the packaging repo.)

    version The version of the project, as used by the packaging tools. This can be determined with ‘rake pl:print_build_params` from the packaging repo.



252
253
254
# File 'lib/beaker/dsl/helpers.rb', line 252

def deploy_package_repo host, path, name, version
  host.deploy_package_repo path, name, version
end

#exit_codeObject

Deprecated.

An proxy for the last Result#exit_code returned by a method that makes remote calls. Use the Result object returned by the method directly instead. For Usage see Result.



158
159
160
161
# File 'lib/beaker/dsl/helpers.rb', line 158

def exit_code
  return nil if @result.nil?
  @result.exit_code
end

#fact(name, opts = {}) ⇒ Object

Get a facter fact from the default host

See Also:



982
983
984
# File 'lib/beaker/dsl/helpers.rb', line 982

def fact(name, opts = {})
  fact_on(default, name, opts)
end

#fact_on(host, name, opts = {}) ⇒ Object

Get a facter fact from a provided host

Parameters:

  • host (Host)

    The host to query the fact for

  • name (String)

    The name of the fact to query for

  • opts (Hash{Symbol=>String}) (defaults to: {})

    Options to alter execution.

Options Hash (opts):

  • :silent (Boolean) — default: false

    Do not produce log output

  • :acceptable_exit_codes (Array<Fixnum>) — default: [0]

    An array (or range) of integer exit codes that should be considered acceptable. An error will be thrown if the exit code does not match one of the values in this list.

  • :environment (Hash{String=>String}) — default: {}

    These will be treated as extra environment variables that should be set before running the command.

Returns:

  • String The value of the fact ‘name’ on the provided host

Raises:

  • (FailTest)

    Raises an exception if call to facter fails



975
976
977
978
# File 'lib/beaker/dsl/helpers.rb', line 975

def fact_on(host, name, opts = {})
  result = on host, facter(name, opts)
  result.stdout.chomp if result.stdout
end

#install_package(host, package_name) ⇒ Result

Install a package on a host

Parameters:

  • host (Host)

    A host object

  • package_name (String)

    Name of the package to install

Returns:

  • (Result)

    An object representing the outcome of *install command*.



223
224
225
# File 'lib/beaker/dsl/helpers.rb', line 223

def install_package host, package_name
  host.install_package package_name
end

#on(host, command, opts = {}, &block) ⇒ Result

The primary method for executing commands on some set of hosts.

Examples:

Most basic usage

on hosts, 'ls /tmp'

Allowing additional exit codes to pass

on agents, 'puppet agent -t', :acceptable_exit_codes => [0,2]

Using the returned result for any kind of checking

if on(host, 'ls -la ~').stdout =~ /\.bin/
  ...do some action...
end

Using TestCase helpers from within a test.

agents.each do |agent|
  on agent, 'cat /etc/puppet/puppet.conf' do
    assert_match stdout, /server = #{master}/, 'WTF Mate'
  end
end

Using a role (defined in a String) to identify the host

on "master", "echo hello"

Using a role (defined in a Symbol) to identify the host

on :dashboard, "echo hello"

Parameters:

  • host (Host, Array<Host>, String, Symbol)

    One or more hosts to act upon, or a role (String or Symbol) that identifies one or more hosts.

  • command (String, Command)

    The command to execute on host.

  • block (Proc)

    Additional actions or assertions.

  • opts (Hash{Symbol=>String}) (defaults to: {})

    Options to alter execution.

Options Hash (opts):

  • :silent (Boolean) — default: false

    Do not produce log output

  • :acceptable_exit_codes (Array<Fixnum>) — default: [0]

    An array (or range) of integer exit codes that should be considered acceptable. An error will be thrown if the exit code does not match one of the values in this list.

  • :environment (Hash{String=>String}) — default: {}

    These will be treated as extra environment variables that should be set before running the command.

Returns:

  • (Result)

    An object representing the outcome of command.

Raises:

  • (FailTest)

    Raises an exception if command obviously fails.



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/beaker/dsl/helpers.rb', line 71

def on(host, command, opts = {}, &block)
  unless command.is_a? Command
    cmd_opts = {}
    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
        #block with arity of 0, just hand back yourself
        when 0
          yield self
        #block with arity of 1 or greater, hand back the result object
        else 
          yield @result
      end
    end

    return @result
  end
end

#port_open_within?(host, port = 8140, seconds = 120) ⇒ Boolean

Blocks until the port is open on the host specified, returns false on failure

Returns:

  • (Boolean)


639
640
641
642
643
# File 'lib/beaker/dsl/helpers.rb', line 639

def port_open_within?( host, port = 8140, seconds = 120 )
  repeat_for( seconds ) do
    host.port_open?( port )
  end
end

#retry_command(desc, host, command, desired_exit_codes = 0, max_retries = 60, retry_interval = 1) ⇒ Object



878
879
880
881
882
883
884
885
886
887
888
889
890
# File 'lib/beaker/dsl/helpers.rb', line 878

def retry_command(desc, host, command, desired_exit_codes = 0, max_retries = 60, retry_interval = 1)
  desired_exit_codes = [desired_exit_codes].flatten
  result = on host, command, :acceptable_exit_codes => (0...127)
  num_retries = 0
  until desired_exit_codes.include?(result.exit_code)
    sleep retry_interval
    result = on host, command, :acceptable_exit_codes => (0...127)
    num_retries += 1
    if (num_retries > max_retries)
      fail("Unable to #{desc}")
    end
  end
end

#run_agent_on(host, arg = '--no-daemonize --verbose --onetime --test', options = {}, &block) ⇒ Object

Deprecated.


768
769
770
771
772
773
774
775
# File 'lib/beaker/dsl/helpers.rb', line 768

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
    on host, puppet_agent(arg), options, &block
  end
end

#run_script(script, opts = {}, &block) ⇒ Object

Move a local script to default host and execute it

See Also:



301
302
303
# File 'lib/beaker/dsl/helpers.rb', line 301

def run_script(script, opts = {}, &block)
  run_script_on(default, script, opts, &block)
end

#run_script_on(host, script, opts = {}, &block) ⇒ Result

Note:

this relies on #on and #scp_to

Move a local script to a remote host and execute it

Parameters:

  • host (Host, #do_scp_to)

    One or more hosts (or some object that responds like Host#do_scp_from.

  • script (String)

    A local path to find an executable script at.

  • opts (Hash{Symbol=>String}) (defaults to: {})

    Options to alter execution.

  • block (Proc)

    Additional tests to run after script has executed

Options Hash (opts):

  • :silent (Boolean) — default: false

    Do not produce log output

  • :acceptable_exit_codes (Array<Fixnum>) — default: [0]

    An array (or range) of integer exit codes that should be considered acceptable. An error will be thrown if the exit code does not match one of the values in this list.

  • :environment (Hash{String=>String}) — default: {}

    These will be treated as extra environment variables that should be set before running the command.

Returns:

  • (Result)

    Returns the result of the underlying SCP operation.



286
287
288
289
290
291
292
293
294
295
296
297
# File 'lib/beaker/dsl/helpers.rb', line 286

def run_script_on(host, script, opts = {}, &block)
  # this is unsafe as it uses the File::SEPARATOR will be set to that
  # of the coordinator node.  This works for us because we use cygwin
  # which will properly convert the paths.  Otherwise this would not
  # work for running tests on a windows machine when the coordinator
  # that the harness is running on is *nix. We should use
  # {Beaker::Host#temp_path} instead. TODO
  remote_path = File.join("", "tmp", File.basename(script))

  scp_to host, script, remote_path
  on host, remote_path, opts, &block
end

#scp_from(host, from_path, to_path, opts = {}) ⇒ Result

Note:

If using Host for the hosts scp is not required on the system as it uses Ruby’s net/scp library. The net-scp gem however is required (and specified in the gemspec).

Move a file from a remote to a local path

Parameters:

  • host (Host, #do_scp_from)

    One or more hosts (or some object that responds like Host#do_scp_from.

  • from_path (String)

    A remote path to a file.

  • to_path (String)

    A local path to copy from_path to.

  • opts (Hash{Symbol=>String}) (defaults to: {})

    Options to alter execution.

Options Hash (opts):

  • :silent (Boolean) — default: false

    Do not produce log output

  • :acceptable_exit_codes (Array<Fixnum>) — default: [0]

    An array (or range) of integer exit codes that should be considered acceptable. An error will be thrown if the exit code does not match one of the values in this list.

  • :environment (Hash{String=>String}) — default: {}

    These will be treated as extra environment variables that should be set before running the command.

Returns:

  • (Result)

    Returns the result of the SCP operation



176
177
178
179
180
181
182
183
# File 'lib/beaker/dsl/helpers.rb', line 176

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
    @result = host.do_scp_from(from_path, to_path, opts)
    @result.log logger
  end
end

#scp_to(host, from_path, to_path, opts = {}) ⇒ Result

Note:

If using Host for the hosts scp is not required on the system as it uses Ruby’s net/scp library. The net-scp gem however is required (and specified in the gemspec.

Move a local file to a remote host

Parameters:

  • host (Host, #do_scp_to)

    One or more hosts (or some object that responds like Host#do_scp_to.

  • from_path (String)

    A local path to a file.

  • to_path (String)

    A remote path to copy from_path to.

  • opts (Hash{Symbol=>String}) (defaults to: {})

    Options to alter execution.

Options Hash (opts):

  • :silent (Boolean) — default: false

    Do not produce log output

  • :acceptable_exit_codes (Array<Fixnum>) — default: [0]

    An array (or range) of integer exit codes that should be considered acceptable. An error will be thrown if the exit code does not match one of the values in this list.

  • :environment (Hash{String=>String}) — default: {}

    These will be treated as extra environment variables that should be set before running the command.

Returns:

  • (Result)

    Returns the result of the SCP operation



198
199
200
201
202
203
204
205
# File 'lib/beaker/dsl/helpers.rb', line 198

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
    @result = host.do_scp_to(from_path, to_path, opts)
    @result.log logger
  end
end

#shell(command, opts = {}, &block) ⇒ Result

The method for executing commands on the default host

Examples:

Most basic usage

shell 'ls /tmp'

Allowing additional exit codes to pass

shell 'puppet agent -t', :acceptable_exit_codes => [0,2]

Using the returned result for any kind of checking

if shell('ls -la ~').stdout =~ /\.bin/
  ...do some action...
end

Using TestCase helpers from within a test.

agents.each do |agent|
  shell('cat /etc/puppet/puppet.conf') do |result|
    assert_match result.stdout, /server = #{master}/, 'WTF Mate'
  end
end

Parameters:

  • command (String, Command)

    The command to execute on host.

  • block (Proc)

    Additional actions or assertions.

  • opts (Hash{Symbol=>String}) (defaults to: {})

    Options to alter execution.

Options Hash (opts):

  • :silent (Boolean) — default: false

    Do not produce log output

  • :acceptable_exit_codes (Array<Fixnum>) — default: [0]

    An array (or range) of integer exit codes that should be considered acceptable. An error will be thrown if the exit code does not match one of the values in this list.

  • :environment (Hash{String=>String}) — default: {}

    These will be treated as extra environment variables that should be set before running the command.

Returns:

  • (Result)

    An object representing the outcome of command.

Raises:

  • (FailTest)

    Raises an exception if command obviously fails.



129
130
131
# File 'lib/beaker/dsl/helpers.rb', line 129

def shell(command, opts = {}, &block)
  on(default, command, opts, &block)
end

#sign_certificateObject

prompt the master to sign certs then check to confirm the cert for the default host is signed



963
964
965
# File 'lib/beaker/dsl/helpers.rb', line 963

def sign_certificate
  sign_certificate_for(default)
end

#sign_certificate_for(host) ⇒ Object

Ensure the host has requested a cert, then sign it

Parameters:

  • host (Host)

    The host to sign for

Returns:

  • nil

Raises:



937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
# File 'lib/beaker/dsl/helpers.rb', line 937

def sign_certificate_for(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]

  else

    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

      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

#sleep_until_puppetdb_started(host) ⇒ Object



868
869
870
871
872
# File 'lib/beaker/dsl/helpers.rb', line 868

def sleep_until_puppetdb_started(host)
  curl_with_retries("start puppetdb", host, "http://localhost:8080", 0, 120)
  curl_with_retries("start puppetdb (ssl)",
                    host, "https://#{host.node_name}:8081", [35, 60])
end

#stderrObject

Deprecated.

An proxy for the last Result#stderr returned by a method that makes remote calls. Use the Result object returned by the method directly instead. For Usage see Result.



148
149
150
151
# File 'lib/beaker/dsl/helpers.rb', line 148

def stderr
  return nil if @result.nil?
  @result.stderr
end

#stdoutObject

Deprecated.

An proxy for the last Result#stdout returned by a method that makes remote calls. Use the Result object returned by the method directly instead. For Usage see Result.



138
139
140
141
# File 'lib/beaker/dsl/helpers.rb', line 138

def stdout
  return nil if @result.nil?
  @result.stdout
end

#stop_agentObject

stops the puppet agent running on the default host

See Also:



920
921
922
# File 'lib/beaker/dsl/helpers.rb', line 920

def stop_agent
  stop_agent_on(default)
end

#stop_agent_on(agent) ⇒ Object

stops the puppet agent running on the host



893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
# File 'lib/beaker/dsl/helpers.rb', line 893

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
 
  if agent['platform'].include?('solaris')
    on(agent, '/usr/sbin/svcadm disable -s svc:/network/pe-puppet:default')
  elsif agent['platform'].include?('aix')
    on(agent, '/usr/bin/stopsrc -s pe-puppet')
  elsif agent['platform'].include?('windows')
    on(agent, 'net stop pe-puppet', :acceptable_exit_codes => [0,2])
  else
    # For the sake of not passing the PE version into this method,
    # we just query the system to find out which service we want to
    # stop
    result = on agent, "[ -e /etc/init.d/pe-puppet-agent ]", :acceptable_exit_codes => [0,1]
    service = (result.exit_code == 0) ? 'pe-puppet-agent' : 'pe-puppet'
    on(agent, "/etc/init.d/#{service} stop")
  end
end

#stub_forgeObject

This wraps the method ‘stub_hosts` and makes the stub specific to the forge alias.

See Also:



864
865
866
# File 'lib/beaker/dsl/helpers.rb', line 864

def stub_forge
  stub_forge_on(default)
end

#stub_forge_on(machine) ⇒ Object

This wraps the method ‘stub_hosts_on` and makes the stub specific to the forge alias.

forge api v1 canonical source is forge.puppetlabs.com forge api v3 canonical source is forgeapi.puppetlabs.com

Parameters:

  • machine (String)

    the host to perform the stub on



854
855
856
857
858
# File 'lib/beaker/dsl/helpers.rb', line 854

def stub_forge_on(machine)
  @forge_ip ||= Resolv.getaddress(forge)
  stub_hosts_on(machine, 'forge.puppetlabs.com' => @forge_ip)
  stub_hosts_on(machine, 'forgeapi.puppetlabs.com' => @forge_ip)
end

#stub_hosts(ip_spec) ⇒ Object

This method accepts a block and using the puppet resource ‘host’ will setup host aliases before and after that block on the default host

Examples:

Stub puppetlabs.com on the default host to 127.0.0.1

stub_hosts('puppetlabs.com' => '127.0.0.1')

See Also:



843
844
845
# File 'lib/beaker/dsl/helpers.rb', line 843

def stub_hosts(ip_spec)
  stub_hosts_on(default, ip_spec)
end

#stub_hosts_on(machine, ip_spec) ⇒ Object

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.

Examples:

Stub puppetlabs.com on the master to 127.0.0.1

stub_hosts_on(master, 'puppetlabs.com' => '127.0.0.1')

Parameters:

  • machine (String)

    the host to execute this stub

  • ip_spec (Hash{String=>String})

    a hash containing the host to ip mappings



821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
# File 'lib/beaker/dsl/helpers.rb', line 821

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

  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') )
    end
  end
end

#upgrade_package(host, package_name) ⇒ Result

Upgrade a package on a host. The package must already be installed

Parameters:

  • host (Host)

    A host object

  • package_name (String)

    Name of the package to install

Returns:

  • (Result)

    An object representing the outcome of *upgrade command*.



233
234
235
# File 'lib/beaker/dsl/helpers.rb', line 233

def upgrade_package host, package_name
  host.upgrade_package package_name
end

#wait_for_host_in_dashboard(host) ⇒ Object

wait for a given host to appear in the dashboard



926
927
928
929
# File 'lib/beaker/dsl/helpers.rb', line 926

def wait_for_host_in_dashboard(host)
  hostname = host.node_name
  retry_command("Wait for #{hostname} to be in the console", dashboard, "! curl --sslv3 -k -I https://#{dashboard}/nodes/#{hostname} | grep '404 Not Found'")
end

#with_puppet_running(conf_opts, testdir = host.tmpdir(File.basename(@path)), &block) ⇒ Object

Test Puppet running in a certain run mode with specific options, on the default host



524
525
526
# File 'lib/beaker/dsl/helpers.rb', line 524

def with_puppet_running conf_opts, testdir = host.tmpdir(File.basename(@path)), &block
  with_puppet_running_on(default, conf_opts, testdir, &block)
end

#with_puppet_running_on(host, conf_opts, testdir = host.tmpdir(File.basename(@path)), &block) ⇒ Object

Test Puppet running in a certain run mode with specific options. This ensures the following steps are performed:

  1. The pre-test Puppet configuration is backed up

  2. A new Puppet configuraton file is layed down

  3. Puppet is started or restarted in the specified run mode

  4. Ensure Puppet has started correctly

  5. Further tests are yielded to

  6. Revert Puppet to the pre-test state

  7. Testing artifacts are saved in a folder named for the test

Examples:

A simple use case to ensure a master is running

with_puppet_running_on( master ) do
    ...tests that require a master...
end

Fully utilizing the possiblities of config options

with_puppet_running_on( master,
                        :main => {:logdest => '/var/blah'},
                        :master => {:masterlog => '/elswhere'},
                        :agent => {:server => 'localhost'} ) do

  ...tests to be ran...
end

Parameters:

  • host (Host)

    One object that act like Host

  • conf_opts (Hash{Symbol=>String})

    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]

    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.

  • testdir (File) (defaults to: host.tmpdir(File.basename(@path)))

    The temporary directory which will hold backup configuration, and other test artifacts.

  • block (Block)

    The point of this method, yields so tests may be ran. After the block is finished puppet will revert to a previous state.

Raises:

  • (ArgumentError)


466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
# File 'lib/beaker/dsl/helpers.rb', line 466

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__ }

  begin
    backup_file = backup_the_file(host, host['puppetpath'], testdir, 'puppet.conf')
    lay_down_new_puppet_conf host, conf_opts, testdir

    if host.is_pe?
      bounce_service( host, 'pe-httpd' )
    else
      puppet_master_started = start_puppet_from_source_on!( host, cmdline_args )
    end

    yield self if block_given?

  rescue Exception => early_exception
    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.is_pe?
        bounce_service( host, 'pe-httpd' )
      else
        if puppet_master_started
          stop_puppet_from_source_on( host )
        else
          dump_puppet_log(host)
        end
      end

    rescue Exception => teardown_exception
      begin
        if !host.is_pe?
          dump_puppet_log(host)
        end
      rescue Exception => dumping_exception
        logger.error("Raised during attempt to dump puppet logs: #{dumping_exception}")
      end

      if original_exception
        logger.error("Raised during attempt to teardown with_puppet_running_on: #{teardown_exception}\n---\n")
        raise original_exception
      else
        raise teardown_exception
      end
    end
  end
end