Please review pull request #447: (#5454) Acceptance test to verify that pluginsync works properly with "features" opened by (cprice-puppet)

Description:

This acceptance test relies on some new features added to the acceptance framework here:

https://github.com/puppetlabs/puppet-acceptance/pull/129

So it shouldn't be merged until after that one is.

  • Opened: Thu Feb 02 22:33:58 UTC 2012
  • Based on: puppetlabs:master (ca50b7cd625d654265138ca07106317180ec4c04)
  • Requested merge: cprice-puppet:feature/2.7.x/5454-pluginsync-features (fc0022c8b820fe7fb4e6127b3e7c34f9ddd7afbf)

Diff follows:

diff --git a/acceptance/tests/pluginsync/feature/pluginsync_should_sync_features.rb b/acceptance/tests/pluginsync/feature/pluginsync_should_sync_features.rb
new file mode 100644
index 0000000..31d36c7
--- /dev/null
+++ b/acceptance/tests/pluginsync/feature/pluginsync_should_sync_features.rb
@@ -0,0 +1,163 @@
+test_name "the pluginsync functionality should sync feature definitions"
+
+#
+# This test is intended to ensure that pluginsync syncs feature definitions to the agents.  It checks the feature
+# twice; once to make sure that it gets loaded successfully during the run in which it was synced, and once to
+# ensure that it still gets loaded successfully during the subsequent run (in which it should not be synced because
+# the files haven't changed.)
+#
+
+# create some vars to point to the directories that we're going to point the master/agents at
+test_identifier = "pluginsync_should_sync_features"
+master_module_dir = "master_modules"
+agent_lib_dir = "agent_lib"
+
+module_name = "superbogus"
+
+# here we create a custom type, which basically doesn't do anything except for test the value of
+# our custom feature and write the result to a file
+agent_module_type_file = "#{agent_lib_dir}/puppet/type/#{module_name}.rb"
+master_module_type_file = "#{master_module_dir}/#{module_name}/lib/puppet/type/#{module_name}.rb"
+master_module_type_content = <<HERE
+module Puppet
+  newtype(:#{module_name}) do
+    newparam(:name) do
+      isnamevar
+    end
+
+    newproperty(:testfeature) do
+      def sync
+        Puppet.info("The value of the #{module_name} feature is: \#{Puppet.features.#{module_name}?}")
+        #require 'ftools'
+        #File.makedirs("\#{agent_feature_output_dir}")
+        #File.open("\#{agent_feature_output_tmpfile}", "w") do |f|
+        #  f.print("\#{Puppet.features.#{module_name}?}")
+        #end
+      end
+      def retrieve
+        :absent
+      end
+      def insync?(is)
+        false
+      end
+    end
+  end
+end
+HERE
+
+# here is our custom feature... it always returns true
+agent_module_feature_file = "#{agent_lib_dir}/puppet/feature/#{module_name}.rb"
+master_module_feature_file = "#{master_module_dir}/#{module_name}/lib/puppet/feature/#{module_name}.rb"
+master_module_feature_content = <<HERE
+Puppet.features.add(:#{module_name}) do
+  Puppet.info("#{module_name} feature being queried")
+  true
+end
+HERE
+
+
+# manifest file for the master, does nothing but instantiate our custom type
+master_manifest_dir = "master_manifest"
+master_manifest_file = "#{master_manifest_dir}/site.pp"
+master_manifest_content = <<HERE
+#{module_name} { "This is the title of the #{module_name} type instance in site.pp":
+    testfeature => "Hi.  I'm setting the testfeature property of #{module_name} here in site.pp",
+}
+HERE
+
+
+# for convenience we build up a list of all of the files we are expecting to deploy on the master
+all_master_files = [
+    [master_module_feature_file, 'feature'],
+    [master_module_type_file, 'type'],
+    [master_manifest_file, 'manifest']
+]
+
+# for convenience we build up a list of all of the files we are expecting to deploy on the agents
+all_agent_files = [
+    [agent_module_feature_file, 'feature'],
+    [agent_module_type_file, 'type']
+]
+
+# the command line args we'll pass to the agent each time we call it
+agent_args = "--libdir=\"%s\" --pluginsync --no-daemonize --verbose " +
+    "--onetime --test --server #{master}"
+# legal exit codes whenever we run the agent
+#  we need to allow exit code 2, which means "changes were applied" on the agent
+agent_exit_codes = [0, 2]
+
+
+# copy all the files to the master
+step "write our simple module out to the master" do
+  master.create_test_file(master_module_type_file, master_module_type_content, :mkdirs => true)
+  master.create_test_file(master_module_feature_file, master_module_feature_content, :mkdirs => true)
+  master.create_test_file(master_manifest_file, master_manifest_content, :mkdirs => true)
+end
+
+step "verify that the module and manifest files exist on the master" do
+  all_master_files.each do |file_path, desc|
+    unless master.test_file_exists?(file_path) then
+      fail_test("Failed to create #{desc} file '#{master.get_test_file_path(file_path)}' on master")
+    end
+  end
+end
+
+step "start the master" do
+
+  with_master_running_on(master,
+             "--manifest=\"#{master.get_test_file_path(master_manifest_file)}\" " +
+             "--modulepath=\"#{master.get_test_file_path(master_module_dir)}\" --pluginsync") do
+
+    # the module files shouldn't exist on the agent yet because they haven't been synced
+    step "verify that the module files don't exist on the agent path" do
+      agents.each do |agent|
+        all_agent_files.each do |file_path, desc|
+          if agent.test_file_exists?(file_path) then
+            fail_test("#{desc} file already exists on agent: '#{agent.get_test_file_path(file_path)}'")
+          end
+        end
+      end
+    end
+
+
+    step "run the agent and verify that it loaded the feature" do
+      agents.each do |agent|
+        run_agent_on(agent, agent_args % agent.get_test_file_path(agent_lib_dir),
+                     :acceptable_exit_codes => agent_exit_codes) do
+          assert_match(/The value of the #{module_name} feature is: true/, result.stdout,
+            "Expected agent stdout to include confirmation that the feature was 'true'")
+        end
+      end
+    end
+
+    step "verify that the module files were synced down to the agent" do
+      agents.each do |agent|
+        all_agent_files.each do |file_path, desc|
+          unless agent.test_file_exists?(file_path) then
+            fail_test("Expected #{desc} file not synced to agent: '#{agent.get_test_file_path(file_path)}'")
+          end
+        end
+      end
+    end
+
+    step "run the agent again" do
+      agents.each do |agent|
+        run_agent_on(agent, agent_args % agent.get_test_file_path(agent_lib_dir),
+                        :acceptable_exit_codes => agent_exit_codes) do
+          assert_match(/The value of the #{module_name} feature is: true/, result.stdout,
+                       "Expected agent stdout to include confirmation that the feature was 'true'")
+        end
+      end
+    end
+
+    #TODO: was thinking about putting in a check for the timestamps on the files (maybe add a method for that to
+    # the framework?) to verify that they didn't get re-synced, but it seems like more trouble than it's worth
+    # at the moment.
+    #step "verify that the module files were not re-synced" do
+    #  fail_test("NOT YET IMPLEMENTED: verify that the module files were not re-synced")
+    #end
+
+  end
+end
+
+
diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb
index de3fa2f..04126a4 100644
--- a/lib/puppet/util.rb
+++ b/lib/puppet/util.rb
@@ -549,6 +549,43 @@ def secure_open(file,must_be_w,&block)
     end
   end
   module_function :secure_open
+
+
+
+
+  # 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 self.pretty_backtrace()
+
+    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
+
+  # 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 self.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
+
+
+
 end
 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