Please review pull request #129: Minor tweaks and new utility methods in acceptance framework test-case opened by (cprice-puppet)

Description:

This commit includes the following:

  • Minor cleanup for readability on failure error messages
  • Documentation for with_master_running_on method
  • New defaults for with_master_running_on: ** will automatically add "--daemonize" if you haven't specified either that or --no-daemonize ** will automatically add "--logdest=/log/puppetmaster.log" if you don't specify a logdest; sending acceptance framework log messages to syslog didn't seem very useful ** will automatically add "--dns_alt_names" if you don't specify it ** will automatically add "--autosign" if you don't specify it ** no longer deletes log dir between executions of master
  • New "get_puppet_tmpdir_path()" method, to hopefully start quarantining acceptance test temp files in a common location
  • Documentation for "create_remote_file" method
  • New options for create_remote_file method to ensure files are visible to "puppet" user et al: ** "mkdirs": will attempt to create parent directory structure before creating file ** "owner": a username to chown the new file to ** "group": a groupname to chown the new file to ** "mode": file permissions to chmod the new file to
  • new "mkdirs_on" method
  • new "rmdirs_on" method
  • new "file_exists_on?" method

  • Opened: Thu Feb 02 17:11:48 UTC 2012
  • Based on: puppetlabs:master (a2b32d29a0f45fcfdafc2390f16ed2d4eb350c39)
  • Requested merge: cprice-puppet:file_utility_methods (ec9bdfa9d3f1c7be3250f7b12acbb146e5dead14)

Diff follows:

diff --git a/lib/test_case.rb b/lib/test_case.rb
index 83ce60f..dacbdc5 100644
--- a/lib/test_case.rb
+++ b/lib/test_case.rb
@@ -104,7 +104,7 @@ def on(host, command, options={}, &block)
         if options[:acceptable_exit_codes].include?(exit_code)
           # cool.
         elsif options[:failing_exit_codes].include?(exit_code)
-          assert( false, "Host '#{host} exited with #{exit_code} running: #{command.cmd_line('')}" )
+          fail_test( "Host '#{host} exited with #{exit_code} running: #{command.cmd_line('')}" )
         else
           raise "Host '#{host}' exited with #{exit_code} running: #{command.cmd_line('')}"
         end
@@ -135,7 +135,7 @@ def skip_test(msg)
     @test_status = :skip
   end
   def fail_test(msg)
-    assert(false, msg)
+    flunk(msg + "\n" + pretty_call_stack_to_s + "\n")
   end
   #
   # result access
@@ -269,11 +269,37 @@ def run_cron_on(host, action, user, entry="", &block)
     end
   end
 
+  # This method performs the following steps:
+  # 1. issues start command for puppet master on specified host
+  # 2. polls until it determines that the master has started successfully
+  # 3. yields to a block of code passed by the caller
+  # 4. runs a "kill" command on the master's pid (on the specified host)
+  # 5. polls until it determines that the master has shut down successfully.
+  #
+  # Parameters:
+  # [host] the master host
+  # [arg] a string containing all of the command line arguments that you would like for the puppet master to
+  #     be started with.  Defaults to '--daemonize'.  NOTE: the following values will be added to the argument list
+  #     if they are not explicitly set in your 'args' parameter:
+  # * --daemonize
+  # * --logdest="#{host['puppetvardir']}/log/puppetmaster.log"
+  # * --dns_alt_names="puppet, $(hostname -s), $(hostname -f)"
+  # * --autosign=true
   def with_master_running_on(host, arg='--daemonize', &block)
+    # they probably want to run with daemonize.  If they pass some other arg/args but forget to re-include
+    # daemonize, we'll check and make sure they didn't explicitly specify "no-daemonize", and, failing that,
+    # we'll add daemonize to the arg string
+    if (arg !~ /(?:--daemonize)|(?:--no-daemonize)/) then arg << " --daemonize" end
+
+    if (arg !~ /--logdest/) then arg << " --logdest=\"#{master['puppetvardir']}/log/puppetmaster.log\"" end
+    if (arg !~ /--dns_alt_names/) then arg << " --dns_alt_names=\"puppet, $(hostname -s), $(hostname -f)\"" end
+    if (arg !~ /--autosign/) then arg << " --autosign=true" end
+
     on hosts, host_command('rm -rf #{host["puppetpath"]}/ssl')
     agents.each do |agent|
-      if vardir = agent['puppetvardir']
-        on agent, "rm -rf #{vardir}/*"
+      if ((vardir = agent['puppetvardir']) && File.exists?(vardir))
+        # we want to remove everything except the log directory
+        on agent, "for f in #{vardir}/*; do if [ \"$f\" != \"#{vardir}/log\" ]; then rm -r \"$f\"; fi; done"
       end
     end
 
@@ -316,14 +342,85 @@ def poll_master_until(host, verb)
     end
   end
 
-  def create_remote_file(hosts, file_path, file_content)
+  # Utility function to return a consistent place where we can/should store temp files on the nodes.  Adhering to
+  # the convention of calling this method and then creating your temp dir somewhere underneath the location it returns
+  # will make it so that a developer / user can safely delete the entire "root" dir that this function describes when
+  # they want to clean temp files off of their nodes.
+  def get_puppet_tmpdir_path()
+    "/tmp/puppet-acceptance"
+  end
+
+  # Create a file on the remote host(s).
+  # Parameters:
+  # [hosts] the hosts to create the file on
+  # [file_path] the path to the file to be created
+  # [file_content] a string containing the contents to be written to the file
+  # [options] a hash containing additional behavior options.  Currently supported:
+  # * :mkdirs (default false) if true, attempt to create the parent directories on the remote host before writing
+  #       the file
+  # * :owner (default 'root') the username of the user that the file should be owned by
+  # * :group (default 'puppet') the name of the group that the file should be owned by
+  # * :mode (default '644') the mode (file permissions) that the file should be created with
+  def create_remote_file(hosts, file_path, file_content, options = {})
+
+    default_options = {
+        :mkdirs => false,
+        :owner => "root",
+        :group => "puppet",
+        :mode => "644"
+    }
+
+    options = default_options.merge(options)
+
+
+    if (options[:mkdirs] == true) then
+      mkdirs_on(hosts, File.dirname(file_path))
+    end
+
     Tempfile.open 'puppet-acceptance' do |tempfile|
       File.open(tempfile.path, 'w') { |file| file.puts file_content }
 
       scp_to hosts, tempfile.path, file_path
+      on(hosts, "chown #{options[:owner]}:#{options[:group]} #{file_path}; chmod #{options[:mode]} #{file_path}")
     end
   end
 
+
+  # Create a directory structure on the remote hosts.
+  # Parameters:
+  # [hosts] the hosts to create the directories on
+  # [dir] the target directory to create; this method will attempt to create any missing parent directories as well
+  def mkdirs_on(hosts, dir)
+     on(hosts, "mkdir -p #{dir}")
+  end
+
+  # Remove (recursively) a directory structure on the remote hosts.
+  # Parameters:
+  # [hosts] the hosts to create the directories on
+  # [dir] the target directory to remove; this method will attempt to recursively delete all of the contents of the
+  #       specified directory
+  def rmdirs_on!(hosts, dir)
+    on(hosts, "rm -rf #{dir}")
+  end
+
+
+  # Check to see if a file exists on a host
+  # Parameters:
+  # [host] the host to check
+  # [file_path] the absolute path of a file to look for
+  #
+  # returns true if the file exists, false otherwise
+  def file_exists_on?(host, file_path)
+    result = false
+    on(host, "ruby -e \"print File.exists?('#{file_path}')\"") do
+      result = (stdout.chomp() == "true")
+    end
+    result
+  end
+
+
+
+
   def with_standard_output_to_logs
     stdout = ''
     old_stdout = $stdout
@@ -343,4 +440,42 @@ def with_standard_output_to_logs
 
     return result
   end
+
+
+  # utility method to get the current call stack and format it to a human-readable string (which some IDEs/editors
+  # will recognize as links to the line numbers in the trace)
+  def pretty_call_stack_to_s()
+
+    caller(1).collect do |line|
+      file_path, line_num = line.split(":")
+      file_path = expand_symlinks(File.expand_path(file_path))
+
+      file_path + ":" + line_num
+    end .join("\n")
+
+  end
+  private :pretty_call_stack_to_s
+
+  # utility method that takes a path as input, checks each component of the path to see if it is a symlink, and expands
+  # it if it is.  returns the expanded path.
+  def expand_symlinks(file_path)
+    file_path.split("/").inject do |full_path, next_dir|
+      next_path = full_path + "/" + next_dir
+      if File.symlink?(next_path) then
+        link = File.readlink(next_path)
+        next_path =
+            case link
+              when /^\// then link
+              else
+                File.expand_path(full_path + "/" + link)
+            end
+      end
+      next_path
+    end
+  end
+  private :expand_symlinks
+
+
+
+
 end

    

--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to [email protected].
For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to