lib/beaker/dsl/helpers.rb in beaker-1.12.2 vs lib/beaker/dsl/helpers.rb in beaker-1.13.0

- old
+ new

@@ -271,10 +271,44 @@ scp_to hosts, tempfile.path, file_path, opts end end + # Create a temp directory on remote host owned by specified user. + # + # @param [Host] host A single remote host on which to create and adjust + # the ownership of a temp directory. + # @param [String] name A remote path prefix for the new temp + # directory. Default value is '/tmp/beaker' + # @param [String] user The name of user that should own the temp + # directory. If no username is specified, use `puppet master + # --configprint user` to obtain username from master. Raise RuntimeError + # if this puppet command returns a non-zero exit code. + # + # @return [String] Returns the name of the newly-created file. + def create_tmpdir_for_user(host, name='/tmp/beaker', user=nil) + if not user + result = on(host, "puppet master --configprint user") + if not result.exit_code == 0 + raise "`puppet master --configprint` failed, check that puppet is installed on #{host} or explicitly pass in a user name." + end + user = result.stdout.strip + end + + if not on(host, "getent passwd #{user}").exit_code == 0 + raise "User #{user} does not exist on #{host}." + end + + if defined? host.tmpdir + dir = host.tmpdir(name) + on host, "chown #{user}.#{user} #{dir}" + return dir + else + raise "Host platform not supported by `create_tmpdir_for_user`." + end + end + # Move a local script to a remote host and execute it # @note this relies on {#on} and {#scp_to} # # @param [Host, #do_scp_to] host One or more hosts (or some object # that responds like @@ -716,10 +750,14 @@ # @option opts [Boolean] :future_parser (false) This option enables # the future parser option that is available # from Puppet verion 3.2 # By default it will use the 'current' parser. # + # @option opts [Boolean] :noop (false) If this option exists, the + # the "--noop" command line parameter will be + # passed to the 'puppet apply' command. + # # @option opts [String] :modulepath The search path for modules, as # a list of directories separated by the system # path separator character. (The POSIX path separator # is ‘:’, and the Windows path separator is ‘;’.) # @@ -735,40 +773,46 @@ 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] - args << "--parser future" if opts[:future_parser] - args << "--modulepath #{opts[:modulepath]}" if opts[:modulepath] + 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]].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") + 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] - args << '--detailed-exitcodes' + 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] - args << '--detailed-exitcodes' + 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] - args << '--detailed-exitcodes' + 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] - args << '--detailed-exitcodes' + 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] @@ -782,17 +826,21 @@ # 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]} + puppet_apply_opts['ENV'] = 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 + + 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 end # Runs 'puppet apply' on default host, piping manifest through stdin # @see #apply_manifest_on def apply_manifest(manifest, opts = {}, &block) @@ -914,21 +962,29 @@ def curl_with_retries(desc, host, url, desired_exit_codes, max_retries = 60, retry_interval = 1) retry_command(desc, host, "curl -m 1 #{url}", desired_exit_codes, max_retries, retry_interval) end - def retry_command(desc, host, command, desired_exit_codes = 0, max_retries = 60, retry_interval = 1) + def retry_command(desc, host, command, desired_exit_codes = 0, + max_retries = 60, retry_interval = 1, verbose = false) + log_prefix = host.log_prefix + @logger.debug "\n#{log_prefix} #{Time.new.strftime('%H:%M:%S')}$ #{command}" + @logger.debug " Trying command #{max_retries} times." + @logger.debug ".", add_newline=false desired_exit_codes = [desired_exit_codes].flatten - result = on host, command, :acceptable_exit_codes => (0...127) + result = on host, command, {:acceptable_exit_codes => (0...127), :silent => !verbose} num_retries = 0 until desired_exit_codes.include?(result.exit_code) sleep retry_interval - result = on host, command, :acceptable_exit_codes => (0...127) + result = on host, command, {:acceptable_exit_codes => (0...127), :silent => !verbose} num_retries += 1 + @logger.debug ".", add_newline=false if (num_retries > max_retries) - fail("Unable to #{desc}") + @logger.debug " Command \`#{command}\` failed." + fail("Command \`#{command}\` failed.") end end + @logger.debug "\n#{log_prefix} #{Time.new.strftime('%H:%M:%S')}$ #{command} ostensibly successful." end #Is semver-ish version a less than semver-ish version b #@param [String] a A version of the from '\d.\d.\d.*' #@param [String] b A version of the form '\d.\d.\d.*'