Please review pull request #488: Feature/2.7.x/5454 pluginsync features autosign opened by (cprice-puppet)
Description:
(#5454) add "autosign" argument
We are removing "autosign" from the list of default arguments for
the with_master_running_on method in the acceptance test framework.
Thus, this test now needs to specify that argument explicitly.
Diff follows:
diff --git a/acceptance/tests/allow_symlinks_as_config_directories.rb b/acceptance/tests/allow_symlinks_as_config_directories.rb
index 66c6ccc..1f450fe 100644
--- a/acceptance/tests/allow_symlinks_as_config_directories.rb
+++ b/acceptance/tests/allow_symlinks_as_config_directories.rb
@@ -1,27 +1,34 @@
test_name "Should allow symlinks to directories as configuration directories"
-step "Create the test confdir with a link to it"
-confdir = "/tmp/puppet_conf-directory-#{$$}"
-conflink = "/tmp/puppet_conf-symlink-#{$$}"
+agents.each do |agent|
+ if agent['platform'].include?('windows')
+ skip_test "Test not supported on this platform"
+ next
+ end
-on agents, "rm -rf #{conflink} #{confdir}"
+ step "Create the test confdir with a link to it"
+ confdir = agent.tmpdir('puppet_conf-directory')
+ conflink = agent.tmpfile('puppet_conf-symlink')
-on agents, "mkdir #{confdir}"
-on agents, "ln -s #{confdir} #{conflink}"
+ on agent, "rm -rf #{conflink} #{confdir}"
-create_remote_file agents, "#{confdir}/puppet.conf", <<CONFFILE
+ on agent, "mkdir #{confdir}"
+ on agent, "ln -s #{confdir} #{conflink}"
+
+ create_remote_file agent, "#{confdir}/puppet.conf", <<CONFFILE
[main]
certname = "awesome_certname"
CONFFILE
manifest = 'notify{"My certname is $clientcert": }'
-step "Run Puppet and ensure it used the conf file in the confdir"
-on agents, puppet_apply("--confdir #{conflink}"), :stdin => manifest do
- assert_match("My certname is awesome_certname", stdout)
-end
+ step "Run Puppet and ensure it used the conf file in the confdir"
+ on agent, puppet_apply("--confdir #{conflink}"), :stdin => manifest do
+ assert_match("My certname is awesome_certname", stdout)
+ end
-step "Check that the symlink and confdir are unchanged"
-on agents, "[ -L #{conflink} ]"
-on agents, "[ -d #{confdir} ]"
-on agents, "[ $(readlink #{conflink}) = #{confdir} ]"
+ step "Check that the symlink and confdir are unchanged"
+ on agent, "[ -L #{conflink} ]"
+ on agent, "[ -d #{confdir} ]"
+ on agent, "[ $(readlink #{conflink}) = #{confdir} ]"
+end
diff --git a/acceptance/tests/apply/classes/should_allow_param_undef_override.rb b/acceptance/tests/apply/classes/should_allow_param_undef_override.rb
index a4f37cb..39904dc 100755
--- a/acceptance/tests/apply/classes/should_allow_param_undef_override.rb
+++ b/acceptance/tests/apply/classes/should_allow_param_undef_override.rb
@@ -1,11 +1,15 @@
test_name "should allow overriding a parameter to undef in inheritence"
-out = "/tmp/class_undef_override_out-#{$$}"
+agents.each do |agent|
+ dir = agent.tmpdir('class_undef_override')
+ out = File.join(dir, 'class_undef_override_out')
+ source = File.join(dir, 'class_undef_override_test')
+
manifest = %Q{
class parent {
file { 'test':
path => '#{out}',
- source => '/tmp/class_undef_override_test-#{$$}',
+ source => '#{source}',
}
}
class child inherits parent {
@@ -18,12 +22,15 @@ class child inherits parent {
include child
}
-step "prepare the target file on all systems"
-on(agents, "echo 'hello world!' > #{out}")
-step "apply the manifest"
-apply_manifest_on(agents, manifest)
-step "verify the file content"
-on(agents, "cat #{out}") do
+ step "prepare the target file on all systems"
+ on(agent, "echo 'hello world!' > #{out}")
+ step "apply the manifest"
+ apply_manifest_on(agent, manifest)
+ step "verify the file content"
+ on(agent, "cat #{out}") do
fail_test "the file was not touched" if stdout.include? "hello world!"
fail_test "the file was not updated" unless stdout.include? "hello new world"
+ end
+
+ on(agent, "rm -rf #{dir}")
end
diff --git a/acceptance/tests/apply/virtual/should_realize.rb b/acceptance/tests/apply/virtual/should_realize.rb
index fd32ad8..7dc2406 100755
--- a/acceptance/tests/apply/virtual/should_realize.rb
+++ b/acceptance/tests/apply/virtual/should_realize.rb
@@ -1,22 +1,25 @@
test_name "should realize"
-out = "/tmp/hosts-#{Time.new.to_i}"
-name = "test-#{Time.new.to_i}-host"
+
+agents.each do |agent|
+ out = agent.tmpfile('should_realize')
+ name = "test-#{Time.new.to_i}-host"
manifest = %Q{
@host{'#{name}': ip=>'127.0.0.2', target=>'#{out}', ensure=>present}
realize(Host['#{name}'])
}
-step "clean the system ready for testing"
-on agents, "rm -f #{out}"
+ step "clean the system ready for testing"
+ on agent, "rm -f #{out}"
-step "realize the resource on the hosts"
-apply_manifest_on agents, manifest
+ step "realize the resource on the host"
+ apply_manifest_on agent, manifest
-step "verify the content of the file"
-on(agents, "cat #{out}") do
+ step "verify the content of the file"
+ on(agent, "cat #{out}") do
fail_test "missing host definition" unless stdout.include? name
-end
+ end
-step "final cleanup of the system"
-on agents, "rm -f #{out}"
+ step "final cleanup of the system"
+ on agent, "rm -f #{out}"
+end
diff --git a/acceptance/tests/apply/virtual/should_realize_complex_query.rb b/acceptance/tests/apply/virtual/should_realize_complex_query.rb
index 9782bbf..512b5cb 100755
--- a/acceptance/tests/apply/virtual/should_realize_complex_query.rb
+++ b/acceptance/tests/apply/virtual/should_realize_complex_query.rb
@@ -1,6 +1,8 @@
test_name "should realize with complex query"
-out = "/tmp/hosts-#{Time.new.to_i}"
-name = "test-#{Time.new.to_i}-host"
+
+agents.each do |agent|
+ out = agent.tmpfile('should_realize_complex_query')
+ name = "test-#{Time.new.to_i}-host"
manifest = %Q{
@host { '#{name}1':
@@ -18,19 +20,20 @@
Host<| host_aliases == 'two' and ip == '127.0.0.3' |>
}
-step "clean up target system for test"
-on agents, "rm -f #{out}"
+ step "clean up target system for test"
+ on agent, "rm -f #{out}"
-step "run the manifest"
-apply_manifest_on agents, manifest
+ step "run the manifest"
+ apply_manifest_on agent, manifest
-step "verify the file output"
-on(agents, "cat #{out}") do
+ step "verify the file output"
+ on(agent, "cat #{out}") do
fail_test "second host not found in output" unless
stdout.include? "#{name}2"
fail_test "first host was found in output" if
stdout.include? "#{name}1"
-end
+ end
-step "clean up system after testing"
-on agents, "rm -f #{out}"
+ step "clean up system after testing"
+ on agent, "rm -f #{out}"
+end
diff --git a/acceptance/tests/apply/virtual/should_realize_many.rb b/acceptance/tests/apply/virtual/should_realize_many.rb
index 8f53cae..80cf3f5 100755
--- a/acceptance/tests/apply/virtual/should_realize_many.rb
+++ b/acceptance/tests/apply/virtual/should_realize_many.rb
@@ -1,6 +1,8 @@
test_name "test that realize function takes a list"
-out = "/tmp/hosts-#{Time.new.to_i}"
-name = "test-#{Time.new.to_i}-host"
+
+agents.each do |agent|
+ out = agent.tmpfile('should_realize_many')
+ name = "test-#{Time.new.to_i}-host"
manifest = %Q{
@host{'#{name}1': ip=>'127.0.0.2', target=>'#{out}', ensure=>present}
@@ -8,15 +10,15 @@
realize(Host['#{name}1'], Host['#{name}2'])
}
+ step "clean up target system for test"
+ on agent, "rm -f #{out}"
-step "clean up target system for test"
-on agents, "rm -f #{out}"
-
-step "run the manifest"
-apply_manifest_on agents, manifest
+ step "run the manifest"
+ apply_manifest_on agent, manifest
-step "verify the file output"
-on(agents, "cat #{out}") do
+ step "verify the file output"
+ on(agent, "cat #{out}") do
fail_test "first host not found in output" unless stdout.include? "#{name}1"
fail_test "second host not found in output" unless stdout.include? "#{name}2"
+ end
end
diff --git a/acceptance/tests/apply/virtual/should_realize_query.rb b/acceptance/tests/apply/virtual/should_realize_query.rb
index 24d3233..ae1ff3e 100755
--- a/acceptance/tests/apply/virtual/should_realize_query.rb
+++ b/acceptance/tests/apply/virtual/should_realize_query.rb
@@ -1,6 +1,8 @@
test_name "should realize query"
-out = "/tmp/hosts-#{Time.new.to_i}"
-name = "test-#{Time.new.to_i}-host"
+
+agents.each do |agent|
+ out = agent.tmpfile('should_realize_query')
+ name = "test-#{Time.new.to_i}-host"
manifest = %Q{
@host { '#{name}':
@@ -12,13 +14,14 @@
Host<| ip == '127.0.0.2' |>
}
-step "clean up target system for test"
-on agents, "rm -f #{out}"
+ step "clean up target system for test"
+ on agent, "rm -f #{out}"
-step "run the manifest"
-apply_manifest_on agents, manifest
+ step "run the manifest"
+ apply_manifest_on agent, manifest
-step "verify the file output"
-on(agents, "cat #{out}") do
+ step "verify the file output"
+ on(agent, "cat #{out}") do
fail_test "host not found in output" unless stdout.include? name
+ end
end
diff --git a/acceptance/tests/apply/virtual/should_realize_query_array.rb b/acceptance/tests/apply/virtual/should_realize_query_array.rb
index 137d93b..c2fa8f6 100755
--- a/acceptance/tests/apply/virtual/should_realize_query_array.rb
+++ b/acceptance/tests/apply/virtual/should_realize_query_array.rb
@@ -1,6 +1,8 @@
test_name "should realize query array"
-out = "/tmp/hosts-#{Time.new.to_i}"
-name = "test-#{Time.new.to_i}-host"
+
+agents.each do |agent|
+ out = agent.tmpfile('should_realize_query_array')
+ name = "test-#{Time.new.to_i}-host"
manifest = %Q{
@host { '#{name}':
@@ -12,13 +14,14 @@
Host<| host_aliases == 'two' |>
}
-step "clean up target system for test"
-on agents, "rm -f #{out}"
+ step "clean up target system for test"
+ on agent, "rm -f #{out}"
-step "run the manifest"
-apply_manifest_on agents, manifest
+ step "run the manifest"
+ apply_manifest_on agent, manifest
-step "verify the file output"
-on(agents, "cat #{out}") do
+ step "verify the file output"
+ on(agent, "cat #{out}") do
fail_test "host not found in output" unless stdout.include? name
+ end
end
diff --git a/acceptance/tests/file_hello_world.rb b/acceptance/tests/file_hello_world.rb
index 683ff46..b64ddd7 100644
--- a/acceptance/tests/file_hello_world.rb
+++ b/acceptance/tests/file_hello_world.rb
@@ -1,22 +1,23 @@
# Verify that a trivial manifest can be run to completion.
-
-filename = "/tmp/hello-world.txt"
-content = "Hello, World"
-manifest = "file { '#{filename}': content => '#{content}' }"
-
test_name "The challenging 'Hello, World' manifest"
-step "ensure we are clean before testing..."
-on agents, "rm -f #{filename}"
+agents.each do |agent|
+ filename = agent.tmpfile('hello-world.txt')
+ content = "Hello, World"
+ manifest = "file { '#{filename}': content => '#{content}' }"
-step "run the manifest itself"
-apply_manifest_on(agents, manifest) do
- fail_test "the expected notice of action was missing" unless
- stdout.index 'File[/tmp/hello-world.txt]/ensure: defined content as'
-end
+ step "ensure we are clean before testing..."
+ on(agent, "rm -f #{filename}")
-step "verify the content of the generated files."
-on agents, "grep '#{content}' #{filename}"
+ step "run the manifest itself"
+ apply_manifest_on(agent, manifest) do
+ fail_test "the expected notice of action was missing" unless
+ stdout.index "File[#{filename}]/ensure: defined content as"
+ end
-step "clean up after our test run."
-on agents, "rm -f #{filename}"
+ step "verify the content of the generated files."
+ on agent, "grep '#{content}' #{filename}"
+
+ step "clean up after our test run."
+ on(agent, "rm -f #{filename}")
+end
diff --git a/acceptance/tests/language/resource_refs_with_nested_arrays.rb b/acceptance/tests/language/resource_refs_with_nested_arrays.rb
index 7bc7978..ead35a3 100644
--- a/acceptance/tests/language/resource_refs_with_nested_arrays.rb
+++ b/acceptance/tests/language/resource_refs_with_nested_arrays.rb
@@ -1,27 +1,27 @@
test_name "#7681: Allow using array variables in resource references"
-test_manifest = <<MANIFEST
+agents.each do |agent|
+ test_manifest = <<MANIFEST
$exec_names = ["first", "second"]
exec { "first":
- command => "echo the first command",
- path => "/usr/bin:/bin",
+ command => "#{agent.echo('the first command')}",
+ path => "#{agent.path}",
logoutput => true,
}
exec { "second":
- command => "echo the second command",
- path => "/usr/bin:/bin",
+ command => "#{agent.echo('the second command')}",
+ path => "#{agent.path}",
logoutput => true,
}
exec { "third":
- command => "echo the final command",
- path => "/usr/bin:/bin",
+ command => "#{agent.echo('the final command')}",
+ path => "#{agent.path}",
logoutput => true,
require => Exec[$exec_names],
}
MANIFEST
-results = apply_manifest_on agents, test_manifest
-
-results.each do |result|
- assert_match(/Exec\[third\].*the final command/, "#{result.stdout}")
+ apply_manifest_on agent, test_manifest do
+ assert_match(/Exec\[third\].*the final command/, "#{stdout}")
+ end
end
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..e480393
--- /dev/null
+++ b/acceptance/tests/pluginsync/feature/pluginsync_should_sync_features.rb
@@ -0,0 +1,287 @@
+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.)
+#
+
+
+
+###############################################################################
+# BEGIN UTILITY METHODS - ideally this stuff would live somewhere besides in
+# the actual test.
+###############################################################################
+
+# Create a file on the host.
+# Parameters:
+# [host] the host 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_test_file(host, file_rel_path, file_content, options)
+
+ # set default options
+ options[:mkdirs] ||= false
+ options[:owner] ||= "root"
+ options[:group] ||= "puppet"
+ options[:mode] ||= "755"
+
+ file_path = get_test_file_path(host, file_rel_path)
+
+ mkdirs(host, File.dirname(file_path)) if (options[:mkdirs] == true)
+ create_remote_file(host, file_path, file_content)
+
+#
+# NOTE: we need these chown/chmod calls because the acceptance framework connects to the nodes as "root", but
+# puppet 'master' runs as user 'puppet'. Therefore, in order for puppet master to be able to read any files
+# that we've created, we have to carefully set their permissions
+#
+
+ chown(host, options[:owner], options[:group], file_path)
+ chmod(host, options[:mode], file_path)
+
+end
+
+
+# Given a relative path, returns an absolute path for a test file. Basically, this just prepends the
+# a unique temp dir path (specific to the current test execution) to your relative path.
+def get_test_file_path(host, file_rel_path)
+ File.join(@host_test_tmp_dirs[host.name], file_rel_path)
+end
+
+
+# Check for the existence of a temp file for the current test; basically, this just calls file_exists?(),
+# but prepends the path to the current test's temp dir onto the file_rel_path parameter. This allows
+# tests to be written using only a relative path to specify file locations, while still taking advantage
+# of automatic temp file cleanup at test completion.
+def test_file_exists?(host, file_rel_path)
+ # I don't think we can easily use "test -f" here, because our "execute" commands are all built around reading
+ # stdout as opposed to reading process exit codes
+ result = host.execute("ruby -e \"print File.exists?('#{get_test_file_path(host, file_rel_path)}')\"")
+ # get a boolean return value
+ result == "true"
+end
+
+def tmpdir(host, basename)
+ host_tmpdir = host.tmpdir(basename)
+ # we need to make sure that the puppet user can traverse this directory...
+ chmod(host, "755", host_tmpdir)
+ host_tmpdir
+end
+
+def mkdirs(host, dir_path)
+ on(host, "mkdir -p #{dir_path}")
+end
+
+def chown(host, owner, group, path)
+ on(host, "chown #{owner}:#{group} #{path}")
+end
+
+def chmod(host, mode, path)
+ on(host, "chmod #{mode} #{path}")
+end
+
+
+
+
+
+# pluck this out of the test case environment; not sure if there is a better way
+cur_test_file = @path
+cur_test_file_shortname = File.basename(cur_test_file, File.extname(cur_test_file))
+
+# we need one list of all of the hosts, to assist in managing temp dirs. It's possible
+# that the master is also an agent, so this will consolidate them into a unique set
+all_hosts = Set[master, *agents]
+
+# now we can create a hash of temp dirs--one per host, and unique to this test--without worrying about
+# doing it twice on any individual host
+@host_test_tmp_dirs = Hash[all_hosts.map do |host| [host.name, tmpdir(host, cur_test_file_shortname)] end ]
+
+# a silly variable for keeping track of whether or not all of the tests passed...
+all_tests_passed = false
+
+###############################################################################
+# END UTILITY METHODS
+###############################################################################
+
+
+
+###############################################################################
+# BEGIN TEST LOGIC
+###############################################################################
+
+# 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}?}")
+ 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 = "--trace --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]
+
+# this begin block is here for handling temp file cleanup via an "ensure" block at the very end of the
+# test.
+begin
+
+ # copy all the files to the master
+ step "write our simple module out to the master" do
+ create_test_file(master, master_module_type_file, master_module_type_content, :mkdirs => true)
+ create_test_file(master, master_module_feature_file, master_module_feature_content, :mkdirs => true)
+ create_test_file(master, 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 test_file_exists?(master, file_path) then
+ fail_test("Failed to create #{desc} file '#{get_test_file_path(master, file_path)}' on master")
+ end
+ end
+ end
+
+ step "start the master" do
+
+ with_master_running_on(master,
+ "--manifest=\"#{get_test_file_path(master, master_manifest_file)}\" " +
+ "--modulepath=\"#{get_test_file_path(master, master_module_dir)}\" " +
+ "--autosign true --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 test_file_exists?(agent, file_path) then
+ fail_test("#{desc} file already exists on agent: '#{get_test_file_path(agent, 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 % get_test_file_path(agent, 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 test_file_exists?(agent, file_path) then
+ fail_test("Expected #{desc} file not synced to agent: '#{get_test_file_path(agent, file_path)}'")
+ end
+ end
+ end
+ end
+
+ step "run the agent again" do
+ agents.each do |agent|
+ run_agent_on(agent, agent_args % get_test_file_path(agent, 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
+
+ all_tests_passed = true
+
+ end
+ensure
+ ##########################################################################################
+ # Clean up all of the temp files created by this test. It would be nice if this logic
+ # could be handled outside of the test itself; I envision a stanza like this one appearing
+ # in a very large number of the tests going forward unless it is handled by the framework.
+ ##########################################################################################
+ if all_tests_passed then
+ all_hosts.each do |host|
+ on(host, "rm -rf #{@host_test_tmp_dirs[host.name]}")
+ end
+ end
+end
+
+
diff --git a/acceptance/tests/puppet_apply_a_file_should_create_a_file_and_report_the_md5.rb b/acceptance/tests/puppet_apply_a_file_should_create_a_file_and_report_the_md5.rb
index 4433852..0358d11 100644
--- a/acceptance/tests/puppet_apply_a_file_should_create_a_file_and_report_the_md5.rb
+++ b/acceptance/tests/puppet_apply_a_file_should_create_a_file_and_report_the_md5.rb
@@ -1,17 +1,17 @@
test_name "puppet apply should create a file and report an MD5"
-file = "/tmp/hello.world.#{Time.new.to_i}.txt"
-manifest = "file{'#{file}': content => 'test'}"
+agents.each do |agent|
+ file = agent.tmpfile('hello-world')
+ manifest = "file{'#{file}': content => 'test'}"
-step "clean up #{file} for testing"
-on agents, "rm -f #{file}"
+ step "clean up #{file} for testing"
+ on(agent, "rm -f #{file}")
-step "Run the manifest and verify MD5 was printed"
-agents.each do |host|
- apply_manifest_on(host, manifest) do
- assert_match(/defined content as '{md5}098f6bcd4621d373cade4e832627b4f6'/, stdout, "#{host}: didn't find the content MD5 on output")
+ step "Run the manifest and verify MD5 was printed"
+ apply_manifest_on(agent, manifest) do
+ assert_match(/defined content as '{md5}098f6bcd4621d373cade4e832627b4f6'/, stdout, "#{agent}: didn't find the content MD5 on output")
end
-end
-step "clean up #{file} after testing"
-on agents, "rm -f #{file}"
+ step "clean up #{file} after testing"
+ on(agent, "rm -f #{file}")
+end
diff --git a/acceptance/tests/resource/cron/should_create_cron.rb b/acceptance/tests/resource/cron/should_create_cron.rb
index d402280..0e48e46 100644
--- a/acceptance/tests/resource/cron/should_create_cron.rb
+++ b/acceptance/tests/resource/cron/should_create_cron.rb
@@ -7,6 +7,11 @@
delete_user = "user { '#{tmpuser}': ensure => absent, managehome => false }"
agents.each do |host|
+ if host['platform'].include?('windows')
+ skip_test "Test not supported on this platform"
+ next
+ end
+
step "ensure the user exist via puppet"
apply_manifest_on host, create_user
diff --git a/acceptance/tests/resource/cron/should_match_existing.rb b/acceptance/tests/resource/cron/should_match_existing.rb
index 92e7dc2..d4af8a9 100755
--- a/acceptance/tests/resource/cron/should_match_existing.rb
+++ b/acceptance/tests/resource/cron/should_match_existing.rb
@@ -7,6 +7,11 @@
delete_user = "user { '#{tmpuser}': ensure => absent, managehome => false }"
agents.each do |host|
+ if host['platform'].include?('windows')
+ skip_test "Test not supported on this platform"
+ next
+ end
+
step "ensure the user exist via puppet"
apply_manifest_on host, create_user
diff --git a/acceptance/tests/resource/cron/should_remove_cron.rb b/acceptance/tests/resource/cron/should_remove_cron.rb
index 78afde4..051a4fc 100755
--- a/acceptance/tests/resource/cron/should_remove_cron.rb
+++ b/acceptance/tests/resource/cron/should_remove_cron.rb
@@ -7,6 +7,11 @@
delete_user = "user { '#{tmpuser}': ensure => absent, managehome => false }"
agents.each do |host|
+ if host['platform'].include?('windows')
+ skip_test "Test not supported on this platform"
+ next
+ end
+
step "ensure the user exist via puppet"
apply_manifest_on host, create_user
diff --git a/acceptance/tests/resource/cron/should_remove_matching.rb b/acceptance/tests/resource/cron/should_remove_matching.rb
index bbfea34..23dba7a 100755
--- a/acceptance/tests/resource/cron/should_remove_matching.rb
+++ b/acceptance/tests/resource/cron/should_remove_matching.rb
@@ -9,6 +9,11 @@
delete_user = "user { '#{tmpuser}': ensure => absent, managehome => false }"
agents.each do |host|
+ if host['platform'].include?('windows')
+ skip_test "Test not supported on this platform"
+ next
+ end
+
step "ensure the user exist via puppet"
apply_manifest_on host, create_user
diff --git a/acceptance/tests/resource/cron/should_update_existing.rb b/acceptance/tests/resource/cron/should_update_existing.rb
index b37952a..1fa9cd9 100755
--- a/acceptance/tests/resource/cron/should_update_existing.rb
+++ b/acceptance/tests/resource/cron/should_update_existing.rb
@@ -7,6 +7,11 @@
delete_user = "user { '#{tmpuser}': ensure => absent, managehome => false }"
agents.each do |host|
+ if host['platform'].include?('windows')
+ skip_test "Test not supported on this platform"
+ next
+ end
+
step "ensure the user exist via puppet"
apply_manifest_on host, create_user
diff --git a/acceptance/tests/resource/exec/accept_multi-line_commands.rb b/acceptance/tests/resource/exec/accept_multi-line_commands.rb
index 1e9aaf1..dafd86c 100644
--- a/acceptance/tests/resource/exec/accept_multi-line_commands.rb
+++ b/acceptance/tests/resource/exec/accept_multi-line_commands.rb
@@ -1,24 +1,32 @@
test_name "Be able to execute multi-line commands (#9996)"
-temp_file_name = "/tmp/9996-multi-line-commands.#{$$}"
-test_manifest = <<HERE
+agents.each do |agent|
+ if agent['platform'].include?('windows')
+ skip_test "Test not supported on this platform"
+ next
+ end
+
+ temp_file_name = agent.tmpfile('9996-multi-line-commands')
+
+ test_manifest = <<HERE
exec { "test exec":
command => "/bin/echo '#Test' > #{temp_file_name};
/bin/echo 'bob' >> #{temp_file_name};"
}
HERE
-expected_results = <<HERE
+ expected_results = <<HERE
#Test
bob
HERE
-on agents, "rm -f #{temp_file_name}"
+ on(agent, "rm -f #{temp_file_name}")
-apply_manifest_on agents, test_manifest
+ apply_manifest_on agent, test_manifest
-on(agents, "cat #{temp_file_name}").each do |result|
- assert_equal(expected_results, "#{result.stdout}", "Unexpected result for host '#{result.host}'")
-end
+ on(agent, "cat #{temp_file_name}") do
+ assert_equal(expected_results, stdout, "Unexpected result for host '#{agent}'")
+ end
-on agents, "rm -f #{temp_file_name}"
+ on(agent, "rm -f #{temp_file_name}")
+end
diff --git a/acceptance/tests/resource/exec/should_not_run_command_creates.rb b/acceptance/tests/resource/exec/should_not_run_command_creates.rb
index 583ae43..3518d24 100644
--- a/acceptance/tests/resource/exec/should_not_run_command_creates.rb
+++ b/acceptance/tests/resource/exec/should_not_run_command_creates.rb
@@ -1,34 +1,36 @@
test_name "should not run command creates"
-touch = "/tmp/touched-#{Time.new.to_i}"
-donottouch = "/tmp/not-touched-#{Time.new.to_i}"
+agents.each do |agent|
+ touch = agent.tmpfile('touched')
+ donottouch = agent.tmpfile('not-touched')
manifest = %Q{
- exec { "test#{Time.new.to_i}": command => '/bin/touch #{donottouch}', creates => "#{touch}"}
+ exec { "test#{Time.new.to_i}": command => '#{agent.touch(donottouch)}', creates => "#{touch}"}
}
-step "prepare the agents for the test"
-on agents, "touch #{touch} ; rm -f #{donottouch}"
+ step "prepare the agents for the test"
+ on agent, "touch #{touch} && rm -f #{donottouch}"
-step "test using puppet apply"
-apply_manifest_on(agents, manifest) do
+ step "test using puppet apply"
+ apply_manifest_on(agent, manifest) do
fail_test "looks like the thing executed, which it shouldn't" if
- stdout.include? 'executed successfully'
-end
+ stdout.include? 'executed successfully'
+ end
-step "verify the file didn't get created"
-on agents, "test -f #{donottouch}", :acceptable_exit_codes => [1]
+ step "verify the file didn't get created"
+ on agent, "test -f #{donottouch}", :acceptable_exit_codes => [1]
-step "prepare the agents for the second part of the test"
-on agents, "touch #{touch} ; rm -f #{donottouch}"
+ step "prepare the agents for the second part of the test"
+ on agent, "touch #{touch} ; rm -f #{donottouch}"
-step "test using puppet resource"
-on(agents, puppet_resource('exec', "test#{Time.new.to_i}",
- "command='/bin/touch #{donottouch}'",
- "creates='#{touch}'")) do
+ step "test using puppet resource"
+ on(agent, puppet_resource('exec', "test#{Time.new.to_i}",
+ "command='#{agent.touch(donottouch)}'",
+ "creates='#{touch}'")) do
fail_test "looks like the thing executed, which it shouldn't" if
- stdout.include? 'executed successfully'
-end
+ stdout.include? 'executed successfully'
+ end
-step "verify the file didn't get created the second time"
-on agents, "test -f #{donottouch}", :acceptable_exit_codes => [1]
+ step "verify the file didn't get created the second time"
+ on agent, "test -f #{donottouch}", :acceptable_exit_codes => [1]
+end
diff --git a/acceptance/tests/resource/exec/should_run_command.rb b/acceptance/tests/resource/exec/should_run_command.rb
index b7156c6..4a76cc4 100644
--- a/acceptance/tests/resource/exec/should_run_command.rb
+++ b/acceptance/tests/resource/exec/should_run_command.rb
@@ -1,31 +1,38 @@
test_name "tests that puppet correctly runs an exec."
# original author: Dan Bode --daniel 2010-12-23
-$touch = "/tmp/test-exec-#{Time.new.to_i}"
-
-def before
- step "file to be touched should not exist."
- on agents, "rm -f #{$touch}"
+def before(agent)
+ step "file to be touched should not exist."
+ touched = agent.tmpfile('test-exec')
end
-def after
- step "checking the output worked"
- on agents, "test -f #{$touch}"
+def after(agent, touched)
+ step "checking the output worked"
+ on agent, "test -f #{touched}"
- step "clean up the system"
- on agents, "rm -f #{$touch}"
+ step "clean up the system"
+ on agent, "rm -f #{touched}"
end
-before
-apply_manifest_on(agents, "exec {'test': command=>'/bin/touch #{$touch}'}") do
+agents.each do |agent|
+ if agent['platform'].include?('windows')
+ Log.warn('Pending due to #11740')
+ next
+ end
+
+ touched = before(agent)
+ apply_manifest_on(agent, "exec {'test': command=>'#{agent.touch(touched)}'}") do
fail_test "didn't seem to run the command" unless
- stdout.include? 'executed successfully'
-end
-after
+ stdout.include? 'executed successfully'
+ end
+ after(agent, touched)
-before
-on(agents, puppet_resource('-d', 'exec', 'test', "command='/bin/touch #{$touch}'")) do
+ touched = before(agent)
+ on(agent, puppet_resource('-d', 'exec', 'test', "command='#{agent.touch(touched)}'}")) do
fail_test "didn't seem to run the command" unless
- stdout.include? 'executed successfully'
+ stdout.include? 'executed successfully'
+ end
+ after(agent, touched)
end
-after
+
+
diff --git a/acceptance/tests/resource/exec/should_set_path.rb b/acceptance/tests/resource/exec/should_set_path.rb
index 4d9ccb0..e1b5aa0 100644
--- a/acceptance/tests/resource/exec/should_set_path.rb
+++ b/acceptance/tests/resource/exec/should_set_path.rb
@@ -1,16 +1,18 @@
test_name "the path statement should work to locate commands"
-file = "/tmp/touched-should-set-path-#{Time.new.to_i}"
+agents.each do |agent|
+ file = agent.tmpfile('touched-should-set-path')
-step "clean up the system for the test"
-on agents, "rm -f #{file}"
+ step "clean up the system for the test"
+ on agent, "rm -f #{file}"
-step "invoke the exec resource with a path set"
-on(agents, puppet_resource('exec', 'test',
- "command='touch #{file}'", 'path="/bin:/usr/bin"'))
+ step "invoke the exec resource with a path set"
+ on(agent, puppet_resource('exec', 'test',
+ "command='#{agent.touch(file, false)}'", "path='#{agent.path}'"))
-step "verify that the files were created"
-on agents, "test -f #{file}"
+ step "verify that the files were created"
+ on agent, "test -f #{file}"
-step "clean up the system after testing"
-on agents, "rm -f #{file}"
+ step "clean up the system after testing"
+ on agent, "rm -f #{file}"
+end
diff --git a/acceptance/tests/resource/file/content_attribute.rb b/acceptance/tests/resource/file/content_attribute.rb
index 31dbac1..768cdb0 100644
--- a/acceptance/tests/resource/file/content_attribute.rb
+++ b/acceptance/tests/resource/file/content_attribute.rb
@@ -1,30 +1,31 @@
test_name "Content Attribute"
-step "Ensure the test environment is clean"
-on agents, 'rm -f /tmp/content_file_test.txt'
+agents.each do |agent|
+ target = agent.tmpfile('content_file_test')
+
+ step "Ensure the test environment is clean"
+ on agent, "rm -f #{target}"
-step "Content Attribute: using raw content"
+ step "Content Attribute: using raw content"
-manifest = "file { '/tmp/content_file_test.txt': content => 'This is the test file content', ensure => present }"
-apply_manifest_on agents, manifest
+ manifest = "file { '#{target}': content => 'This is the test file content', ensure => present }"
+ apply_manifest_on agent, manifest
-agents.each do |host|
- on host, "cat /tmp/content_file_test.txt" do
- assert_match(/This is the test file content/, stdout, "File content not matched on #{host}")
+ on agent, "cat #{target}" do
+ assert_match(/This is the test file content/, stdout, "File content not matched on #{agent}")
end
-end
-step "Ensure the test environment is clean"
-on agents, 'rm -f /tmp/content_file_test.txt'
+ step "Ensure the test environment is clean"
+ on agent, "rm -f #{target}"
-step "Content Attribute: using a checksum from filebucket"
-on agents, "echo 'This is the checksum file contents' > /tmp/checksum_test_file.txt"
-step "Backup file into the filebucket"
-on agents, puppet_filebucket("backup --local /tmp/checksum_test_file.txt")
+ step "Content Attribute: using a checksum from filebucket"
+ on agent, "echo 'This is the checksum file contents' > #{target}"
+
+ step "Backup file into the filebucket"
+ on agent, puppet_filebucket("backup --local #{target}")
-agents.each do |agent|
bucketdir="not set"
- on agent, puppet_filebucket("--configprint bucketdir") do
+ on agent, puppet_filebucket("--configprint bucketdir") do
bucketdir = stdout.chomp
end
@@ -33,20 +34,18 @@
path => '#{bucketdir}',
}
- file { '/tmp/content_file_test.txt':
+ file { '#{target}':
content => '{md5}18571d3a04b2bb7ccfdbb2c44c72caa9',
ensure => present,
backup => local,
}
|
- step "Applying Manifest on Agents"
+ step "Applying Manifest on Agent"
apply_manifest_on agent, manifest
-end
-step "Validate filebucket checksum file contents"
-agents.each do |host|
- on host, "cat /tmp/content_file_test.txt" do
- assert_match(/This is the checksum file content/, stdout, "File content not matched on #{host}")
+ step "Validate filebucket checksum file contents"
+ on agent, "cat #{target}" do
+ assert_match(/This is the checksum file content/, stdout, "File content not matched on #{agent}")
end
end
diff --git a/acceptance/tests/resource/file/should_create_directory.rb b/acceptance/tests/resource/file/should_create_directory.rb
index 37ad9db..ebe8441 100755
--- a/acceptance/tests/resource/file/should_create_directory.rb
+++ b/acceptance/tests/resource/file/should_create_directory.rb
@@ -1,15 +1,17 @@
test_name "should create directory"
-target = "/tmp/test-#{Time.new.to_i}"
+agents.each do |agent|
+ target = agent.tmpfile("create-dir")
-step "clean up the system before we begin"
-on agents, "rm -rf #{target}"
+ step "clean up the system before we begin"
+ on(agent, "rm -rf #{target}")
-step "verify we can create a directory"
-on(agents, puppet_resource("file", target, 'ensure=directory'))
+ step "verify we can create a directory"
+ on(agent, puppet_resource("file", target, 'ensure=directory'))
-step "verify the directory was created"
-on agents, "test -d #{target}"
+ step "verify the directory was created"
+ on(agent, "test -d #{target}")
-step "clean up after the test run"
-on agents, "rm -rf #{target}"
+ step "clean up after the test run"
+ on(agent, "rm -rf #{target}")
+end
diff --git a/acceptance/tests/resource/file/should_create_empty.rb b/acceptance/tests/resource/file/should_create_empty.rb
index e9d9d8e..4c16c06 100755
--- a/acceptance/tests/resource/file/should_create_empty.rb
+++ b/acceptance/tests/resource/file/should_create_empty.rb
@@ -1,15 +1,17 @@
test_name "should create empty file for 'present'"
-target = "/tmp/test-#{Time.new.to_i}"
+agents.each do |agent|
+ target = agent.tmpfile("empty")
-step "clean up the system before we begin"
-on agents, "rm -rf #{target}"
+ step "clean up the system before we begin"
+ on(agent, "rm -rf #{target}")
-step "verify we can create an empty file"
-on(agents, puppet_resource("file", target, 'ensure=present'))
+ step "verify we can create an empty file"
+ on(agent, puppet_resource("file", target, 'ensure=present'))
-step "verify the target was created"
-on agents, "test -f #{target} && test ! -s #{target}"
+ step "verify the target was created"
+ on(agent, "test -f #{target} && test ! -s #{target}")
-step "clean up after the test run"
-on agents, "rm -rf #{target}"
+ step "clean up after the test run"
+ on(agent, "rm -rf #{target}")
+end
diff --git a/acceptance/tests/resource/file/should_create_symlink.rb b/acceptance/tests/resource/file/should_create_symlink.rb
index 81fe4b4..0721bb2 100755
--- a/acceptance/tests/resource/file/should_create_symlink.rb
+++ b/acceptance/tests/resource/file/should_create_symlink.rb
@@ -4,25 +4,32 @@
target = "/tmp/test-#{Time.new.to_i}"
source = "/tmp/test-#{Time.new.to_i}-source"
-step "clean up the system before we begin"
-on agents, "rm -rf #{target}"
-on agents, "echo '#{message}' > #{source}"
+agents.each do |agent|
+ if agent['platform'].include?('windows')
+ skip_test "Test not supported on this platform"
+ next
+ end
-step "verify we can create a symlink"
-on(agents, puppet_resource("file", target, "ensure=#{source}"))
+ step "clean up the system before we begin"
+ on agent, "rm -rf #{target}"
+ on agent, "echo '#{message}' > #{source}"
-step "verify the symlink was created"
-on agents, "test -L #{target} && test -f #{target}"
-step "verify source file"
-on agents, "test -f #{source}"
+ step "verify we can create a symlink"
+ on(agent, puppet_resource("file", target, "ensure=#{source}"))
-step "verify the content is identical on both sides"
-on(agents, "cat #{source}") do
+ step "verify the symlink was created"
+ on agent, "test -L #{target} && test -f #{target}"
+ step "verify source file"
+ on agent, "test -f #{source}"
+
+ step "verify the content is identical on both sides"
+ on(agent, "cat #{source}") do
fail_test "source missing content" unless stdout.include? message
-end
-on(agents, "cat #{target}") do
+ end
+ on(agent, "cat #{target}") do
fail_test "target missing content" unless stdout.include? message
-end
+ end
-step "clean up after the test run"
-on agents, "rm -rf #{target} #{source}"
+ step "clean up after the test run"
+ on agent, "rm -rf #{target} #{source}"
+end
diff --git a/acceptance/tests/resource/file/should_remove_dir.rb b/acceptance/tests/resource/file/should_remove_dir.rb
index 36fa1ad..ca8a003 100755
--- a/acceptance/tests/resource/file/should_remove_dir.rb
+++ b/acceptance/tests/resource/file/should_remove_dir.rb
@@ -1,21 +1,23 @@
test_name "should remove directory, but force required"
-target = "/tmp/test-#{Time.new.to_i}"
+agents.each do |agent|
+ target = agent.tmpdir("delete-dir")
-step "clean up the system before we begin"
-on agents, "rm -rf #{target} ; mkdir -p #{target}"
+ step "clean up the system before we begin"
+ on agent, "rm -rf #{target} ; mkdir -p #{target}"
-step "verify we can't remove a directory without 'force'"
-on(agents, puppet_resource("file", target, 'ensure=absent')) do
+ step "verify we can't remove a directory without 'force'"
+ on(agent, puppet_resource("file", target, 'ensure=absent')) do
fail_test "didn't tell us that force was required" unless
- stdout.include? "Not removing directory; use 'force' to override"
-end
+ stdout.include? "Not removing directory; use 'force' to override"
+ end
-step "verify the directory still exists"
-on agents, "test -d #{target}"
+ step "verify the directory still exists"
+ on agent, "test -d #{target}"
-step "verify we can remove a directory with 'force'"
-on(agents, puppet_resource("file", target, 'ensure=absent', 'force=true'))
+ step "verify we can remove a directory with 'force'"
+ on(agent, puppet_resource("file", target, 'ensure=absent', 'force=true'))
-step "verify that the directory is gone"
-on agents, "test -d #{target}", :acceptable_exit_codes => [1]
+ step "verify that the directory is gone"
+ on agent, "test -d #{target}", :acceptable_exit_codes => [1]
+end
diff --git a/acceptance/tests/resource/file/should_remove_file.rb b/acceptance/tests/resource/file/should_remove_file.rb
index aadb829..60cf632 100755
--- a/acceptance/tests/resource/file/should_remove_file.rb
+++ b/acceptance/tests/resource/file/should_remove_file.rb
@@ -1,12 +1,14 @@
test_name "should remove file"
-target = "/tmp/test-#{Time.new.to_i}"
+agents.each do |agent|
+ target = agent.tmpfile('delete-file')
-step "clean up the system before we begin"
-on agents, "rm -rf #{target} && touch #{target}"
+ step "clean up the system before we begin"
+ on agent, "rm -rf #{target} && touch #{target}"
-step "verify we can remove a file"
-on(agents, puppet_resource("file", target, 'ensure=absent'))
+ step "verify we can remove a file"
+ on(agent, puppet_resource("file", target, 'ensure=absent'))
-step "verify that the file is gone"
-on agents, "test -e #{target}", :acceptable_exit_codes => [1]
+ step "verify that the file is gone"
+ on agent, "test -e #{target}", :acceptable_exit_codes => [1]
+end
diff --git a/acceptance/tests/resource/file/source_attribtute.rb b/acceptance/tests/resource/file/source_attribtute.rb
index 3fa447a..5308cb3 100644
--- a/acceptance/tests/resource/file/source_attribtute.rb
+++ b/acceptance/tests/resource/file/source_attribtute.rb
@@ -1,43 +1,46 @@
test_name "The source attribute"
-step "Ensure the test environment is clean"
-on agents, 'rm -f /tmp/source_file_test.txt'
+agents.each do |agent|
+ target = agent.tmpfile('source_file_test')
+
+ step "Ensure the test environment is clean"
+ on agent, "rm -f #{target}"
# TODO: Add tests for puppet:// URIs with master/agent setups.
# step "when using a puppet:/// URI with a master/agent setup"
# step "when using a puppet://$server/ URI with a master/agent setup"
-step "Using a local file path"
-on agents, "echo 'Yay, this is the local file.' > /tmp/local_source_file_test.txt"
-manifest = "file { '/tmp/source_file_test.txt': source => '/tmp/local_source_file_test.txt', ensure => present }"
+ step "Using a local file path"
+ source = agent.tmpfile('local_source_file_test')
+ on agent, "echo 'Yay, this is the local file.' > #{source}"
-apply_manifest_on agents, manifest
-agents.each do |host|
- on host, "cat /tmp/source_file_test.txt" do
- assert_match(/Yay, this is the local file./, stdout, "FIRST: File contents not matched on #{host}")
+ manifest = "file { '#{target}': source => '#{source}', ensure => present }"
+ apply_manifest_on agent, manifest
+ on agent, "cat #{target}" do
+ assert_match(/Yay, this is the local file./, stdout, "FIRST: File contents not matched on #{agent}")
end
-end
-
-step "Ensure the test environment is clean"
-on agents, 'rm -f /tmp/source_file_test.txt'
-step "Using a puppet:/// URI with puppet apply"
+ step "Ensure the test environment is clean"
+ on agent, "rm -f #{target}"
-on agents, puppet_agent("--configprint modulepath") do
- modulepath = stdout.split(':')[0]
- modulepath = modulepath.chomp
- on agents, "mkdir -p #{modulepath}/test_module/files"
- #on agents, "echo 'Yay, this is the puppet:/// file.' > #{modulepath}/test_module/files/test_file.txt"
- on agents, "echo 'Yay, this is the puppetfile.' > #{modulepath}/test_module/files/test_file.txt"
-end
+ step "Using a puppet:/// URI with puppet apply"
+ on agent, puppet_agent("--configprint modulepath") do
+ modulepath = agent.path_split(stdout)[0]
+ modulepath = modulepath.chomp
+ on agent, "mkdir -p '#{modulepath}/test_module/files'"
+ #on agent, "echo 'Yay, this is the puppet:/// file.' > #{modulepath}/test_module/files/test_file.txt"
+ on agent, "echo 'Yay, this is the puppetfile.' > '#{modulepath}/test_module/files/test_file.txt'"
+ end
-on agents, %q{echo "file { '/tmp/source_file_test.txt': source => 'puppet:///modules/test_module/test_file.txt', ensure => present }" > /tmp/source_test_manifest.pp}
-on agents, puppet_apply("/tmp/source_test_manifest.pp")
+ manifest = "file { '#{target}': source => 'puppet:///modules/test_module/test_file.txt', ensure => present }"
+ apply_manifest_on agent, manifest
-agents.each do |host|
- on host, "cat /tmp/source_file_test.txt" do
- assert_match(/Yay, this is the puppetfile./, stdout, "SECOND: File contents not matched on #{host}")
+ on agent, "cat #{target}" do
+ assert_match(/Yay, this is the puppetfile./, stdout, "SECOND: File contents not matched on #{agent}")
end
+
+ step "Cleanup"
+ on agent, "rm -f #{target}; rm -rf #{source}"
end
# Oops. We (Jesse & Jacob) ended up writing this before realizing that you
diff --git a/acceptance/tests/resource/file/symbolic_modes.rb b/acceptance/tests/resource/file/symbolic_modes.rb
index 3d088ee..46c61ca 100644
--- a/acceptance/tests/resource/file/symbolic_modes.rb
+++ b/acceptance/tests/resource/file/symbolic_modes.rb
@@ -4,19 +4,18 @@ def validate(path, mode)
"ruby -e 'exit (File::Stat.new(#{path.inspect}).mode & 0777 == #{mode})'"
end
-def tmpfile(what)
- "/tmp/symbolic-mode-#{what}-" +
- "#{Time.now.strftime("%Y%m%d")}-#{$$}-" +
- "#{rand(0x100000000).to_s(36)}.test"
-end
+agents.each do |agent|
+ if agent['platform'].include?('windows')
+ Log.warn("Pending: this does not currently work on Windows")
+ next
+ end
-# Generate some standard, remote-safe names for our scratch content, and make
-# sure that they exist already. Don't need to care about modes or owners, as
-# we reset anything that matters inside the test loop.
-file = tmpfile('file')
-dir = tmpfile('dir')
+ user = agent['user']
+ group = agent['group'] || user
+ file = agent.tmpfile('symbolic-mode-file')
+ dir = agent.tmpdir('symbolic-mode-dir')
-on agents, "touch #{file} ; mkdir #{dir}"
+ on(agent, "touch #{file} ; mkdir -p #{dir}")
# Infrastructure for a nice, table driven test. Yum.
#
@@ -72,12 +71,12 @@ def tmpfile(what)
dir_mode = '%04o' % data[3].to_i(8)
step "ensure permissions for testing #{symbolic_mode}"
- on agents, "chmod #{start_mode} #{file} && chown root:root #{file}"
- on agents, "chmod #{start_mode} #{dir} && chown root:root #{dir}"
+ on agent, "chmod #{start_mode} #{file} && chown #{user}:#{group} #{file}"
+ on agent, "chmod #{start_mode} #{dir} && chown #{user}:#{group} #{dir}"
step "test mode #{symbolic_mode} works on a file"
manifest = "file { #{file.inspect}: ensure => file, mode => #{symbolic_mode} }"
- apply_manifest_on(agents, manifest) do
+ apply_manifest_on(agent, manifest) do
unless start_mode == file_mode
assert_match(/mode changed '#{start_mode}' to '#{file_mode}'/, stdout,
"couldn't set file mode to #{symbolic_mode}")
@@ -85,16 +84,16 @@ def tmpfile(what)
end
step "validate the mode changes applied to the file"
- on agents, "test -f #{file} && " + validate(file, file_mode)
+ on agent, "test -f #{file} && " + validate(file, file_mode)
# Validate that we don't reapply the changes - that they are stable.
- apply_manifest_on(agents, manifest) do
+ apply_manifest_on(agent, manifest) do
assert_no_match(/mode changed/, stdout, "reapplied the symbolic mode change")
end
step "test mode #{symbolic_mode} works on a directory"
manifest = "file { #{dir.inspect}: ensure => directory, mode => #{symbolic_mode} }"
- apply_manifest_on(agents, manifest) do
+ apply_manifest_on(agent, manifest) do
unless start_mode == dir_mode
assert_match(/mode changed '#{start_mode}' to '#{dir_mode}'/, stdout,
"couldn't set dir mode to #{symbolic_mode}")
@@ -102,14 +101,14 @@ def tmpfile(what)
end
step "validate the mode changes applied to the dir"
- on agents, "test -d #{dir} && " + validate(file, dir_mode)
+ on agent, "test -d #{dir} && " + validate(file, dir_mode)
# Validate that we don't reapply the changes - that they are stable.
- apply_manifest_on(agents, manifest) do
+ apply_manifest_on(agent, manifest) do
assert_no_match(/mode changed/, stdout, "reapplied the symbolic mode change")
end
end
-
step "clean up old test things"
-on agents, "rm -rf #{file} #{dir}"
+on agent, "rm -rf #{file} #{dir}"
+end
diff --git a/acceptance/tests/resource/file/ticket_8740_should_not_enumerate_root_directory.rb b/acceptance/tests/resource/file/ticket_8740_should_not_enumerate_root_directory.rb
index 5763a3c..a918f8c 100644
--- a/acceptance/tests/resource/file/ticket_8740_should_not_enumerate_root_directory.rb
+++ b/acceptance/tests/resource/file/ticket_8740_should_not_enumerate_root_directory.rb
@@ -2,31 +2,38 @@
target = "/test-socket-#{$$}"
-step "clean up the system before we begin"
-on(agents, "rm -f #{target}")
+agents.each do |agent|
+ if agent['platform'].include?('windows')
+ skip_test "Test not supported on this platform"
+ next
+ end
-step "create UNIX domain socket"
-on(agents, %Q{ruby -e "require 'socket'; UNIXServer::new('#{target}').close"})
+ step "clean up the system before we begin"
+ on(agent, "rm -f #{target}")
-step "query for all files, which should return nothing"
-on(agents, puppet_resource('file'), :acceptable_exit_codes => [1]) do
- assert_match(%r{Listing all file instances is not supported. Please specify a file or directory, e.g. puppet resource file /etc}, stderr)
-end
+ step "create UNIX domain socket"
+ on(agent, %Q{ruby -e "require 'socket'; UNIXServer::new('#{target}').close"})
+
+ step "query for all files, which should return nothing"
+ on(agent, puppet_resource('file'), :acceptable_exit_codes => [1]) do
+ assert_match(%r{Listing all file instances is not supported. Please specify a file or directory, e.g. puppet resource file /etc}, stderr)
+ end
-["/", "/etc"].each do |file|
- step "query '#{file}' directory, which should return single entry"
- on(agents, puppet_resource('file', file)) do
- files = stdout.scan(/^file \{ '([^']+)'/).flatten
+ ["/", "/etc"].each do |file|
+ step "query '#{file}' directory, which should return single entry"
+ on(agent, puppet_resource('file', file)) do
+ files = stdout.scan(/^file \{ '([^']+)'/).flatten
- assert_equal(1, files.size, "puppet returned multiple files: #{files.join(', ')}")
- assert_match(file, files[0], "puppet did not return file")
+ assert_equal(1, files.size, "puppet returned multiple files: #{files.join(', ')}")
+ assert_match(file, files[0], "puppet did not return file")
+ end
end
-end
-step "query file that does not exist, which should report the file is absent"
-on(agents, puppet_resource('file', '/this/does/notexist')) do
- assert_match(/ensure\s+=>\s+'absent'/, stdout)
-end
+ step "query file that does not exist, which should report the file is absent"
+ on(agent, puppet_resource('file', '/this/does/notexist')) do
+ assert_match(/ensure\s+=>\s+'absent'/, stdout)
+ end
-step "remove UNIX domain socket"
-on(agents, "rm -f #{target}")
+ step "remove UNIX domain socket"
+ on(agent, "rm -f #{target}")
+end
diff --git a/acceptance/tests/resource/group/should_create.rb b/acceptance/tests/resource/group/should_create.rb
index efb80a4..16a74c7 100755
--- a/acceptance/tests/resource/group/should_create.rb
+++ b/acceptance/tests/resource/group/should_create.rb
@@ -1,20 +1,17 @@
-test_name "should create group"
+test_name "should create a group"
name = "pl#{rand(999999).to_i}"
-def cleanup(name)
- step "remove group #{name} if it exists"
- on agents, "if getent group #{name}; then groupdel #{name}; fi"
-end
+agents.each do |agent|
+ step "ensure the group does not exist"
+ agent.group_absent(name)
-cleanup(name)
+ step "create the group"
+ on agent, puppet_resource('group', name, 'ensure=present')
-step "create the group #{name} with the resource agent"
-on(agents, puppet_resource('group', name, 'ensure=present'))
+ step "verify the group exists"
+ agent.group_get(name)
-step "verify the group #{name} was created"
-on(agents, "getent group #{name}") do
- fail_test "group information is not sensible" unless stdout =~ /^#{name}:.*:[0-9]+:/
+ step "delete the group"
+ agent.group_absent(name)
end
-
-cleanup(name)
diff --git a/acceptance/tests/resource/group/should_destroy.rb b/acceptance/tests/resource/group/should_destroy.rb
index 1551abe..6b88757 100755
--- a/acceptance/tests/resource/group/should_destroy.rb
+++ b/acceptance/tests/resource/group/should_destroy.rb
@@ -1,14 +1,14 @@
test_name "should destroy a group"
-name = "test-group-#{Time.new.to_i}"
+name = "pl#{rand(999999).to_i}"
-step "ensure the group exists on the target system"
-on agents, "getent group #{name} || groupadd #{name}"
+agents.each do |agent|
+ step "ensure the group is present"
+ agent.group_present(name)
-step "use puppet to remove the group"
-on(agents, puppet_resource('group', name, 'ensure=absent'))
+ step "delete the group"
+ on agent, puppet_resource('group', name, 'ensure=absent')
-step "verify that the group has been removed"
-# REVISIT: I /think/ that exit code 2 is standard across Linux, but I have no
-# idea what non-Linux platforms are going to return. --daniel 2010-12-24
-on agents, "getent group #{name}", :acceptable_exit_codes => [2]
+ step "verify the group was deleted"
+ agent.group_absent(name)
+end
diff --git a/acceptance/tests/resource/group/should_modify_gid.rb b/acceptance/tests/resource/group/should_modify_gid.rb
index b54d401..65e9a1f 100755
--- a/acceptance/tests/resource/group/should_modify_gid.rb
+++ b/acceptance/tests/resource/group/should_modify_gid.rb
@@ -4,21 +4,28 @@
gid1 = rand(999999).to_i
gid2 = rand(999999).to_i
-step "ensure that the group exists with gid #{gid1}"
-on(agents, puppet_resource('group', name, 'ensure=present', "gid=#{gid1}")) do
+agents.each do |agent|
+ if agent['platform'].include?('windows')
+ skip_test "Test not supported on this platform"
+ next
+ end
+
+ step "ensure that the group exists with gid #{gid1}"
+ on(agent, puppet_resource('group', name, 'ensure=present', "gid=#{gid1}")) do
fail_test "missing gid notice" unless stdout =~ /gid +=> +'#{gid1}'/
-end
+ end
-step "ensure that we can modify the GID of the group to #{gid2}"
-on(agents, puppet_resource('group', name, 'ensure=present', "gid=#{gid2}")) do
+ step "ensure that we can modify the GID of the group to #{gid2}"
+ on(agent, puppet_resource('group', name, 'ensure=present', "gid=#{gid2}")) do
fail_test "missing gid notice" unless stdout =~ /gid +=> +'#{gid2}'/
-end
+ end
-step "verify that the GID changed"
-on(agents, "getent group #{name}") do
+ step "verify that the GID changed"
+ on(agent, "getent group #{name}") do
fail_test "gid is wrong through getent output" unless
- stdout =~ /^#{name}:.*:#{gid2}:/
-end
+ stdout =~ /^#{name}:.*:#{gid2}:/
+ end
-step "clean up the system after the test run"
-on(agents, puppet_resource('group', name, 'ensure=absent'))
+ step "clean up the system after the test run"
+ on(agent, puppet_resource('group', name, 'ensure=absent'))
+end
diff --git a/acceptance/tests/resource/group/should_not_create_existing.rb b/acceptance/tests/resource/group/should_not_create_existing.rb
index ed4f54c..351ca0c 100755
--- a/acceptance/tests/resource/group/should_not_create_existing.rb
+++ b/acceptance/tests/resource/group/should_not_create_existing.rb
@@ -2,14 +2,16 @@
name = "test-group-#{Time.new.to_i}"
-step "ensure the group exists on the target node"
-on(agents, puppet_resource('group', name, 'ensure=present'))
+agents.each do |agent|
+ step "ensure the group exists on the target node"
+ agent.group_present(name)
-step "verify that we don't try and create the existing group"
-on(agents, puppet_resource('group', name, 'ensure=present')) do
+ step "verify that we don't try and create the existing group"
+ on(agent, puppet_resource('group', name, 'ensure=present')) do
fail_test "looks like we created the group" if
- stdout.include? '/Group[bozo]/ensure: created'
-end
+ stdout.include? "/Group[#{name}]/ensure: created"
+ end
-step "clean up the system after the test run"
-on(agents, puppet_resource('group', name, 'ensure=absent'))
+ step "clean up the system after the test run"
+ agent.group_absent(name)
+end
diff --git a/acceptance/tests/resource/group/should_not_destoy_unexisting.rb b/acceptance/tests/resource/group/should_not_destoy_unexisting.rb
index 256a8f1..287bb0f 100755
--- a/acceptance/tests/resource/group/should_not_destoy_unexisting.rb
+++ b/acceptance/tests/resource/group/should_not_destoy_unexisting.rb
@@ -3,11 +3,13 @@
name = "test-group-#{Time.new.to_i}"
step "verify the group does not already exist"
-on(agents, puppet_resource('group', name, 'ensure=absent'))
+agents.each do |agent|
+ agent.group_absent(name)
+end
step "verify that we don't remove the group when it doesn't exist"
on(agents, puppet_resource('group', name, 'ensure=absent')) do
- fail_test "it looks like we tried to remove the group" if
- stdout.include? "notice: /Group[#{name}]/ensure: removed"
+ fail_test "it looks like we tried to remove the group" if
+ stdout.include? "notice: /Group[#{name}]/ensure: removed"
end
diff --git a/acceptance/tests/resource/group/should_query.rb b/acceptance/tests/resource/group/should_query.rb
index 3bbce07..12da6ea 100755
--- a/acceptance/tests/resource/group/should_query.rb
+++ b/acceptance/tests/resource/group/should_query.rb
@@ -1,15 +1,16 @@
-test_name "group should query"
+test_name "test that we can query and find a group that exists."
-name = "test-group-#{Time.new.to_i}"
+name = "pl#{rand(999999).to_i}"
-step "ensure the group exists on the target systems"
-on agents, "getent group #{name} || groupadd #{name}"
+agents.each do |agent|
+ step "ensure that our test group exists"
+ agent.group_present(name)
-step "ensure that the resource agent sees the group"
-on(agents, puppet_resource('group', name)) do
- fail_test "missing group identifier" unless stdout.include? "group { '#{name}':"
- fail_test "missing present attributed" unless stdout.include? "ensure => 'present'"
-end
+ step "query for the resource and verify it was found"
+ on(agent, puppet_resource('group', name)) do
+ fail_test "didn't find the group #{name}" unless stdout.include? 'present'
+ end
-step "clean up the system after the test"
-on(agents, puppet_resource('group', name, 'ensure=absent'))
+ step "clean up the group we added"
+ agent.group_absent(name)
+end
diff --git a/acceptance/tests/resource/group/should_query_all.rb b/acceptance/tests/resource/group/should_query_all.rb
index 9abcfed..87ce781 100755
--- a/acceptance/tests/resource/group/should_query_all.rb
+++ b/acceptance/tests/resource/group/should_query_all.rb
@@ -1,30 +1,23 @@
-test_name "puppet resource should query all groups"
+test_name "should query all groups"
-agents.each do |host|
- groups = {}
+agents.each do |agent|
+ step "query natively"
+ groups = agent.group_list
- step "collect the list of groups on #{host} with getent group"
- on(host, "getent group") do
- stdout.each_line do |line| groups[line[/^[^:]+/]] = 'getent' end
- end
+ fail_test("No groups found") unless groups
- step "collect the list of groups on #{host} with puppet resource"
- on(host, puppet_resource('group')) do
- stdout.each_line do |line|
- match = line.match(/^group \{ '([^']+)'/)
- if match then
- name = match[1]
+ step "query with puppet"
+ on(agent, puppet_resource('group')) do
+ stdout.each_line do |line|
+ name = ( line.match(/^group \{ '([^']+)'/) or next )[1]
- if groups.include? name then
- groups.delete name
- else
- fail_test "group #{name} found by puppet, not getent"
- end
- end
- end
+ unless groups.delete(name)
+ fail_test "group #{name} found by puppet, not natively"
+ end
end
+ end
- groups.keys.each do |name|
- fail_test "group #{name} found by getent, not puppet"
- end
+ if groups.length > 0 then
+ fail_test "#{groups.length} groups found natively, not puppet: #{groups.join(', ')}"
+ end
end
diff --git a/acceptance/tests/resource/host/should_create.rb b/acceptance/tests/resource/host/should_create.rb
index f5c0a17..6ad807f 100755
--- a/acceptance/tests/resource/host/should_create.rb
+++ b/acceptance/tests/resource/host/should_create.rb
@@ -1,15 +1,17 @@
test_name "host should create"
-target = "/tmp/host-#{Time.new.to_i}"
+agents.each do |agent|
+ target = agent.tmpfile('host-create')
-step "clean up for the test"
-on agents, "rm -f #{target}"
+ step "clean up for the test"
+ on agent, "rm -f #{target}"
-step "create the host record"
-on(agents, puppet_resource("host", "test", "ensure=present",
+ step "create the host record"
+ on(agent, puppet_resource("host", "test", "ensure=present",
"ip=127.0.0.1", "target=#{target}"))
-step "verify that the record was created"
-on(agents, "cat #{target} ; rm -f #{target}") do
+ step "verify that the record was created"
+ on(agent, "cat #{target} ; rm -f #{target}") do
fail_test "record was not present" unless stdout =~ /^127\.0\.0\.1[[:space:]]+test/
+ end
end
diff --git a/acceptance/tests/resource/host/should_create_aliases.rb b/acceptance/tests/resource/host/should_create_aliases.rb
index 71e92ae..91031e6 100755
--- a/acceptance/tests/resource/host/should_create_aliases.rb
+++ b/acceptance/tests/resource/host/should_create_aliases.rb
@@ -1,16 +1,18 @@
test_name "host should create aliases"
-target = "/tmp/host-#{Time.new.to_i}"
+agents.each do |agent|
+ target = agent.tmpfile('host-create-aliases')
-step "clean up the system for testing"
-on agents, "rm -f #{target}"
+ step "clean up the system for testing"
+ on agent, "rm -f #{target}"
-step "create the record"
-on(agents, puppet_resource('host', 'test', "ensure=present",
+ step "create the record"
+ on(agent, puppet_resource('host', 'test', "ensure=present",
"ip=127.0.0.7", "target=#{target}", "host_aliases=alias"))
-step "verify that the aliases were added"
-on(agents, "cat #{target} ; rm -f #{target}") do
+ step "verify that the aliases were added"
+ on(agent, "cat #{target} ; rm -f #{target}") do
fail_test "alias was missing" unless
- stdout =~ /^127\.0\.0\.7[[:space:]]+test[[:space:]]alias/
+ stdout =~ /^127\.0\.0\.7[[:space:]]+test[[:space:]]alias/
+ end
end
diff --git a/acceptance/tests/resource/host/should_destroy.rb b/acceptance/tests/resource/host/should_destroy.rb
index 69c74b8..75e8166 100755
--- a/acceptance/tests/resource/host/should_destroy.rb
+++ b/acceptance/tests/resource/host/should_destroy.rb
@@ -1,19 +1,21 @@
test_name "should be able to remove a host record"
-file = "/tmp/hosts-#{Time.new.to_i}"
-line = "127.0.0.7 test1"
+agents.each do |agent|
+ file = agent.tmpfile('host-destroy')
+ line = "127.0.0.7 test1"
-step "set up files for the test"
-on agents, "printf '#{line}\n' > #{file}"
+ step "set up files for the test"
+ on agent, "printf '#{line}\n' > #{file}"
-step "delete the resource from the file"
-on(agents, puppet_resource('host', 'test1', "target=#{file}",
+ step "delete the resource from the file"
+ on(agent, puppet_resource('host', 'test1', "target=#{file}",
'ensure=absent', 'ip=127.0.0.7'))
-step "verify that the content was removed"
-on(agents, "cat #{file}; rm -f #{file}") do
+ step "verify that the content was removed"
+ on(agent, "cat #{file}; rm -f #{file}") do
fail_test "the content was still present" if stdout.include? line
-end
+ end
-step "clean up after the test"
-on agents, "rm -f #{file}"
+ step "clean up after the test"
+ on agent, "rm -f #{file}"
+end
diff --git a/acceptance/tests/resource/host/should_modify_alias.rb b/acceptance/tests/resource/host/should_modify_alias.rb
index 1ebbf33..df3ceb8 100755
--- a/acceptance/tests/resource/host/should_modify_alias.rb
+++ b/acceptance/tests/resource/host/should_modify_alias.rb
@@ -1,19 +1,21 @@
test_name "should be able to modify a host alias"
-file = "/tmp/hosts-#{Time.new.to_i}"
+agents.each do |agent|
+ file = agent.tmpfile('host-modify-alias')
-step "set up files for the test"
-on agents, "printf '127.0.0.8 test alias\n' > #{file}"
+ step "set up files for the test"
+ on agent, "printf '127.0.0.8 test alias\n' > #{file}"
-step "modify the resource"
-on(agents, puppet_resource('host', 'test', "target=#{file}",
+ step "modify the resource"
+ on(agent, puppet_resource('host', 'test', "target=#{file}",
'ensure=present', 'ip=127.0.0.8', 'host_aliases=banzai'))
-step "verify that the content was updated"
-on(agents, "cat #{file}; rm -f #{file}") do
+ step "verify that the content was updated"
+ on(agent, "cat #{file}; rm -f #{file}") do
fail_test "the alias was not updated" unless
- stdout =~ /^127\.0\.0\.8[[:space:]]+test[[:space:]]+banzai[[:space:]]*$/
-end
+ stdout =~ /^127\.0\.0\.8[[:space:]]+test[[:space:]]+banzai[[:space:]]*$/
+ end
-step "clean up after the test"
-on agents, "rm -f #{file}"
+ step "clean up after the test"
+ on agent, "rm -f #{file}"
+end
diff --git a/acceptance/tests/resource/host/should_modify_ip.rb b/acceptance/tests/resource/host/should_modify_ip.rb
index cf3c3f1..75eee01 100755
--- a/acceptance/tests/resource/host/should_modify_ip.rb
+++ b/acceptance/tests/resource/host/should_modify_ip.rb
@@ -1,19 +1,21 @@
test_name "should be able to modify a host address"
-file = "/tmp/hosts-#{Time.new.to_i}"
+agents.each do |agent|
+ file = agent.tmpfile('host-modify-ip')
-step "set up files for the test"
-on agents, "printf '127.0.0.9 test alias\n' > #{file}"
+ step "set up files for the test"
+ on agent, "printf '127.0.0.9 test alias\n' > #{file}"
-step "modify the resource"
-on(agents, puppet_resource('host', 'test', "target=#{file}",
+ step "modify the resource"
+ on(agent, puppet_resource('host', 'test', "target=#{file}",
'ensure=present', 'ip=127.0.0.10', 'host_aliases=alias'))
-step "verify that the content was updated"
-on(agents, "cat #{file}; rm -f #{file}") do
+ step "verify that the content was updated"
+ on(agent, "cat #{file}; rm -f #{file}") do
fail_test "the address was not updated" unless
- stdout =~ /^127\.0\.0\.10[[:space:]]+test[[:space:]]+alias[[:space:]]*$/
-end
+ stdout =~ /^127\.0\.0\.10[[:space:]]+test[[:space:]]+alias[[:space:]]*$/
+ end
-step "clean up after the test"
-on agents, "rm -f #{file}"
+ step "clean up after the test"
+ on agent, "rm -f #{file}"
+end
diff --git a/acceptance/tests/resource/host/should_not_create_existing.rb b/acceptance/tests/resource/host/should_not_create_existing.rb
index a8f9022..2f2161c 100755
--- a/acceptance/tests/resource/host/should_not_create_existing.rb
+++ b/acceptance/tests/resource/host/should_not_create_existing.rb
@@ -1,17 +1,18 @@
test_name "should not create host if it exists"
-file = "/tmp/hosts-#{Time.new.to_i}"
+agents.each do |agent|
+ file = agent.tmpfile('host-not-create-existing')
-step "set up the system for the test"
-on agents, "printf '127.0.0.2 test alias\n' > #{file}"
+ step "set up the system for the test"
+ on agent, "printf '127.0.0.2 test alias\n' > #{file}"
-step "tell puppet to ensure the host exists"
-on(agents, puppet_resource('host', 'test', "target=#{file}",
+ step "tell puppet to ensure the host exists"
+ on(agent, puppet_resource('host', 'test', "target=#{file}",
'ensure=present', 'ip=127.0.0.2', 'host_aliases=alias')) do
fail_test "darn, we created the host record" if
- stdout.include? 'notice: /Host[test1]/ensure: created'
-end
-
-step "clean up after we created things"
-on agents, "rm -f #{file}"
+ stdout.include? 'notice: /Host[test1]/ensure: created'
+ end
+ step "clean up after we created things"
+ on agent, "rm -f #{file}"
+end
diff --git a/acceptance/tests/resource/host/should_query.rb b/acceptance/tests/resource/host/should_query.rb
index 76f84e4..a01889a 100755
--- a/acceptance/tests/resource/host/should_query.rb
+++ b/acceptance/tests/resource/host/should_query.rb
@@ -1,15 +1,17 @@
test_name "should query hosts out of a hosts file"
-file = "/tmp/hosts-#{Time.new.to_i}"
+agents.each do |agent|
+ file = agent.tmpfile('host-query')
-step "set up the system for the test"
-on agents, "printf '127.0.0.1 localhost.local localhost\n' > #{file}"
+ step "set up the system for the test"
+ on agent, "printf '127.0.0.1 localhost.local localhost\n' > #{file}"
-step "fetch the list of hosts from puppet"
-on(agents, puppet_resource('host', 'localhost', "target=#{file}")) do
+ step "fetch the list of hosts from puppet"
+ on(agent, puppet_resource('host', 'localhost', "target=#{file}")) do
found = stdout.scan('present').length
fail_test "found #{found} hosts, not 1" if found != 1
-end
+ end
-step "clean up the system"
-on agents, "rm -f #{file}"
+ step "clean up the system"
+ on agent, "rm -f #{file}"
+end
diff --git a/acceptance/tests/resource/host/should_query_all.rb b/acceptance/tests/resource/host/should_query_all.rb
index bf1f1b8..24eb438 100755
--- a/acceptance/tests/resource/host/should_query_all.rb
+++ b/acceptance/tests/resource/host/should_query_all.rb
@@ -6,21 +6,23 @@
127.0.0.4 test4 test4.local
}
-backup = "/tmp/hosts.backup-#{Time.new.to_i}"
+agents.each do |agent|
+ backup = agent.tmpfile('host-query-all')
-step "configure the system for testing (including file backups)"
-on agents, "cp /etc/hosts #{backup}"
-on agents, "cat > /etc/hosts", :stdin => content
+ step "configure the system for testing (including file backups)"
+ on agent, "cp /etc/hosts #{backup}"
+ on agent, "cat > /etc/hosts", :stdin => content
-step "query all host records using puppet"
-on(agents, puppet_resource('host')) do
+ step "query all host records using puppet"
+ on(agent, puppet_resource('host')) do
found = stdout.scan(/host \{ '([^']+)'/).flatten.sort
fail_test "the list of returned hosts was wrong: #{found.join(', ')}" unless
- found == %w{test1 test2 test3 test4}
+ found == %w{test1 test2 test3 test4}
count = stdout.scan(/ensure\s+=>\s+'present'/).length
fail_test "found #{count} records, wanted 4" unless count == 4
-end
+ end
-step "clean up the system afterwards"
-on agents, "mv -f #{backup} /etc/hosts"
+ step "clean up the system afterwards"
+ on agent, "mv -f #{backup} /etc/hosts"
+end
diff --git a/acceptance/tests/resource/host/ticket_4131_should_not_create_without_ip.rb b/acceptance/tests/resource/host/ticket_4131_should_not_create_without_ip.rb
index 9223da6..3926784 100755
--- a/acceptance/tests/resource/host/ticket_4131_should_not_create_without_ip.rb
+++ b/acceptance/tests/resource/host/ticket_4131_should_not_create_without_ip.rb
@@ -1,21 +1,23 @@
test_name "#4131: should not create host without IP attribute"
-file = "/tmp/hosts-#{Time.new.to_i}"
+agents.each do |agent|
+ file = agent.tmpfile('4131-require-ip')
-step "configure the target system for the test"
-on agents, "rm -vrf #{file} ; touch #{file}"
+ step "configure the target system for the test"
+ on agent, "rm -vrf #{file} ; touch #{file}"
-step "try to create the host, which should fail"
-# REVISIT: This step should properly need to handle the non-zero exit code,
-# and #5668 has been filed to record that. When it is fixed this test will
-# start to fail, and this comment will tell you why. --daniel 2010-12-24
-on(agents, puppet_resource('host', 'test', "target=#{file}",
+ step "try to create the host, which should fail"
+ # REVISIT: This step should properly need to handle the non-zero exit code,
+ # and #5668 has been filed to record that. When it is fixed this test will
+ # start to fail, and this comment will tell you why. --daniel 2010-12-24
+ on(agent, puppet_resource('host', 'test', "target=#{file}",
"host_aliases=alias")) do
fail_test "puppet didn't complain about the missing attribute" unless
- stdout.include? 'ip is a required attribute for hosts'
-end
+ stdout.include? 'ip is a required attribute for hosts'
+ end
-step "verify that the host was not added to the file"
-on(agents, "cat #{file} ; rm -f #{file}") do
+ step "verify that the host was not added to the file"
+ on(agent, "cat #{file} ; rm -f #{file}") do
fail_test "the host was apparently added to the file" if stdout.include? 'test'
+ end
end
diff --git a/acceptance/tests/resource/tidy/should_remove_old_files.rb b/acceptance/tests/resource/tidy/should_remove_old_files.rb
index 63af8a8..cb1430f 100644
--- a/acceptance/tests/resource/tidy/should_remove_old_files.rb
+++ b/acceptance/tests/resource/tidy/should_remove_old_files.rb
@@ -1,16 +1,18 @@
test_name "Tidying files by date"
-step "Create a directory of old and new files"
+agents.each do |agent|
+ step "Create a directory of old and new files"
+ dir = agent.tmpdir('tidy-test')
+ on agent, "mkdir -p #{dir}"
-dir = "/tmp/tidy-test-#{$$}"
-on agents, "mkdir -p #{dir}"
-# YYMMddhhmm, so 03:04 Jan 2 1970
-old = %w[one two three four five]
-new = %w[a b c d e]
-on agents, "touch -t 7001020304 #{dir}/{#{old.join(',')}}"
-on agents, "touch #{dir}/{#{new.join(',')}}"
+ # YYMMddhhmm, so 03:04 Jan 2 1970
+ old = %w[one two three four five]
+ new = %w[a b c d e]
-step "Run a tidy resource to remove the old files"
+ on agent, "touch -t 7001020304 #{dir}/{#{old.join(',')}}"
+ on agent, "touch #{dir}/{#{new.join(',')}}"
+
+ step "Run a tidy resource to remove the old files"
manifest = <<-MANIFEST
tidy { "#{dir}":
@@ -19,16 +21,17 @@
}
MANIFEST
-apply_manifest_on agents, manifest
+ apply_manifest_on agent, manifest
-step "Ensure the old files are gone"
+ step "Ensure the old files are gone"
-old_test = old.map {|name| "-f #{File.join(dir, name)}"}.join(' -o ')
+ old_test = old.map {|name| "-f #{File.join(dir, name)}"}.join(' -o ')
-on agents, "[ #{old_test} ]", :acceptable_exit_codes => [1]
+ on agent, "[ #{old_test} ]", :acceptable_exit_codes => [1]
-step "Ensure the new files are still present"
+ step "Ensure the new files are still present"
-new_test = new.map {|name| "-f #{File.join(dir, name)}"}.join(' -a ')
+ new_test = new.map {|name| "-f #{File.join(dir, name)}"}.join(' -a ')
-on agents, "[ #{new_test} ]"
+ on agent, "[ #{new_test} ]"
+end
diff --git a/acceptance/tests/resource/user/should_create.rb b/acceptance/tests/resource/user/should_create.rb
index 0b2b0c6..4889c06 100755
--- a/acceptance/tests/resource/user/should_create.rb
+++ b/acceptance/tests/resource/user/should_create.rb
@@ -1,24 +1,26 @@
-test_name "should create a user, and the default matching group"
+test_name "should create a user"
name = "pl#{rand(999999).to_i}"
-step "ensure that the user and group #{name} do not exist"
-on agents, "if getent passwd #{name}; then userdel #{name}; fi"
-on agents, "if getent group #{name}; then groupdel #{name}; fi"
+agents.each do |agent|
+ step "ensure the user and group do not exist"
+ agent.user_absent(name)
+ agent.group_absent(name)
-step "ask puppet to create the user"
-on(agents, puppet_resource('user', name, 'ensure=present'))
+ step "create the user"
+ on agent, puppet_resource('user', name, 'ensure=present')
-step "verify that the user and group now exist"
-agents.each do |agent|
- if agent['platform'].include? 'sles' or agent['platform'].include? 'solaris' # no private user groups by default
- on agent, "getent passwd #{name}"
+ step "verify the user exists"
+ agent.user_get(name)
+
+ case agent['platform']
+ when /sles/, /solaris/, /windows/
+ # no private user groups by default
else
- on agent, "getent passwd #{name} && getent group #{name}"
+ agent.group_get(name)
end
-end
-
-step "ensure that the user and group #{name} do not exist"
-on agents, "if getent passwd #{name}; then userdel #{name}; fi"
-on agents, "if getent group #{name}; then groupdel #{name}; fi"
+ step "delete the user, and group, if any"
+ agent.user_absent(name)
+ agent.group_absent(name)
+end
diff --git a/acceptance/tests/resource/user/should_create_with_gid.rb b/acceptance/tests/resource/user/should_create_with_gid.rb
index c92d5c9..0b9f00d 100755
--- a/acceptance/tests/resource/user/should_create_with_gid.rb
+++ b/acceptance/tests/resource/user/should_create_with_gid.rb
@@ -4,6 +4,9 @@
group = "gp#{rand(999999).to_i}"
agents.each do |host|
+ if host['platform'].include?('windows')
+ skip_test "Test not supported on this platform"
+ else
step "user should not exist"
on host, "if getent passwd #{user}; then userdel #{user}; fi"
@@ -27,4 +30,5 @@
step "clean up after the test is done"
on(host, puppet_resource('user', user, 'ensure=absent'))
on(host, puppet_resource('group', group, 'ensure=absent'))
+ end
end
diff --git a/acceptance/tests/resource/user/should_destroy.rb b/acceptance/tests/resource/user/should_destroy.rb
index 6555012..73d73db 100755
--- a/acceptance/tests/resource/user/should_destroy.rb
+++ b/acceptance/tests/resource/user/should_destroy.rb
@@ -1,19 +1,14 @@
-test_name "verify that puppet resource correctly destroys users"
+test_name "should delete a user"
-user = "pl#{rand(999999).to_i}"
-group = user
+name = "pl#{rand(999999).to_i}"
-step "ensure that the user and associated group exist"
-on(agents, puppet_resource('group', group, 'ensure=present'))
-on(agents, puppet_resource('user', user, 'ensure=present', "gid=#{group}"))
+agents.each do |agent|
+ step "ensure the user is present"
+ agent.user_present(name)
-step "try and delete the user"
-on(agents, puppet_resource('user', user, 'ensure=absent'))
+ step "delete the user"
+ on agent, puppet_resource('user', name, 'ensure=absent')
-step "verify that the user is no longer present"
-on(agents, "getent passwd #{user}", :acceptable_exit_codes => [2]) do
- fail_test "found the user in the output" if stdout.include? "#{user}:"
+ step "verify the user was deleted"
+ agent.user_absent(name)
end
-
-step "remove the group as well..."
-on(agents, puppet_resource('group', group, 'ensure=absent'))
diff --git a/acceptance/tests/resource/user/should_modify.rb b/acceptance/tests/resource/user/should_modify.rb
new file mode 100644
index 0000000..24e9016
--- /dev/null
+++ b/acceptance/tests/resource/user/should_modify.rb
@@ -0,0 +1,20 @@
+test_name "should modify a user"
+
+name = "pl#{rand(999999).to_i}"
+
+agents.each do |agent|
+ step "ensure the user is present"
+ agent.user_present(name)
+
+ step "modify the user"
+ on agent, puppet_resource('user', name, ["ensure=present", "comment=comment#{name}"])
+
+ step "verify the user was modified"
+ agent.user_get(name) do |result|
+ fail_test "didn't modify the user #{name}" unless result.stdout.include? "comment#{name}"
+ end
+
+ step "delete the user"
+ agent.user_absent(name)
+ agent.group_absent(name)
+end
diff --git a/acceptance/tests/resource/user/should_modify_gid.rb b/acceptance/tests/resource/user/should_modify_gid.rb
index d8bc60f..4c13dc4 100755
--- a/acceptance/tests/resource/user/should_modify_gid.rb
+++ b/acceptance/tests/resource/user/should_modify_gid.rb
@@ -5,6 +5,9 @@
group2 = "#{user}new"
agents.each do |host|
+ if host['platform'].include?('windows')
+ skip_test "Test not supported on this platform"
+ else
step "ensure that the groups both exist"
on(host, puppet_resource('group', group1, 'ensure=present'))
on(host, puppet_resource('group', group2, 'ensure=present'))
@@ -38,4 +41,5 @@
on(host, puppet_resource('user', user, 'ensure=absent'))
on(host, puppet_resource('group', group1, 'ensure=absent'))
on(host, puppet_resource('group', group2, 'ensure=absent'))
+ end
end
diff --git a/acceptance/tests/resource/user/should_not_create_existing.rb b/acceptance/tests/resource/user/should_not_create_existing.rb
index 2f33a94..9948322 100755
--- a/acceptance/tests/resource/user/should_not_create_existing.rb
+++ b/acceptance/tests/resource/user/should_not_create_existing.rb
@@ -1,6 +1,8 @@
test_name "tests that user resource will not add users that already exist."
step "verify that we don't try to create a user account that already exists"
-on(agents, puppet_resource('user', 'root', 'ensure=present')) do
- fail_test "tried to create 'root' user" if stdout.include? 'created'
+agents.each do |agent|
+ on(agent, puppet_resource('user', agent['user'], 'ensure=present')) do
+ fail_test "tried to create '#{agent['user']}' user" if stdout.include? 'created'
+ end
end
diff --git a/acceptance/tests/resource/user/should_not_destoy_unexisting.rb b/acceptance/tests/resource/user/should_not_destoy_unexisting.rb
index 133d513..5e6bcd2 100755
--- a/acceptance/tests/resource/user/should_not_destoy_unexisting.rb
+++ b/acceptance/tests/resource/user/should_not_destoy_unexisting.rb
@@ -3,9 +3,11 @@
name = "pl#{rand(999999).to_i}"
step "verify that user #{name} does not exist"
-on agents, "getent passwd #{name}", :acceptable_exit_codes => [2]
+agents.each do |agent|
+ agent.user_absent(name)
+end
step "ensure absent doesn't try and do anything"
on(agents, puppet_resource('user', name, 'ensure=absent')) do
- fail_test "tried to remove the user, apparently" if stdout.include? 'removed'
+ fail_test "tried to remove the user, apparently" if stdout.include? 'removed'
end
diff --git a/acceptance/tests/resource/user/should_query.rb b/acceptance/tests/resource/user/should_query.rb
index c976c87..de9425b 100755
--- a/acceptance/tests/resource/user/should_query.rb
+++ b/acceptance/tests/resource/user/should_query.rb
@@ -2,14 +2,16 @@
name = "pl#{rand(999999).to_i}"
-step "ensure that our test user exists"
-on(agents, puppet_resource('user', name, 'ensure=present'))
+agents.each do |agent|
+ step "ensure that our test user exists"
+ agent.user_present(name)
-step "query for the resource and verify it was found"
-on(agents, puppet_resource('user', name)) do
+ step "query for the resource and verify it was found"
+ on(agent, puppet_resource('user', name)) do
fail_test "didn't find the user #{name}" unless stdout.include? 'present'
-end
+ end
-step "clean up the user and group we added"
-on(agents, puppet_resource('user', name, 'ensure=absent'))
-on(agents, puppet_resource('group', name, 'ensure=absent'))
+ step "clean up the user and group we added"
+ agent.user_absent(name)
+ agent.group_absent(name)
+end
diff --git a/acceptance/tests/resource/user/should_query_all.rb b/acceptance/tests/resource/user/should_query_all.rb
index 00d7b25..db7037c 100755
--- a/acceptance/tests/resource/user/should_query_all.rb
+++ b/acceptance/tests/resource/user/should_query_all.rb
@@ -1,30 +1,23 @@
-test_name "ensure that puppet queries the correct number of users"
+test_name "should query all users"
-agents.each do |host|
- users = []
+agents.each do |agent|
+ step "query natively"
+ users = agent.user_list
- step "collect the list of known users via getent"
- on(host, "getent passwd") do
- stdout.each_line do |line|
- users << line.split(':')[0]
- end
- end
+ fail_test("No users found") unless users
- step "collect the list of known users via puppet"
- on(host, puppet_resource('user')) do
- stdout.each_line do |line|
- name = ( line.match(/^user \{ '([^']+)'/) or next )[1]
+ step "query with puppet"
+ on(agent, puppet_resource('user')) do
+ stdout.each_line do |line|
+ name = ( line.match(/^user \{ '([^']+)'/) or next )[1]
- # OK: Was this name found in the list of users?
- if users.member? name then
- users.delete name
- else
- fail_test "user #{name} found by puppet, not by getent"
- end
- end
+ unless users.delete(name)
+ fail_test "user #{name} found by puppet, not natively"
+ end
end
+ end
- if users.length > 0 then
- fail_test "#{users.length} users found with getent, not puppet: #{users.join(', ')}"
- end
+ if users.length > 0 then
+ fail_test "#{users.length} users found natively, not puppet: #{users.join(', ')}"
+ end
end
diff --git a/acceptance/tests/stages/ticket_4655_default_stage_for_classes.rb b/acceptance/tests/stages/ticket_4655_default_stage_for_classes.rb
index 1b0b537..be5a167 100644
--- a/acceptance/tests/stages/ticket_4655_default_stage_for_classes.rb
+++ b/acceptance/tests/stages/ticket_4655_default_stage_for_classes.rb
@@ -1,39 +1,42 @@
test_name "#4655: Allow setting the default stage for parameterized classes"
-temp_file_name = "/tmp/4655-stage-in-parameterized-class.#{$$}"
+agents.each do |agent|
+ temp_file_name = agent.tmpfile('4655-stage-in-parameterized-class')
test_manifest = <<HERE
stage { one: before => Stage[two] }
stage { two: before => Stage[three] }
stage { three: before => Stage[main] }
class in_one {
- exec { "echo 'in_one' > #{temp_file_name}":
- path => '/usr/bin:/bin',
+ exec { "#{agent.echo('in_one', false)} > #{temp_file_name}":
+ path => '#{agent.path}',
}
}
class { in_one: stage => "one" }
class in_two( $stage=two ){
- exec { "echo 'in_two' >> #{temp_file_name}":
- path => '/usr/bin:/bin',
+ exec { "#{agent.echo('in_two', false)} >> #{temp_file_name}":
+ path => '#{agent.path}',
}
}
class { in_two: }
class in_three {
- exec { "echo 'in_three' >> #{temp_file_name}":
- path => '/usr/bin:/bin',
+ exec { "#{agent.echo('in_three', false)} >> #{temp_file_name}":
+ path => '#{agent.path}',
}
}
class { "in_three": stage => "three" }
HERE
-expected_results = "in_one
+ expected_results = "in_one
in_two
in_three
"
-apply_manifest_on agents, test_manifest
+ apply_manifest_on agent, test_manifest
-on(agents, "cat #{temp_file_name}").each do |result|
- assert_equal(expected_results, "#{result.stdout}", "Unexpected result for host '#{result.host}'")
+ on(agent, "cat #{temp_file_name}") do
+ # echo on windows adds \r\n, so do dotall regexp match
+ assert_match(/in_one\s*in_two\s*\in_three/m, stdout, "Unexpected result for host '#{agent}'")
+ end
end
diff --git a/acceptance/tests/ticket_3360_allow_duplicate_csr_with_option_set.rb b/acceptance/tests/ticket_3360_allow_duplicate_csr_with_option_set.rb
index 005141e..08638d7 100644
--- a/acceptance/tests/ticket_3360_allow_duplicate_csr_with_option_set.rb
+++ b/acceptance/tests/ticket_3360_allow_duplicate_csr_with_option_set.rb
@@ -3,8 +3,15 @@
agent_hostnames = agents.map {|a| a.to_s}
with_master_running_on master, "--allow_duplicate_certs --dns_alt_names=\"puppet,$(hostname -s),$(hostname -f)\" --verbose --noop" do
- step "Generate a certificate request for the agent"
- on agents, "puppet certificate generate `hostname -f` --ca-location remote --server #{master}"
+ agents.each do |agent|
+ if agent['platform'].include?('windows')
+ Log.warn("Pending: Windows does not support hostname -f")
+ next
+ end
+
+ step "Generate a certificate request for the agent"
+ on agent, "puppet certificate generate `hostname -f` --ca-location remote --server #{master}"
+ end
step "Collect the original certs"
on master, puppet_cert("--sign --all")
@@ -18,11 +25,17 @@
end
end
- step "Make another request with the same certname"
- on agents, "puppet certificate generate `hostname -f` --ca-location remote --server #{master}"
+ agents.each do |agent|
+ if agent['platform'].include?('windows')
+ Log.warn("Pending: Windows does not support hostname -f")
+ next
+ end
- step "Collect the new certs"
+ step "Make another request with the same certname"
+ on agent, "puppet certificate generate `hostname -f` --ca-location remote --server #{master}"
+ end
+ step "Collect the new certs"
on master, puppet_cert("--sign --all")
new_cert_list = on master, puppet_cert("--list --all")
diff --git a/acceptance/tests/ticket_3961_puppet_ca_should_produce_certs.rb b/acceptance/tests/ticket_3961_puppet_ca_should_produce_certs.rb
index 22a5b4b..3f41aeb 100644
--- a/acceptance/tests/ticket_3961_puppet_ca_should_produce_certs.rb
+++ b/acceptance/tests/ticket_3961_puppet_ca_should_produce_certs.rb
@@ -1,29 +1,35 @@
test_name "#3961: puppet ca should produce certs spec"
-scratch = "/tmp/puppet-ssl-3961"
target = "working3961.example.org"
-options = { :confdir => scratch, :vardir => scratch }
-
expect = ['notice: Signed certificate request for ca',
'notice: Rebuilding inventory file',
'notice: working3961.example.org has a waiting certificate request',
'notice: Signed certificate request for working3961.example.org',
'notice: Removing file Puppet::SSL::CertificateRequest working3961.example.org']
+agents.each do |agent|
+ if agent['platform'].include?('windows')
+ skip_test "Test not supported on this platform"
+ next
+ end
+
+ scratch = agent.tmpdir('puppet-ssl-3961')
+ options = { :confdir => scratch, :vardir => scratch }
-step "removing the SSL scratch directory..."
-on agents, "rm -vrf #{scratch}"
+ step "removing the SSL scratch directory..."
+ on(agent, "rm -vrf #{scratch}")
-step "generate a certificate in #{scratch}"
-on(agents,puppet_cert('--trace', '--generate', target, options)) do
- expect.each do |line|
- stdout.index(line) or fail_test("missing line in output: #{line}")
+ step "generate a certificate in #{scratch}"
+ on(agent,puppet_cert('--trace', '--generate', target, options)) do
+ expect.each do |line|
+ stdout.index(line) or fail_test("missing line in output: #{line}")
+ end
end
-end
-step "verify the certificate for #{target} exists"
-on agents, "test -f #{scratch}/ssl/certs/#{target}.pem"
+ step "verify the certificate for #{target} exists"
+ on agent, "test -f #{scratch}/ssl/certs/#{target}.pem"
-step "verify the private key for #{target} exists"
-on agents, "grep -q 'BEGIN RSA PRIVATE KEY' #{scratch}/ssl/private_keys/#{target}.pem"
+ step "verify the private key for #{target} exists"
+ on agent, "grep -q 'BEGIN RSA PRIVATE KEY' #{scratch}/ssl/private_keys/#{target}.pem"
+end
diff --git a/acceptance/tests/ticket_4059_ralsh_can_change_settings.rb b/acceptance/tests/ticket_4059_ralsh_can_change_settings.rb
index 83f5899..ea7b77c 100644
--- a/acceptance/tests/ticket_4059_ralsh_can_change_settings.rb
+++ b/acceptance/tests/ticket_4059_ralsh_can_change_settings.rb
@@ -1,21 +1,21 @@
test_name "#4059: ralsh can change settings"
-target = "/tmp/hosts-#4059"
-content = "host example.com ensure=present ip=127.0.0.1 target=#{target}"
+agents.each do |agent|
+ target = agent.tmpfile('hosts-#4059')
+ content = "host example.com ensure=present ip=127.0.0.1 target=#{target}"
-step "cleanup the target file"
-on agents, "rm -f #{target}"
+ step "cleanup the target file"
+ on(agent, "rm -f #{target}")
-step "run the resource agent"
-on(agents, puppet_resource(content)) do
- stdout.index('Host[example.com]/ensure: created') or
- fail_test("missing notice about host record creation")
-end
-agents.each do |host|
- on(host, "cat #{target}") do
- assert_match(/^127\.0\.0\.1\s+example\.com/, stdout, "missing host record in #{target} on #{host}")
+ step "run the resource agent"
+ on(agent, puppet_resource(content)) do
+ stdout.index('Host[example.com]/ensure: created') or
+ fail_test("missing notice about host record creation")
+ end
+ on(agent, "cat #{target}") do
+ assert_match(/^127\.0\.0\.1\s+example\.com/, stdout, "missing host record in #{target} on #{agent}")
end
-end
-step "cleanup at the end of the test"
-on agents, "rm -f #{target}"
+ step "cleanup at the end of the test"
+ on(agent, "rm -f #{target}")
+end
diff --git a/acceptance/tests/ticket_4233_resource_with_a_newline.rb b/acceptance/tests/ticket_4233_resource_with_a_newline.rb
index 11924b5..1ed1ce8 100644
--- a/acceptance/tests/ticket_4233_resource_with_a_newline.rb
+++ b/acceptance/tests/ticket_4233_resource_with_a_newline.rb
@@ -10,7 +10,8 @@
# if we find it.
agents.each do |host|
- apply_manifest_on(host, 'exec { \'/bin/echo -e "\nHello World\n"\': }') do
+ resource = host.echo('-e "\nHello World\n"')
+ apply_manifest_on(host, "exec { '#{resource}': }") do
assert_no_match(/err:/, stdout, "error report in output on #{host}")
end
end
diff --git a/acceptance/tests/ticket_4285_file_resource_fail_when_name_defined_instead_of_path.rb b/acceptance/tests/ticket_4285_file_resource_fail_when_name_defined_instead_of_path.rb
index c1cdb0b..cc67fa8 100644
--- a/acceptance/tests/ticket_4285_file_resource_fail_when_name_defined_instead_of_path.rb
+++ b/acceptance/tests/ticket_4285_file_resource_fail_when_name_defined_instead_of_path.rb
@@ -1,18 +1,20 @@
test_name "Bug #4285: ArgumentError: Cannot alias File[mytitle] to [nil]"
-manifest = %q{
+agents.each do |host|
+ dir = host.tmpdir('4285-aliasing')
+
+manifest = %Q{
file { "file1":
- name => '/tmp/file1',
- source => "/tmp/",
+ name => '#{dir}/file1',
+ source => "#{dir}/",
}
file { "file2":
- name => '/tmp/file2',
- source => "/tmp/",
+ name => '#{dir}/file2',
+ source => "#{dir}/",
}
}
-agents.each do |host|
apply_manifest_on(host, manifest) do
assert_no_match(/Cannot alias/, stdout, "#{host}: found the bug report output")
end
diff --git a/acceptance/tests/ticket_6418_file_recursion_and_audit.rb b/acceptance/tests/ticket_6418_file_recursion_and_audit.rb
index b21e57d..acb72f5 100644
--- a/acceptance/tests/ticket_6418_file_recursion_and_audit.rb
+++ b/acceptance/tests/ticket_6418_file_recursion_and_audit.rb
@@ -5,29 +5,30 @@
test_name "#6418: file recursion and audit"
-manifest = %q{
- file { "/tmp/6418": ensure => directory }
- file { "/tmp/6418/dir": ensure => directory}
- file { "/tmp/6418/dir/dir": ensure => directory}
- file { "/tmp/6418/dir/dir/dir": ensure => directory}
- file { "/tmp/6418-copy": ensure => present, source => "/tmp/6418/" }
-
- File["/tmp/6418"] -> File["/tmp/6418/dir"] -> File["/tmp/6418/dir/dir"] -> File["/tmp/6418/dir/dir/dir"] -> File["/tmp/6418-copy"]
-}
+agents.each do |agent|
+ dir = agent.tmpdir('6418-recurse-audit')
-step "Query agent for statefile"
-agent=agents.first
-on agent, puppet_agent('--configprint statefile')
-statefile=stdout.chomp
+manifest = %Q{
+ file { "#{dir}/6418": ensure => directory }
+ file { "#{dir}/6418/dir": ensure => directory}
+ file { "#{dir}/6418/dir/dir": ensure => directory}
+ file { "#{dir}/6418/dir/dir/dir": ensure => directory}
+ file { "#{dir}/6418-copy": ensure => present, source => "#{dir}/6418/" }
-step "Remove the statefile on all Agents"
-on agents, "rm -f #{statefile}"
+ File["#{dir}/6418"] -> File["#{dir}/6418/dir"] -> File["#{dir}/6418/dir/dir"] -> File["#{dir}/6418/dir/dir/dir"] -> File["#{dir}/6418-copy"]
+}
-step "Apply the manifest"
-apply_manifest_on agents, manifest
+ step "Query agent for statefile"
+ on agent, puppet_agent('--configprint statefile') do
+ statefile=stdout.chomp
+ step "Remove the statefile on the agent"
+ on(agent, "rm -f '#{statefile}'")
-step "Verify corecct file recursion and audit state"
-agents.each do |agent|
- on(agent, "grep ensure.*directory #{statefile}", :acceptable_exit_codes => [ 1 ])
+ step "Apply the manifest"
+ apply_manifest_on agent, manifest
+
+ step "Verify correct file recursion and audit state"
+ on(agent, "grep ensure.*directory '#{statefile}'", :acceptable_exit_codes => [ 1 ])
+ end
end
diff --git a/acceptance/tests/ticket_6541_invalid_filebucket_files.rb b/acceptance/tests/ticket_6541_invalid_filebucket_files.rb
index 2c7136e..11de0e6 100644
--- a/acceptance/tests/ticket_6541_invalid_filebucket_files.rb
+++ b/acceptance/tests/ticket_6541_invalid_filebucket_files.rb
@@ -1,36 +1,33 @@
test_name "#6541: file type truncates target when filebucket cannot retrieve hash"
-target="/tmp/6541-$$"
-on agents, host_command('rm -rf #{host["puppetvardir"]}/*bucket')
+agents.each do |agent|
+ target=agent.tmpfile('6541-target')
-step "write zero length file"
-manifest = "file { '#{target}': content => '' }"
-apply_manifest_on(agents, manifest)
+ on agent, host_command('rm -rf #{host["puppetvardir"]}/*bucket')
-step "overwrite file, causing zero-length file to be backed up"
-manifest = "file { '#{target}': content => 'some text' }"
-apply_manifest_on(agents, manifest)
+ step "write zero length file"
+ manifest = "file { '#{target}': content => '' }"
+ apply_manifest_on(agent, manifest)
-test_name "verify invalid hashes should not change the file"
-manifest = "file { '#{target}': content => '{md5}notahash' }"
-agents.each do |host|
- apply_manifest_on(host, manifest) do
- assert_no_match(/content changed/, stdout, "#{host}: shouldn't have overwrote the file")
+ step "overwrite file, causing zero-length file to be backed up"
+ manifest = "file { '#{target}': content => 'some text' }"
+ apply_manifest_on(agent, manifest)
+
+ test_name "verify invalid hashes should not change the file"
+ manifest = "file { '#{target}': content => '{md5}notahash' }"
+ apply_manifest_on(agent, manifest) do
+ assert_no_match(/content changed/, stdout, "#{agent}: shouldn't have overwrote the file")
end
-end
-test_name "verify valid but unbucketed hashes should not change the file"
-manifest = "file { '#{target}': content => '{md5}13ad7345d56b566a4408ffdcd877bc78' }"
-agents.each do |host|
- apply_manifest_on(host, manifest) do
- assert_no_match(/content changed/, stdout, "#{host}: shouldn't have overwrote the file")
+ test_name "verify valid but unbucketed hashes should not change the file"
+ manifest = "file { '#{target}': content => '{md5}13ad7345d56b566a4408ffdcd877bc78' }"
+ apply_manifest_on(agent, manifest) do
+ assert_no_match(/content changed/, stdout, "#{agent}: shouldn't have overwrote the file")
end
-end
-test_name "verify that an empty file can be retrieved from the filebucket"
-manifest = "file { '#{target}': content => '{md5}d41d8cd98f00b204e9800998ecf8427e' }"
-agents.each do |host|
- apply_manifest_on(host, manifest) do
- assert_match(/content changed '\{md5\}552e21cd4cd9918678e3c1a0df491bc3' to '\{md5\}d41d8cd98f00b204e9800998ecf8427e'/, stdout, "#{host}: shouldn't have overwrote the file")
+ test_name "verify that an empty file can be retrieved from the filebucket"
+ manifest = "file { '#{target}': content => '{md5}d41d8cd98f00b204e9800998ecf8427e' }"
+ apply_manifest_on(agent, manifest) do
+ assert_match(/content changed '\{md5\}552e21cd4cd9918678e3c1a0df491bc3' to '\{md5\}d41d8cd98f00b204e9800998ecf8427e'/, stdout, "#{agent}: shouldn't have overwrote the file")
end
end
diff --git a/acceptance/tests/ticket_6907_use_provider_in_same_run_it_becomes_suitable.rb b/acceptance/tests/ticket_6907_use_provider_in_same_run_it_becomes_suitable.rb
index a9b0b88..2a5d113 100644
--- a/acceptance/tests/ticket_6907_use_provider_in_same_run_it_becomes_suitable.rb
+++ b/acceptance/tests/ticket_6907_use_provider_in_same_run_it_becomes_suitable.rb
@@ -1,9 +1,10 @@
test_name "providers should be useable in the same run they become suitable"
-dir = "/tmp/#{$$}-6907"
+agents.each do |agent|
+ dir = agent.tmpdir('provider-6907')
-on agents, "mkdir -p #{dir}/lib/puppet/{type,provider/test6907}"
-on agents, "cat > #{dir}/lib/puppet/type/test6907.rb", :stdin => <<TYPE
+ on agent, "mkdir -p #{dir}/lib/puppet/{type,provider/test6907}"
+ on agent, "cat > #{dir}/lib/puppet/type/test6907.rb", :stdin => <<TYPE
Puppet::Type.newtype(:test6907) do
newparam(:name, :namevar => true)
@@ -11,7 +12,7 @@
end
TYPE
-on agents, "cat > #{dir}/lib/puppet/provider/test6907/only.rb", :stdin => <<PROVIDER
+ on agent, "cat > #{dir}/lib/puppet/provider/test6907/only.rb", :stdin => <<PROVIDER
Puppet::Type.type(:test6907).provide(:only) do
commands :anything => "#{dir}/must_exist"
require 'fileutils'
@@ -26,7 +27,7 @@ def file=(value)
end
PROVIDER
-on agents, puppet_apply("--libdir #{dir}/lib --trace"), :stdin => <<MANIFEST
+ on agent, puppet_apply("--libdir #{dir}/lib --trace"), :stdin => <<MANIFEST
test6907 { "test-6907":
file => "#{dir}/test_file",
}
@@ -37,4 +38,5 @@ def file=(value)
}
MANIFEST
-on agents, "ls #{dir}/test_file"
+ on agent, "ls #{dir}/test_file"
+end
diff --git a/acceptance/tests/ticket_6928_puppet_master_parse_fails.rb b/acceptance/tests/ticket_6928_puppet_master_parse_fails.rb
index 155e91d..039390c 100644
--- a/acceptance/tests/ticket_6928_puppet_master_parse_fails.rb
+++ b/acceptance/tests/ticket_6928_puppet_master_parse_fails.rb
@@ -11,25 +11,22 @@
step "Agents: create valid, invalid formatted manifests"
agents.each do |host|
- create_remote_file(host, '/tmp/good.pp', %w{notify{good:}} )
- create_remote_file(host, '/tmp/bad.pp', 'notify{bad:')
-end
+ good = host.tmpfile('good-6928')
+ bad = host.tmpfile('bad-6928')
-step "Agents: use --parseonly on an invalid manifest, should return 1 and issue deprecation warning"
-agents.each do |host|
- on(host, "puppet --parseonly /tmp/bad.pp}", :acceptable_exit_codes => [ 1 ]) do
+ create_remote_file(host, good, %w{notify{good:}} )
+ create_remote_file(host, bad, 'notify{bad:')
+
+ step "Agents: use --parseonly on an invalid manifest, should return 1 and issue deprecation warning"
+ on(host, puppet('--parseonly', bad), :acceptable_exit_codes => [ 1 ]) do
assert_match(/--parseonly has been removed. Please use \'puppet parser validate <manifest>\'/, stdout, "Deprecation warning not issued for --parseonly on #{host}" )
end
-end
-step "Test Face for ‘parser validate’ with good manifest -- should pass"
-agents.each do |host|
- on(host, "puppet parser validate /tmp/good.pp", :acceptable_exit_codes => [ 0 ])
-end
+ step "Test Face for 'parser validate' with good manifest -- should pass"
+ on(host, puppet('parser', 'validate', good), :acceptable_exit_codes => [ 0 ])
-step "Test Faces for ‘parser validate’ with bad manifest -- should fail"
-agents.each do |host|
- on(host, "puppet parser validate /tmp/bad.pp", :acceptable_exit_codes => [ 1 ]) do
+ step "Test Faces for 'parser validate' with bad manifest -- should fail"
+ on(host, puppet('parser', 'validate', bad), :acceptable_exit_codes => [ 1 ]) do
assert_match(/err: Could not parse for environment production/, stdout, "Bad manifest detection failed on #{host}" )
end
end
diff --git a/acceptance/tests/ticket_7101_template_compile.rb b/acceptance/tests/ticket_7101_template_compile.rb
index d2ebecd..b2486b0 100644
--- a/acceptance/tests/ticket_7101_template_compile.rb
+++ b/acceptance/tests/ticket_7101_template_compile.rb
@@ -1,25 +1,24 @@
test_name "#7101: template compile"
-manifest = %q{
+agents.each do |agent|
+ template = agent.tmpfile('template_7101.erb')
+ target = agent.tmpfile('file_7101.erb')
+
+ manifest = %Q{
$bar = 'test 7101'
-file { '/tmp/file_7101.erb':
- content => template('/tmp/template_7101.erb')
+file { '#{target}':
+ content => template("#{template}")
}
}
+ step "Agents: Create template file"
+ create_remote_file(agent, template, %w{<%= bar %>} )
-step "Agents: Create template file"
-agents.each do |host|
- create_remote_file(host, '/tmp/template_7101.erb', %w{<%= bar %>} )
-end
-
-step "Run manifest referencing template file"
-apply_manifest_on(agents, manifest)
-
+ step "Run manifest referencing template file"
+ apply_manifest_on(agent, manifest)
-step "Agents: Verify file is created with correct contents "
-agents.each do |host|
- on(host, "cat /tmp/file_7101.erb") do
- assert_match(/test 7101/, stdout, "File /tmp/file_7101.erb not created with correct contents on #{host}" )
+ step "Agents: Verify file is created with correct contents "
+ on(agent, "cat #{target}") do
+ assert_match(/test 7101/, stdout, "File #{target} not created with correct contents on #{agent}" )
end
end
diff --git a/acceptance/tests/ticket_7117_broke_env_criteria_authconf.rb b/acceptance/tests/ticket_7117_broke_env_criteria_authconf.rb
index bb0b0ab..5bace08 100644
--- a/acceptance/tests/ticket_7117_broke_env_criteria_authconf.rb
+++ b/acceptance/tests/ticket_7117_broke_env_criteria_authconf.rb
@@ -14,14 +14,19 @@
on master, "chmod 644 /tmp/auth.conf-7117"
with_master_running_on(master, "--dns_alt_names=\"puppet, $(hostname -s), $(hostname -f)\" --rest_authconfig /tmp/auth.conf-7117 --verbose --autosign true") do
- # Run test on Agents
- step "Run agent to upload facts"
- on agents, puppet_agent("--test --server #{master}")
+ agents.each do |agent|
+ if agent['platform'].include?('windows')
+ Log.warn("Pending: Window's doesn't support hostname -f")
+ next
+ end
+
+ # Run test on Agents
+ step "Run agent to upload facts"
+ on agent, puppet_agent("--test --server #{master}")
- step "Fetch agent facts from Puppet Master"
- agents.each do |host|
- on(host, "curl -k -H \"Accept: yaml\" https://#{master}:8140/override/facts/\`hostname -f\`") do
- assert_match(/--- !ruby\/object:Puppet::Node::Facts/, stdout, "Agent Facts not returned for #{host}")
+ step "Fetch agent facts from Puppet Master"
+ on(agent, "curl -k -H \"Accept: yaml\" https://#{master}:8140/override/facts/\`hostname -f\`") do
+ assert_match(/--- !ruby\/object:Puppet::Node::Facts/, stdout, "Agent Facts not returned for #{agent}")
end
end
end
diff --git a/acceptance/tests/ticket_7139_puppet_resource_file_qualified_paths.rb b/acceptance/tests/ticket_7139_puppet_resource_file_qualified_paths.rb
index f773ba1..7a7b594 100644
--- a/acceptance/tests/ticket_7139_puppet_resource_file_qualified_paths.rb
+++ b/acceptance/tests/ticket_7139_puppet_resource_file_qualified_paths.rb
@@ -1,11 +1,13 @@
-test_name "#7139: Puppet resource file failes on path with leading '/'"
+test_name "#7139: Puppet resource file fails on path with leading '/'"
-step "Agents: create valid, invalid formatted manifests"
-create_remote_file(agents, '/tmp/ticket-7139', %w{foo bar contents} )
+agents.each do |agent|
+ target = agent.tmpfile('ticket-7139')
-step "Run puppet file resource on /tmp/ticket-7139"
-agents.each do |host|
- on(host, "puppet resource file /tmp/ticket-7139") do
- assert_match(/file \{ \'\/tmp\/ticket-7139\':/, stdout, "puppet resource file failed on #{host}")
+ step "Agents: create valid, invalid formatted manifests"
+ create_remote_file(agent, target, %w{foo bar contents} )
+
+ step "Run puppet file resource on #{target}"
+ on(agent, puppet_resource('file', target)) do
+ assert_match(/file \{ \'#{Regexp.escape(target)}\':/, stdout, "puppet resource file failed on #{agent}")
end
end
diff --git a/lib/puppet/application/apply.rb b/lib/puppet/application/apply.rb
index 3e2be48..ef6c4c5 100644
--- a/lib/puppet/application/apply.rb
+++ b/lib/puppet/application/apply.rb
@@ -182,12 +182,12 @@ def main
Puppet[:manifest] = manifest
end
- # Collect our facts.
- unless facts = Puppet::Node::Facts.indirection.find(Puppet[:node_name_value])
- raise "Could not find facts for #{Puppet[:node_name_value]}"
- end
-
unless Puppet[:node_name_fact].empty?
+ # Collect our facts.
+ unless facts = Puppet::Node::Facts.indirection.find(Puppet[:node_name_value])
+ raise "Could not find facts for #{Puppet[:node_name_value]}"
+ end
+
Puppet[:node_name_value] = facts.values[Puppet[:node_name_fact]]
facts.name = Puppet[:node_name_value]
end
@@ -198,7 +198,7 @@ def main
end
# Merge in the facts.
- node.merge(facts.values)
+ node.merge(facts.values) if facts
# Allow users to load the classes that puppet agent creates.
if options[:loadclasses]
diff --git a/lib/puppet/application/kick.rb b/lib/puppet/application/kick.rb
index bf6178e..0b6ddc9 100644
--- a/lib/puppet/application/kick.rb
+++ b/lib/puppet/application/kick.rb
@@ -76,16 +76,30 @@ def help
USAGE NOTES
-----------
-Puppet kick is useless unless puppet agent is listening for incoming
-connections and allowing access to the `run` endpoint. This entails
-starting the agent with `listen = true` in its puppet.conf file, and
-allowing access to the `/run` path in its auth.conf file; see
-`http://docs.puppetlabs.com/guides/rest_auth_conf.html` for more
-details.
-
-Additionally, due to a known bug, you must make sure a
-namespaceauth.conf file exists in puppet agent's $confdir. This file
-will not be consulted, and may be left empty.
+Puppet kick needs the puppet agent on the target machine to be running as a
+daemon, be configured to listen for incoming network connections, and have an
+appropriate security configuration.
+
+The specific changes required are:
+
+* Set `listen = true` in the agent's `puppet.conf` file (or `--listen` on the
+ command line)
+* Configure the node's firewall to allow incoming connections on port 8139
+* Insert the following stanza at the top of the node's `auth.conf` file:
+
+ # Allow puppet kick access
+ path /run
+ method save
+ auth any
+ allow workstation.example.com
+
+This example would allow the machine `workstation.example.com` to trigger a
+Puppet run; adjust the "allow" directive to suit your site. You may also use
+`allow *` to allow anyone to trigger a Puppet run, but that makes it possible
+to interfere with your site by triggering excessive Puppet runs.
+
+See `http://docs.puppetlabs.com/guides/rest_auth_conf.html` for more details
+about security settings.
OPTIONS
-------
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb
index e4c11e5..71d04df 100644
--- a/lib/puppet/defaults.rb
+++ b/lib/puppet/defaults.rb
@@ -1,10 +1,10 @@
-# The majority of the system configuration parameters are set in this file.
+# The majority of Puppet's configuration settings are set in this file.
module Puppet
setdefaults(:main,
- :confdir => [Puppet.run_mode.conf_dir, "The main Puppet configuration directory. The default for this parameter is calculated based on the user. If the process
+ :confdir => [Puppet.run_mode.conf_dir, "The main Puppet configuration directory. The default for this setting is calculated based on the user. If the process
is running as root or the user that Puppet is supposed to run as, it defaults to a system directory, but if it's running as any other user,
it defaults to being in the user's home directory."],
- :vardir => [Puppet.run_mode.var_dir, "Where Puppet stores dynamic and growing data. The default for this parameter is calculated specially, like `confdir`_."],
+ :vardir => [Puppet.run_mode.var_dir, "Where Puppet stores dynamic and growing data. The default for this setting is calculated specially, like `confdir`_."],
:name => [Puppet.application_name.to_s, "The name of the application, if we are running as one. The
default is essentially $0 without the path or `.rb`."],
:run_mode => [Puppet.run_mode.name.to_s, "The effective 'run mode' of the application: master, agent, or user."]
@@ -42,18 +42,16 @@ module Puppet
sense when used interactively. Takes into account arguments specified
on the CLI."],
:configprint => ["",
- "Print the value of a specific configuration parameter. If a
- parameter is provided for this, then the value is printed and puppet
+ "Print the value of a specific configuration setting. If the name of a
+ setting is provided for this, then the value is printed and puppet
exits. Comma-separate multiple values. For a list of all values,
- specify 'all'. This feature is only available in Puppet versions
- higher than 0.18.4."],
+ specify 'all'."],
:color => {
:default => (Puppet.features.microsoft_windows? ? "false" : "ansi"),
:type => :setting,
- :desc => "Whether to use colors when logging to the console.
- Valid values are `ansi` (equivalent to `true`), `html` (mostly
- used during testing with TextMate), and `false`, which produces
- no color.",
+ :desc => "Whether to use colors when logging to the console. Valid values are
+ `ansi` (equivalent to `true`), `html`, and `false`, which produces no color.
+ Defaults to false on Windows, as its console does not support ansi colors.",
},
:mkusers => [false,
"Whether to create the necessary user and group that puppet agent will
@@ -94,9 +92,9 @@ module Puppet
$LOAD_PATH << value
end
},
- :ignoreimport => [false, "A parameter that can be used in commit
- hooks, since it enables you to parse-check a single file rather
- than requiring that all files exist."],
+ :ignoreimport => [false, "If true, allows the parser to continue without requiring
+ all files referenced with `import` statements to exist. This setting was primarily
+ designed for use with commit hooks for parse-checking."],
:authconfig => [ "$confdir/namespaceauth.conf",
"The configuration file that defines the rights to the different
namespaces and methods. This can be used as a coarse-grained
@@ -107,10 +105,13 @@ module Puppet
is used to find modules and much more. For servers (i.e., `puppet master`) this provides the default environment for nodes
we know nothing about."
},
- :diff_args => ["-u", "Which arguments to pass to the diff command when printing differences between files."],
+ :diff_args => ["-u", "Which arguments to pass to the diff command when printing differences between
+ files. The command to use can be chosen with the `diff` setting."],
:diff => {
:default => (Puppet.features.microsoft_windows? ? "" : "diff"),
- :desc => "Which diff command to use when printing differences between files.",
+ :desc => "Which diff command to use when printing differences between files. This setting
+ has no default value on Windows, as standard `diff` is not available, but Puppet can use many
+ third-party diff tools.",
},
:show_diff => [false, "Whether to log and report a contextual diff when files are being replaced. This causes
partial file contents to pass through Puppet's normal logging and reporting system, so this setting should be
@@ -118,7 +119,8 @@ module Puppet
This feature currently requires the `diff/lcs` Ruby library."],
:daemonize => {
:default => (Puppet.features.microsoft_windows? ? false : true),
- :desc => "Send the process into the background. This is the default.",
+ :desc => "Whether to send the process into the background. This defaults to true on POSIX systems,
+ and to false on Windows (where Puppet currently cannot daemonize).",
:short => "D",
:hook => proc do |value|
if value and Puppet.features.microsoft_windows?
@@ -424,12 +426,12 @@ module Puppet
uses that configuration file to determine which keys to sign."},
:allow_duplicate_certs => [false, "Whether to allow a new certificate
request to overwrite an existing certificate."],
- :ca_days => ["", "How long a certificate should be valid.
- This parameter is deprecated, use ca_ttl instead"],
+ :ca_days => ["", "How long a certificate should be valid, in days.
+ This setting is deprecated; use `ca_ttl` instead"],
:ca_ttl => ["5y", "The default TTL for new certificates; valid values
must be an integer, optionally followed by one of the units
'y' (years of 365 days), 'd' (days), 'h' (hours), or
- 's' (seconds). The unit defaults to seconds. If this parameter
+ 's' (seconds). The unit defaults to seconds. If this setting
is set, ca_days is ignored. Examples are '3600' (one hour)
and '1825d', which is the same as '5y' (5 years) "],
:ca_md => ["md5", "The type of hash used in certificates."],
@@ -507,7 +509,7 @@ module Puppet
:ca => [true, "Wether the master should function as a certificate authority."],
:modulepath => {
:default => "$confdir/modules#{File::PATH_SEPARATOR}/usr/share/puppet/modules",
- :desc => "The search path for modules as a list of directories separated by the '#{File::PATH_SEPARATOR}' character.",
+ :desc => "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 ';'.)",
:type => :setting # We don't want this to be considered a file, since it's multiple files.
},
:ssl_client_header => ["HTTP_X_CLIENT_DN", "The header containing an authenticated
@@ -758,7 +760,7 @@ module Puppet
:main,
:factpath => {:default => "$vardir/lib/facter#{File::PATH_SEPARATOR}$vardir/facts",
:desc => "Where Puppet should look for facts. Multiple directories should
- be colon-separated, like normal PATH variables.",
+ be separated by the system path separator character. (The POSIX path separator is ':', and the Windows path separator is ';'.)",
:call_on_define => true, # Call our hook with the default value, so we always get the value added to facter.
:type => :setting, # Don't consider it a file, because it could be multiple colon-separated files
@@ -844,10 +846,10 @@ module Puppet
:main,
:external_nodes => ["none",
- "An external command that can produce node information. The output
- must be a YAML dump of a hash, and that hash must have one or both of
- `classes` and `parameters`, where `classes` is an array and
- `parameters` is a hash. For unknown nodes, the commands should
+ "An external command that can produce node information. The command's output
+ must be a YAML dump of a hash, and that hash must have a `classes` key and/or
+ a `parameters` key, where `classes` is an array or hash and
+ `parameters` is a hash. For unknown nodes, the command should
exit with a non-zero exit code.
This command makes it straightforward to store your node mapping
diff --git a/lib/puppet/forge.rb b/lib/puppet/forge.rb
new file mode 100644
index 0000000..6b3c574
--- /dev/null
+++ b/lib/puppet/forge.rb
@@ -0,0 +1,153 @@
+require 'net/http'
+require 'open-uri'
+require 'pathname'
+require 'uri'
+require 'puppet/forge/cache'
+require 'puppet/forge/repository'
+
+module Puppet::Forge
+ class Forge
+ def initialize(url=Puppet.settings[:module_repository])
+ @uri = URI.parse(url)
+ end
+
+ # Return a list of module metadata hashes that match the search query.
+ # This return value is used by the module_tool face install search,
+ # and displayed to on the console.
+ #
+ # Example return value:
+ #
+ # [
+ # {
+ # "author" => "puppetlabs",
+ # "name" => "bacula",
+ # "tag_list" => ["backup", "bacula"],
+ # "releases" => [{"version"=>"0.0.1"}, {"version"=>"0.0.2"}],
+ # "full_name" => "puppetlabs/bacula",
+ # "version" => "0.0.2",
+ # "project_url" => "http://github.com/puppetlabs/puppetlabs-bacula",
+ # "desc" => "bacula"
+ # }
+ # ]
+ #
+ def search(term)
+ request = Net::HTTP::Get.new("/modules.json?q=#{URI.escape(term)}")
+ response = repository.make_http_request(request)
+
+ case response.code
+ when "200"
+ matches = PSON.parse(response.body)
+ else
+ raise RuntimeError, "Could not execute search (HTTP #{response.code})"
+ matches = []
+ end
+
+ matches
+ end
+
+ # Return a Pathname object representing the path to the module
+ # release package in the `Puppet.settings[:module_working_dir]`.
+ def get_release_package(params)
+ cache_path = nil
+ case params[:source]
+ when :repository
+ if not (params[:author] && params[:modname])
+ raise ArgumentError, ":author and :modename required"
+ end
+ cache_path = get_release_package_from_repository(params[:author], params[:modname], params[:version])
+ when :filesystem
+ if not params[:filename]
+ raise ArgumentError, ":filename required"
+ end
+ cache_path = get_release_package_from_filesystem(params[:filename])
+ else
+ raise ArgumentError, "Could not determine installation source"
+ end
+
+ cache_path
+ end
+
+ def get_releases(author, modname)
+ request_string = "/#{author}/#{modname}"
+
+ begin
+ response = repository.make_http_request(request_string)
+ rescue => e
+ raise ArgumentError, "Could not find a release for this module (#{e.message})"
+ end
+
+ results = PSON.parse(response.body)
+ # At this point releases look like this:
+ # [{"version" => "0.0.1"}, {"version" => "0.0.2"},{"version" => "0.0.3"}]
+ #
+ # Lets fix this up a bit and return something like this to the caller
+ # ["0.0.1", "0.0.2", "0.0.3"]
+ results["releases"].collect {|release| release["version"]}
+ end
+
+ private
+
+ # Locate and download a module release package from the remote forge
+ # repository into the `Puppet.settings[:module_working_dir]`. Do not
+ # unpack it, just return the location of the package on disk.
+ def get_release_package_from_repository(author, modname, version=nil)
+ release = get_release(author, modname, version)
+ if release['file']
+ begin
+ cache_path = repository.retrieve(release['file'])
+ rescue OpenURI::HTTPError => e
+ raise RuntimeError, "Could not download module: #{e.message}"
+ end
+ else
+ raise RuntimeError, "Malformed response from module repository."
+ end
+
+ cache_path
+ end
+
+ # Locate a module release package on the local filesystem and move it
+ # into the `Puppet.settings[:module_working_dir]`. Do not unpack it, just
+ # return the location of the package on disk.
+ def get_release_package_from_filesystem(filename)
+ if File.exist?(File.expand_path(filename))
+ repository = Repository.new('file:///')
+ uri = URI.parse("file://#{URI.escape(File.expand_path(filename))}")
+ cache_path = repository.retrieve(uri)
+ else
+ raise ArgumentError, "File does not exists: #{filename}"
+ end
+
+ cache_path
+ end
+
+ def repository
+ @repository ||= Puppet::Forge::Repository.new(@uri)
+ end
+
+ # Connect to the remote repository and locate a specific module release
+ # by author/name combination. If a version requirement is specified, search
+ # for that exact version, or grab the latest release available.
+ #
+ # Return the following response to the caller:
+ #
+ # {"file"=>"/system/releases/p/puppetlabs/puppetlabs-apache-0.0.3.tar.gz", "version"=>"0.0.3"}
+ #
+ #
+ def get_release(author, modname, version_requirement=nil)
+ request_string = "/users/#{author}/modules/#{modname}/releases/find.json"
+ if version_requirement
+ request_string + "?version=#{URI.escape(version_requirement)}"
+ end
+ request = Net::HTTP::Get.new(request_string)
+
+ begin
+ response = repository.make_http_request(request)
+ rescue => e
+ raise ArgumentError, "Could not find a release for this module (#{e.message})"
+ end
+
+ PSON.parse(response.body)
+ end
+ end
+end
+
diff --git a/lib/puppet/forge/cache.rb b/lib/puppet/forge/cache.rb
new file mode 100644
index 0000000..253f247
--- /dev/null
+++ b/lib/puppet/forge/cache.rb
@@ -0,0 +1,55 @@
+require 'uri'
+
+module Puppet::Forge
+ # = Cache
+ #
+ # Provides methods for reading files from local cache, filesystem or network.
+ class Cache
+
+ # Instantiate new cahe for the +repositry+ instance.
+ def initialize(repository, options = {})
+ @repository = repository
+ @options = options
+ end
+
+ # Return filename retrieved from +uri+ instance. Will download this file and
+ # cache it if needed.
+ #
+ # TODO: Add checksum support.
+ # TODO: Add error checking.
+ def retrieve(url)
+ (path + File.basename(url.to_s)).tap do |cached_file|
+ uri = url.is_a?(::URI) ? url : ::URI.parse(url)
+ unless cached_file.file?
+ if uri.scheme == 'file'
+ FileUtils.cp(URI.unescape(uri.path), cached_file)
+ else
+ # TODO: Handle HTTPS; probably should use repository.contact
+ data = read_retrieve(uri)
+ cached_file.open('wb') { |f| f.write data }
+ end
+ end
+ end
+ end
+
+ # Return contents of file at the given URI's +uri+.
+ def read_retrieve(uri)
+ return uri.read
+ end
+
+ # Return Pathname for repository's cache directory, create it if needed.
+ def path
+ return @path ||= (self.class.base_path + @repository.cache_key).tap{ |o| o.mkpath }
+ end
+
+ # Return the base Pathname for all the caches.
+ def self.base_path
+ Pathname(Puppet.settings[:module_working_dir]) + 'cache'
+ end
+
+ # Clean out all the caches.
+ def self.clean
+ base_path.rmtree if base_path.exist?
+ end
+ end
+end
diff --git a/lib/puppet/forge/repository.rb b/lib/puppet/forge/repository.rb
new file mode 100644
index 0000000..2e10149
--- /dev/null
+++ b/lib/puppet/forge/repository.rb
@@ -0,0 +1,121 @@
+require 'net/http'
+require 'digest/sha1'
+require 'uri'
+
+require 'puppet/module_tool/utils'
+
+module Puppet::Forge
+ # Directory names that should not be checksummed.
+ ARTIFACTS = ['pkg', /^\./, /^~/, /^#/, 'coverage']
+ FULL_MODULE_NAME_PATTERN = /\A([^-\/|.]+)[-|\/](.+)\z/
+ REPOSITORY_URL = Puppet.settings[:module_repository]
+
+ # = Repository
+ #
+ # This class is a file for accessing remote repositories with modules.
+ class Repository
+ include Puppet::Module::Tool::Utils::Interrogation
+
+ attr_reader :uri, :cache
+
+ # Instantiate a new repository instance rooted at the optional string
+ # +url+, else an instance of the default Puppet modules repository.
+ def initialize(url=Puppet[:module_repository])
+ @uri = url.is_a?(::URI) ? url : ::URI.parse(url)
+ @cache = Cache.new(self)
+ end
+
+ # Read HTTP proxy configurationm from Puppet's config file, or the
+ # http_proxy environment variable.
+ def http_proxy_env
+ proxy_env = ENV["http_proxy"] || ENV["HTTP_PROXY"] || nil
+ begin
+ return URI.parse(proxy_env) if proxy_env
+ rescue URI::InvalidURIError
+ return nil
+ end
+ return nil
+ end
+
+ def http_proxy_host
+ env = http_proxy_env
+
+ if env and env.host then
+ return env.host
+ end
+
+ if Puppet.settings[:http_proxy_host] == 'none'
+ return nil
+ end
+
+ return Puppet.settings[:http_proxy_host]
+ end
+
+ def http_proxy_port
+ env = http_proxy_env
+
+ if env and env.port then
+ return env.port
+ end
+
+ return Puppet.settings[:http_proxy_port]
+ end
+
+ # Return a Net::HTTPResponse read for this +request+.
+ #
+ # Options:
+ # * :authenticate => Request authentication on the terminal. Defaults to false.
+ def make_http_request(request, options = {})
+ if options[:authenticate]
+ authenticate(request)
+ end
+ if ! @uri.user.nil? && ! @uri.password.nil?
+ request.basic_auth(@uri.user, @uri.password)
+ end
+ return read_response(request)
+ end
+
+ # Return a Net::HTTPResponse read from this HTTPRequest +request+.
+ def read_response(request)
+ begin
+ Net::HTTP::Proxy(
+ http_proxy_host,
+ http_proxy_port
+ ).start(@uri.host, @uri.port) do |http|
+ http.request(request)
+ end
+ rescue Errno::ECONNREFUSED, SocketError
+ raise RuntimeError, "Could not reach remote repository"
+ end
+ end
+
+ # Set the HTTP Basic Authentication parameters for the Net::HTTPRequest
+ # +request+ by asking the user for input on the console.
+ def authenticate(request)
+ Puppet.notice "Authenticating for #{@uri}"
+ email = prompt('Email Address')
+ password = prompt('Password', true)
+ request.basic_auth(email, password)
+ end
+
+ # Return the local file name containing the data downloaded from the
+ # repository at +release+ (e.g. "myuser-mymodule").
+ def retrieve(release)
+ return cache.retrieve(@uri + release)
+ end
+
+ # Return the URI string for this repository.
+ def to_s
+ return @uri.to_s
+ end
+
+ # Return the cache key for this repository, this a hashed string based on
+ # the URI.
+ def cache_key
+ return @cache_key ||= [
+ @uri.to_s.gsub(/[^[:alnum:]]+/, '_').sub(/_$/, ''),
+ Digest::SHA1.hexdigest(@uri.to_s)
+ ].join('-')
+ end
+ end
+end
diff --git a/lib/puppet/module_tool.rb b/lib/puppet/module_tool.rb
index c11fd58..6d8d4db 100644
--- a/lib/puppet/module_tool.rb
+++ b/lib/puppet/module_tool.rb
@@ -37,42 +37,6 @@ def self.username_and_modname_from(full_module_name)
end
end
- # Read HTTP proxy configurationm from Puppet's config file, or the
- # http_proxy environment variable.
- def self.http_proxy_env
- proxy_env = ENV["http_proxy"] || ENV["HTTP_PROXY"] || nil
- begin
- return URI.parse(proxy_env) if proxy_env
- rescue URI::InvalidURIError
- return nil
- end
- return nil
- end
-
- def self.http_proxy_host
- env = http_proxy_env
-
- if env and env.host then
- return env.host
- end
-
- if Puppet.settings[:http_proxy_host] == 'none'
- return nil
- end
-
- return Puppet.settings[:http_proxy_host]
- end
-
- def self.http_proxy_port
- env = http_proxy_env
-
- if env and env.port then
- return env.port
- end
-
- return Puppet.settings[:http_proxy_port]
- end
-
def self.find_module_root(path)
for dir in [path, Dir.pwd].compact
if File.exist?(File.join(dir, 'Modulefile'))
@@ -87,11 +51,11 @@ def self.find_module_root(path)
# Load remaining libraries
require 'puppet/module_tool/applications'
-require 'puppet/module_tool/cache'
require 'puppet/module_tool/checksums'
require 'puppet/module_tool/contents_description'
require 'puppet/module_tool/dependency'
require 'puppet/module_tool/metadata'
require 'puppet/module_tool/modulefile'
-require 'puppet/module_tool/repository'
require 'puppet/module_tool/skeleton'
+require 'puppet/forge/cache'
+require 'puppet/forge'
diff --git a/lib/puppet/module_tool/applications/application.rb b/lib/puppet/module_tool/applications/application.rb
index 5f8c0c4..43d5c04 100644
--- a/lib/puppet/module_tool/applications/application.rb
+++ b/lib/puppet/module_tool/applications/application.rb
@@ -16,10 +16,6 @@ def initialize(options = {})
@options = options
end
- def repository
- @repository ||= Repository.new(@options[:module_repository])
- end
-
def run
raise NotImplementedError, "Should be implemented in child classes."
end
diff --git a/lib/puppet/module_tool/applications/cleaner.rb b/lib/puppet/module_tool/applications/cleaner.rb
index c42687f..b811983 100644
--- a/lib/puppet/module_tool/applications/cleaner.rb
+++ b/lib/puppet/module_tool/applications/cleaner.rb
@@ -2,7 +2,7 @@ module Puppet::Module::Tool
module Applications
class Cleaner < Application
def run
- Puppet::Module::Tool::Cache.clean
+ Puppet::Forge::Cache.clean
# Return a status Hash containing the status of the clean command
# and a status message. This return value is used by the module_tool
diff --git a/lib/puppet/module_tool/applications/installer.rb b/lib/puppet/module_tool/applications/installer.rb
index ad423bd..d76e0e3 100644
--- a/lib/puppet/module_tool/applications/installer.rb
+++ b/lib/puppet/module_tool/applications/installer.rb
@@ -7,22 +7,26 @@ module Applications
class Installer < Application
def initialize(name, options = {})
+ @forge = Puppet::Forge::Forge.new
+ @install_params = {}
+
if File.exist?(name)
if File.directory?(name)
# TODO Unify this handling with that of Unpacker#check_clobber!
raise ArgumentError, "Module already installed: #{name}"
end
- @source = :filesystem
@filename = File.expand_path(name)
+ @install_params[:source] = :filesystem
+ @install_params[:filename] = @filename
parse_filename!
else
- @source = :repository
+ @install_params[:source] = :repository
begin
- @username, @module_name = Puppet::Module::Tool::username_and_modname_from(name)
+ @install_params[:author], @install_params[:modname] = Puppet::Module::Tool::username_and_modname_from(name)
rescue ArgumentError
raise "Could not install module with invalid name: #{name}"
end
- @version_requirement = options[:version]
+ @install_params[:version_requirement] = options[:version]
end
super(options)
end
@@ -32,27 +36,9 @@ def force?
end
def run
- case @source
- when :repository
- if match['file']
- begin
- cache_path = repository.retrieve(match['file'])
- rescue OpenURI::HTTPError => e
- raise RuntimeError, "Could not install module: #{e.message}"
- end
- module_dir = Unpacker.run(cache_path, options)
- else
- raise RuntimeError, "Malformed response from module repository."
- end
- when :filesystem
- repository = Repository.new('file:///')
- uri = URI.parse("file://#{URI.escape(File.expand_path(@filename))}")
- cache_path = repository.retrieve(uri)
- module_dir = Unpacker.run(cache_path, options)
- else
- raise ArgumentError, "Could not determine installation source"
- end
+ cache_path = @forge.get_release_package(@install_params)
+ module_dir = Unpacker.run(cache_path, options)
# Return the Pathname object representing the path to the installed
# module. This return value is used by the module_tool face install
# action, and displayed to on the console.
@@ -63,27 +49,6 @@ def run
#
module_dir
end
-
- private
-
- def match
- return @match ||= begin
- url = repository.uri + "/users/#{@username}/modules/#{@module_name}/releases/find.json"
- if @version_requirement
- url.query = "version=#{URI.escape(@version_requirement)}"
- end
- begin
- raw_result = read_match(url)
- rescue => e
- raise ArgumentError, "Could not find a release for this module (#{e.message})"
- end
- @match = PSON.parse(raw_result)
- end
- end
-
- def read_match(url)
- return url.read
- end
end
end
end
diff --git a/lib/puppet/module_tool/applications/searcher.rb b/lib/puppet/module_tool/applications/searcher.rb
index 0a2267b..97028cd 100644
--- a/lib/puppet/module_tool/applications/searcher.rb
+++ b/lib/puppet/module_tool/applications/searcher.rb
@@ -4,36 +4,12 @@ class Searcher < Application
def initialize(term, options = {})
@term = term
+ @forge = Puppet::Forge::Forge.new
super(options)
end
def run
- request = Net::HTTP::Get.new("/modules.json?q=#{URI.escape(@term)}")
- response = repository.make_http_request(request)
- case response
- when Net::HTTPOK
- matches = PSON.parse(response.body)
- else
- raise RuntimeError, "Could not execute search (HTTP #{response.code})"
- matches = []
- end
-
- # Return a list of module metadata hashes that match the search query.
- # This return value is used by the module_tool face install search,
- # and displayed to on the console.
- #
- # Example return value:
- #
- # [
- # {
- # "name" => "nginx",
- # "project_url" => "http://github.com/puppetlabs/puppetlabs-nginx",
- # "version" => "0.0.1",
- # "full_name" => "puppetlabs/nginx" # full_name comes back from
- # } # API all to the forge.
- # ]
- #
- matches
+ @forge.search(@term)
end
end
end
diff --git a/lib/puppet/module_tool/applications/unpacker.rb b/lib/puppet/module_tool/applications/unpacker.rb
index 6dd1fca..119eaf3 100644
--- a/lib/puppet/module_tool/applications/unpacker.rb
+++ b/lib/puppet/module_tool/applications/unpacker.rb
@@ -36,7 +36,7 @@ def tag_revision
def extract_module_to_install_dir
delete_existing_installation_or_abort!
- build_dir = Puppet::Module::Tool::Cache.base_path + "tmp-unpacker-#{Digest::SHA1.hexdigest(@filename.basename.to_s)}"
+ build_dir = Puppet::Forge::Cache.base_path + "tmp-unpacker-#{Digest::SHA1.hexdigest(@filename.basename.to_s)}"
build_dir.mkpath
begin
Puppet.notice "Installing #{@filename.basename} to #{@module_dir.expand_path}"
diff --git a/lib/puppet/module_tool/cache.rb b/lib/puppet/module_tool/cache.rb
deleted file mode 100644
index b254780..0000000
--- a/lib/puppet/module_tool/cache.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-require 'uri'
-
-module Puppet::Module::Tool
-
- # = Cache
- #
- # Provides methods for reading files from local cache, filesystem or network.
- class Cache
-
- # Instantiate new cahe for the +repositry+ instance.
- def initialize(repository, options = {})
- @repository = repository
- @options = options
- end
-
- # Return filename retrieved from +uri+ instance. Will download this file and
- # cache it if needed.
- #
- # TODO: Add checksum support.
- # TODO: Add error checking.
- def retrieve(url)
- (path + File.basename(url.to_s)).tap do |cached_file|
- uri = url.is_a?(::URI) ? url : ::URI.parse(url)
- unless cached_file.file?
- if uri.scheme == 'file'
- FileUtils.cp(URI.unescape(uri.path), cached_file)
- else
- # TODO: Handle HTTPS; probably should use repository.contact
- data = read_retrieve(uri)
- cached_file.open('wb') { |f| f.write data }
- end
- end
- end
- end
-
- # Return contents of file at the given URI's +uri+.
- def read_retrieve(uri)
- return uri.read
- end
-
- # Return Pathname for repository's cache directory, create it if needed.
- def path
- return @path ||= (self.class.base_path + @repository.cache_key).tap{ |o| o.mkpath }
- end
-
- # Return the base Pathname for all the caches.
- def self.base_path
- Pathname(Puppet.settings[:module_working_dir]) + 'cache'
- end
-
- # Clean out all the caches.
- def self.clean
- base_path.rmtree if base_path.exist?
- end
- end
-end
diff --git a/lib/puppet/module_tool/dependency.rb b/lib/puppet/module_tool/dependency.rb
index bb55f59..d0eead1 100644
--- a/lib/puppet/module_tool/dependency.rb
+++ b/lib/puppet/module_tool/dependency.rb
@@ -10,7 +10,7 @@ def initialize(full_module_name, version_requirement = nil, repository = nil)
# TODO: add error checking, the next line raises ArgumentError when +full_module_name+ is invalid
@username, @name = Puppet::Module::Tool.username_and_modname_from(full_module_name)
@version_requirement = version_requirement
- @repository = repository ? Repository.new(repository) : nil
+ @repository = repository ? Puppet::Forge::Repository.new(repository) : nil
end
# Return PSON representation of this data.
diff --git a/lib/puppet/module_tool/repository.rb b/lib/puppet/module_tool/repository.rb
deleted file mode 100644
index 7f0ad84..0000000
--- a/lib/puppet/module_tool/repository.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-require 'net/http'
-require 'digest/sha1'
-require 'uri'
-
-module Puppet::Module::Tool
-
- # = Repository
- #
- # This class is a file for accessing remote repositories with modules.
- class Repository
- include Utils::Interrogation
-
- attr_reader :uri, :cache
-
- # Instantiate a new repository instance rooted at the optional string
- # +url+, else an instance of the default Puppet modules repository.
- def initialize(url=Puppet[:module_repository])
- @uri = url.is_a?(::URI) ? url : ::URI.parse(url)
- @cache = Cache.new(self)
- end
-
- # Return a Net::HTTPResponse read for this +request+.
- #
- # Options:
- # * :authenticate => Request authentication on the terminal. Defaults to false.
- def make_http_request(request, options = {})
- if options[:authenticate]
- authenticate(request)
- end
- if ! @uri.user.nil? && ! @uri.password.nil?
- request.basic_auth(@uri.user, @uri.password)
- end
- return read_response(request)
- end
-
- # Return a Net::HTTPResponse read from this HTTPRequest +request+.
- def read_response(request)
- begin
- Net::HTTP::Proxy(
- Puppet::Module::Tool::http_proxy_host,
- Puppet::Module::Tool::http_proxy_port
- ).start(@uri.host, @uri.port) do |http|
- http.request(request)
- end
- rescue Errno::ECONNREFUSED, SocketError
- raise RuntimeError, "Could not reach remote repository"
- end
- end
-
- # Set the HTTP Basic Authentication parameters for the Net::HTTPRequest
- # +request+ by asking the user for input on the console.
- def authenticate(request)
- Puppet.notice "Authenticating for #{@uri}"
- email = prompt('Email Address')
- password = prompt('Password', true)
- request.basic_auth(email, password)
- end
-
- # Return the local file name containing the data downloaded from the
- # repository at +release+ (e.g. "myuser-mymodule").
- def retrieve(release)
- return cache.retrieve(@uri + release)
- end
-
- # Return the URI string for this repository.
- def to_s
- return @uri.to_s
- end
-
- # Return the cache key for this repository, this a hashed string based on
- # the URI.
- def cache_key
- return @cache_key ||= [
- @uri.to_s.gsub(/[^[:alnum:]]+/, '_').sub(/_$/, ''),
- Digest::SHA1.hexdigest(@uri.to_s)
- ].join('-')
- end
- end
-end
diff --git a/lib/puppet/network/http/handler.rb b/lib/puppet/network/http/handler.rb
index 2c78a02..a105d8b 100644
--- a/lib/puppet/network/http/handler.rb
+++ b/lib/puppet/network/http/handler.rb
@@ -89,7 +89,10 @@ def do_exception(response, exception, status=400)
status = 403 if status == 400
end
if exception.is_a?(Exception)
- puts exception.backtrace if Puppet[:trace]
+ if Puppet[:trace] then
+ puts exception.backtrace
+ Puppet.err(exception.backtrace.join("\n"))
+ end
Puppet.err(exception)
end
set_content_type(response, "text/plain")
diff --git a/lib/puppet/provider/exec/windows.rb b/lib/puppet/provider/exec/windows.rb
index 76ca1b3..ee12680 100644
--- a/lib/puppet/provider/exec/windows.rb
+++ b/lib/puppet/provider/exec/windows.rb
@@ -6,9 +6,31 @@
confine :operatingsystem => :windows
defaultfor :operatingsystem => :windows
- desc "Execute external binaries directly, on Windows systems.
-This does not pass through a shell, or perform any interpolation, but
-only directly calls the command with the arguments given."
+ desc <<-EOT
+ Execute external binaries on Windows systems. As with the `posix`
+ provider, this provider directly calls the command with the arguments
+ given, without passing it through a shell or performing any interpolation.
+ To use shell built-ins --- that is, to emulate the `shell` provider on
+ Windows --- a command must explicitly invoke the shell:
+
+ exec {'echo foo':
+ command => 'cmd.exe /c echo "foo"',
+ }
+
+ If no extension is specified for a command, Windows will use the `PATHEXT`
+ environment variable to locate the executable.
+
+ **Note on PowerShell scripts:** PowerShell's default `restricted`
+ execution policy doesn't allow it to run saved scripts. To run PowerShell
+ scripts, specify the `remotesigned` execution policy as part of the
+ command:
+
+ exec { 'test':
+ path => 'C:/Windows/System32/WindowsPowerShell/v1.0',
+ command => 'powershell -executionpolicy remotesigned -file C:/test.ps1',
+ }
+
+ EOT
# Verify that we have the executable
def checkexe(command)
diff --git a/lib/puppet/provider/file/posix.rb b/lib/puppet/provider/file/posix.rb
index 480bbe4..5ab84b4 100644
--- a/lib/puppet/provider/file/posix.rb
+++ b/lib/puppet/provider/file/posix.rb
@@ -1,5 +1,5 @@
Puppet::Type.type(:file).provide :posix do
- desc "Uses POSIX functionality to manage file's users and rights."
+ desc "Uses POSIX functionality to manage file ownership and permissions."
confine :feature => :posix
diff --git a/lib/puppet/provider/file/windows.rb b/lib/puppet/provider/file/windows.rb
index 254fba3..bb31df9 100644
--- a/lib/puppet/provider/file/windows.rb
+++ b/lib/puppet/provider/file/windows.rb
@@ -1,5 +1,5 @@
Puppet::Type.type(:file).provide :windows do
- desc "Uses Microsoft Windows functionality to manage file's users and rights."
+ desc "Uses Microsoft Windows functionality to manage file ownership and permissions."
confine :operatingsystem => :windows
diff --git a/lib/puppet/provider/group/windows_adsi.rb b/lib/puppet/provider/group/windows_adsi.rb
index 83dd00b..6d086da 100644
--- a/lib/puppet/provider/group/windows_adsi.rb
+++ b/lib/puppet/provider/group/windows_adsi.rb
@@ -1,7 +1,7 @@
require 'puppet/util/adsi'
Puppet::Type.type(:group).provide :windows_adsi do
- desc "Group management for Windows"
+ desc "Local group management for Windows. Nested groups are not supported."
defaultfor :operatingsystem => :windows
confine :operatingsystem => :windows
diff --git a/lib/puppet/provider/package/msi.rb b/lib/puppet/provider/package/msi.rb
index c2ab37d..86b5eac 100644
--- a/lib/puppet/provider/package/msi.rb
+++ b/lib/puppet/provider/package/msi.rb
@@ -1,7 +1,13 @@
require 'puppet/provider/package'
Puppet::Type.type(:package).provide(:msi, :parent => Puppet::Provider::Package) do
- desc "Package management by installing and removing MSIs."
+ desc "Windows package management by installing and removing MSIs.
+
+ This provider requires a `source` attribute, and will accept paths to local
+ files or files on mapped drives.
+
+ This provider cannot uninstall arbitrary MSI packages; it can only uninstall
+ packages which were originally installed by Puppet."
confine :operatingsystem => :windows
defaultfor :operatingsystem => :windows
diff --git a/lib/puppet/provider/package/zypper.rb b/lib/puppet/provider/package/zypper.rb
index b0caf28..8323a4c 100644
--- a/lib/puppet/provider/package/zypper.rb
+++ b/lib/puppet/provider/package/zypper.rb
@@ -10,7 +10,8 @@
#on zypper versions <1.0, the version option returns 1
#some versions of zypper output on stderr
def zypper_version
- zypper "--version", { :failonfail => false, :combine => true}
+ cmd = [self.class.command(:zypper),"--version"]
+ execute(cmd, { :failonfail => false, :combine => true})
end
# Install a package using 'zypper'.
diff --git a/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb b/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb
index a3d8084..3e8f2bc 100644
--- a/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb
+++ b/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb
@@ -6,8 +6,12 @@
end
Puppet::Type.type(:scheduled_task).provide(:win32_taskscheduler) do
- desc 'This uses the win32-taskscheduler gem to provide support for
- managing scheduled tasks on Windows.'
+ desc %q{This provider uses the win32-taskscheduler gem to manage scheduled
+ tasks on Windows.
+
+ Puppet requires version 0.2.1 or later of the win32-taskscheduler gem;
+ previous versions can cause "Could not evaluate: The operation completed
+ successfully" errors.}
defaultfor :operatingsystem => :windows
confine :operatingsystem => :windows
diff --git a/lib/puppet/provider/service/windows.rb b/lib/puppet/provider/service/windows.rb
index e773fa5..717e585 100644
--- a/lib/puppet/provider/service/windows.rb
+++ b/lib/puppet/provider/service/windows.rb
@@ -5,11 +5,12 @@
Puppet::Type.type(:service).provide :windows do
desc <<-EOT
- Support for Windows Service Control Manager (SCM).
+ Support for Windows Service Control Manager (SCM). This provider can
+ start, stop, enable, and disable services, and the SCM provides working
+ status methods for all services.
- Services are controlled according to the capabilities of the `win32-service`
- gem. All SCM operations (start/stop/enable/disable/query) are supported.
- Control of service groups (dependencies) is not yet supported.
+ Control of service groups (dependencies) is not yet supported, nor is running
+ services as a specific user.
EOT
defaultfor :operatingsystem => :windows
diff --git a/lib/puppet/provider/user/windows_adsi.rb b/lib/puppet/provider/user/windows_adsi.rb
index 045a84b..e3d323d 100644
--- a/lib/puppet/provider/user/windows_adsi.rb
+++ b/lib/puppet/provider/user/windows_adsi.rb
@@ -1,7 +1,7 @@
require 'puppet/util/adsi'
Puppet::Type.type(:user).provide :windows_adsi do
- desc "User management for Windows."
+ desc "Local user management for Windows."
defaultfor :operatingsystem => :windows
confine :operatingsystem => :windows
diff --git a/lib/puppet/type/file.rb b/lib/puppet/type/file.rb
index a7608c9..fe08082 100644
--- a/lib/puppet/type/file.rb
+++ b/lib/puppet/type/file.rb
@@ -17,16 +17,18 @@
include Puppet::Util::Backups
include Puppet::Util::SymbolicFileMode
- @doc = "Manages local files, including setting ownership and
- permissions, creation of both files and directories, and
- retrieving entire files from remote servers. As Puppet matures, it
- expected that the `file` resource will be used less and less to
- manage content, and instead native resources will be used to do so.
+ @doc = "Manages files, including their content, ownership, and permissions.
- If you find that you are often copying files in from a central
- location, rather than using native resources, please contact
- Puppet Labs and we can hopefully work with you to develop a
- native resource to support what you are doing.
+ The `file` type can manage normal files, directories, and symlinks; the
+ type should be specified in the `ensure` attribute. Note that symlinks cannot
+ be managed on Windows systems.
+
+ File contents can be managed directly with the `content` attribute, or
+ downloaded from a remote source using the `source` attribute; the latter
+ can also be used to recursively serve directories (when the `recurse`
+ attribute is set to `true` or `local`). On Windows, note that file
+ contents are managed in binary mode; Puppet never automatically translates
+ line endings.
**Autorequires:** If Puppet is managing the user or group that owns a
file, the file resource will autorequire them. If Puppet is managing any
@@ -37,7 +39,12 @@ def self.title_patterns
end
newparam(:path) do
- desc "The path to the file to manage. Must be fully qualified."
+ desc <<-EOT
+ The path to the file to manage. Must be fully qualified.
+
+ On Windows, the path should include the drive letter and should use `/` as
+ the separator character (rather than `\\`).
+ EOT
isnamevar
validate do |value|
@@ -191,9 +198,11 @@ def self.title_patterns
end
newparam(:replace, :boolean => true) do
- desc "Whether or not to replace a file that is
- sourced but exists. This is useful for using file sources
- purely for initialization."
+ desc "Whether to replace a file that already exists on the local system but
+ whose content doesn't match what the `source` or `content` attribute
+ specifies. Setting this to false allows file resources to initialize files
+ without overwriting future changes. Note that this only affects content;
+ Puppet will still manage ownership and permissions."
newvalues(:true, :false)
aliasvalue(:yes, :true)
aliasvalue(:no, :false)
@@ -251,11 +260,11 @@ def self.title_patterns
newparam(:sourceselect) do
desc "Whether to copy all valid sources, or just the first one. This parameter
- is only used in recursive copies; by default, the first valid source is the
- only one used as a recursive source, but if this parameter is set to `all`,
- then all valid sources will have all of their contents copied to the local host,
- and for sources that have the same file, the source earlier in the list will
- be used."
+ only affects recursive directory copies; by default, the first valid
+ source is the only one used, but if this parameter is set to `all`, then
+ all valid sources will have all of their contents copied to the local
+ system. If a given file exists in more than one source, the version from
+ the earliest source in the list will be used."
defaultto :first
diff --git a/lib/puppet/type/file/checksum.rb b/lib/puppet/type/file/checksum.rb
index 5586b13..3fd37d4 100755
--- a/lib/puppet/type/file/checksum.rb
+++ b/lib/puppet/type/file/checksum.rb
@@ -5,9 +5,9 @@
Puppet::Type.type(:file).newparam(:checksum) do
include Puppet::Util::Checksums
- desc "The checksum type to use when checksumming a file.
+ desc "The checksum type to use when determining whether to replace a file's contents.
- The default checksum parameter, if checksums are enabled, is md5."
+ The default checksum type is md5."
newvalues "md5", "md5lite", "mtime", "ctime", "none"
diff --git a/lib/puppet/type/file/content.rb b/lib/puppet/type/file/content.rb
index 8f3b8b4..b1009a2 100755
--- a/lib/puppet/type/file/content.rb
+++ b/lib/puppet/type/file/content.rb
@@ -15,27 +15,32 @@ module Puppet
attr_reader :actual_content
- desc "Specify the contents of a file as a string. Newlines, tabs, and
- spaces can be specified using standard escaped syntax in
- double-quoted strings (e.g., \\n for a newline).
+ desc <<-EOT
+ The desired contents of a file, as a string. This attribute is mutually
+ exclusive with `source` and `target`.
- With very small files, you can construct strings directly...
+ Newlines and tabs can be specified in double-quoted strings using
+ standard escaped syntax --- \n for a newline, and \t for a tab.
+
+ With very small files, you can construct content strings directly in
+ the manifest...
define resolve(nameserver1, nameserver2, domain, search) {
- $str = \"search $search
+ $str = "search $search
domain $domain
nameserver $nameserver1
nameserver $nameserver2
- \"
+ "
- file { \"/etc/resolv.conf\":
- content => $str
+ file { "/etc/resolv.conf":
+ content => "$str",
}
}
...but for larger files, this attribute is more useful when combined with the
[template](http://docs.puppetlabs.com/references/latest/function.html#template)
- function."
+ function.
+ EOT
# Store a checksum as the value, rather than the actual content.
# Simplifies everything.
diff --git a/lib/puppet/type/file/ensure.rb b/lib/puppet/type/file/ensure.rb
index b7614f3..9979f76 100755
--- a/lib/puppet/type/file/ensure.rb
+++ b/lib/puppet/type/file/ensure.rb
@@ -10,11 +10,12 @@ module Puppet
Possible values are *absent*, *present*, *file*, and *directory*.
Specifying `present` will match any form of file existence, and
if the file is missing will create an empty file. Specifying
- `absent` will delete the file (and directory if `recurse => true`).
+ `absent` will delete the file (or directory, if `recurse => true`).
- Anything other than those values will create a symlink. In the interest
- of readability and clarity, you should use `ensure => link` and
- explicitly specify a target; however, if a `target` attribute isn't
+ Anything other than the above values will create a symlink; note that
+ symlinks cannot be managed on Windows. In the interest of readability
+ and clarity, symlinks should be created by setting `ensure => link` and
+ explicitly specifying a target; however, if a `target` attribute isn't
provided, the value of the `ensure` attribute will be used as the
symlink target. The following two declarations are equivalent:
diff --git a/lib/puppet/type/file/group.rb b/lib/puppet/type/file/group.rb
index 4310a10..a904996 100755
--- a/lib/puppet/type/file/group.rb
+++ b/lib/puppet/type/file/group.rb
@@ -3,8 +3,16 @@
# Manage file group ownership.
module Puppet
Puppet::Type.type(:file).newproperty(:group) do
- desc "Which group should own the file. Argument can be either group
- name or group ID."
+ desc <<-EOT
+ Which group should own the file. Argument can be either a group
+ name or a group ID.
+
+ On Windows, a user (such as "Administrator") can be set as a file's group
+ and a group (such as "Administrators") can be set as a file's owner;
+ however, a file's owner and group shouldn't be the same. (If the owner
+ is also the group, files with modes like `0640` will cause log churn, as
+ they will always appear out of sync.)
+ EOT
validate do |group|
raise(Puppet::Error, "Invalid group name '#{group.inspect}'") unless group and group != ""
diff --git a/lib/puppet/type/file/mode.rb b/lib/puppet/type/file/mode.rb
index 8c7020b..b5dd2e2 100755
--- a/lib/puppet/type/file/mode.rb
+++ b/lib/puppet/type/file/mode.rb
@@ -6,24 +6,52 @@ module Puppet
require 'puppet/util/symbolic_file_mode'
include Puppet::Util::SymbolicFileMode
- desc "Mode the file should be. Currently relatively limited:
- you must specify the exact mode the file should be.
-
- Note that when you set the mode of a directory, Puppet always
- sets the search/traverse (1) bit anywhere the read (4) bit is set.
- This is almost always what you want: read allows you to list the
- entries in a directory, and search/traverse allows you to access
- (read/write/execute) those entries.) Because of this feature, you
- can recursively make a directory and all of the files in it
- world-readable by setting e.g.:
-
- file { '/some/dir':
- mode => 644,
- recurse => true,
- }
-
- In this case all of the files underneath `/some/dir` will have
- mode 644, and all of the directories will have mode 755."
+ desc <<-EOT
+ The desired permissions mode for the file, in symbolic or numeric
+ notation. Puppet uses traditional Unix permission schemes and translates
+ them to equivalent permissions for systems which represent permissions
+ differently, including Windows.
+
+ Numeric modes should use the standard four-digit octal notation of
+ `<setuid/setgid/sticky><owner><group><other>` (e.g. 0644). Each of the
+ "owner," "group," and "other" digits should be a sum of the
+ permissions for that class of users, where read = 4, write = 2, and
+ execute/search = 1. When setting numeric permissions for
+ directories, Puppet sets the search permission wherever the read
+ permission is set.
+
+ Symbolic modes should be represented as a string of comma-separated
+ permission clauses, in the form `<who><op><perm>`:
+
+ * "Who" should be u (user), g (group), o (other), and/or a (all)
+ * "Op" should be = (set exact permissions), + (add select permissions),
+ or - (remove select permissions)
+ * "Perm" should be one or more of:
+ * r (read)
+ * w (write)
+ * x (execute/search)
+ * t (sticky)
+ * s (setuid/setgid)
+ * X (execute/search if directory or if any one user can execute)
+ * u (user's current permissions)
+ * g (group's current permissions)
+ * o (other's current permissions)
+
+ Thus, mode `0664` could be represented symbolically as either `a=r,ug+w` or
+ `ug=rw,o=r`. See the manual page for GNU or BSD `chmod` for more details
+ on numeric and symbolic modes.
+
+ On Windows, permissions are translated as follows:
+
+ * Owner and group names are mapped to Windows SIDs
+ * The "other" class of users maps to the "Everyone" SID
+ * The read/write/execute permissions map to the `FILE_GENERIC_READ`,
+ `FILE_GENERIC_WRITE`, and `FILE_GENERIC_EXECUTE` access rights; a
+ file's owner always has the `FULL_CONTROL` right
+ * "Other" users can't have any permissions a file's group lacks,
+ and its group can't have any permissions its owner lacks; that is, 0644
+ is an acceptable mode, but 0464 is not.
+ EOT
validate do |value|
unless value.nil? or valid_symbolic_mode?(value)
diff --git a/lib/puppet/type/file/owner.rb b/lib/puppet/type/file/owner.rb
index 2eda3c4..3b61b40 100755
--- a/lib/puppet/type/file/owner.rb
+++ b/lib/puppet/type/file/owner.rb
@@ -2,8 +2,16 @@ module Puppet
Puppet::Type.type(:file).newproperty(:owner) do
include Puppet::Util::Warnings
- desc "To whom the file should belong. Argument can be user name or
- user ID."
+ desc <<-EOT
+ The user to whom the file should belong. Argument can be a user name or a
+ user ID.
+
+ On Windows, a group (such as "Administrators") can be set as a file's owner
+ and a user (such as "Administrator") can be set as a file's group; however,
+ a file's owner and group shouldn't be the same. (If the owner is also
+ the group, files with modes like `0640` will cause log churn, as they
+ will always appear out of sync.)
+ EOT
def insync?(current)
# We don't want to validate/munge users until we actually start to
diff --git a/lib/puppet/type/file/source.rb b/lib/puppet/type/file/source.rb
index 5d4fb9b..6912853 100755
--- a/lib/puppet/type/file/source.rb
+++ b/lib/puppet/type/file/source.rb
@@ -13,55 +13,42 @@ module Puppet
attr_accessor :source, :local
desc <<-EOT
- Copy a file over the current file. Uses `checksum` to
- determine when a file should be copied. Valid values are either
- fully qualified paths to files, or URIs. Currently supported URI
- types are *puppet* and *file*.
-
- This is one of the primary mechanisms for getting content into
- applications that Puppet does not directly support and is very
- useful for those configuration files that don't change much across
- sytems. For instance:
-
- class sendmail {
- file { "/etc/mail/sendmail.cf":
- source => "puppet://server/modules/module_name/sendmail.cf"
- }
- }
+ A source file, which will be copied into place on the local system.
+ Values can be URIs pointing to remote files, or fully qualified paths to
+ files available on the local system (including files on NFS shares or
+ Windows mapped drives). This attribute is mutually exclusive with
+ `content` and `target`.
+
+ The available URI schemes are *puppet* and *file*. *Puppet*
+ URIs will retrieve files from Puppet's built-in file server, and are
+ usually formatted as:
- You can also leave out the server name, in which case `puppet agent`
- will fill in the name of its configuration server and `puppet apply`
- will use the local filesystem. This makes it easy to use the same
- configuration in both local and centralized forms.
+ `puppet:///modules/name_of_module/filename`
- Currently, only the `puppet` scheme is supported for source
- URL's. Puppet will connect to the file server running on
- `server` to retrieve the contents of the file. If the
- `server` part is empty, the behavior of the command-line
- interpreter (`puppet apply`) and the client demon (`puppet agent`) differs
- slightly: `apply` will look such a file up on the module path
- on the local host, whereas `agent` will connect to the
- puppet server that it received the manifest from.
+ This will fetch a file from a module on the puppet master (or from a
+ local module when using puppet apply). Given a `modulepath` of
+ `/etc/puppetlabs/puppet/modules`, the example above would resolve to
+ `/etc/puppetlabs/puppet/modules/name_of_module/files/filename`.
- See the [fileserver configuration documentation](http://docs.puppetlabs.com/guides/file_serving.html)
- for information on how to configure and use file services within Puppet.
+ Unlike `content`, the `source` attribute can be used to recursively copy
+ directories if the `recurse` attribute is set to `true` or `remote`. If
+ a source directory contains symlinks, use the `links` attribute to
+ specify whether to recreate links or follow them.
- If you specify multiple file sources for a file, then the first
- source that exists will be used. This allows you to specify
- what amount to search paths for files:
+ Multiple `source` values can be specified as an array, and Puppet will
+ use the first source that exists. This can be used to serve different
+ files to different system types:
- file { "/path/to/my/file":
+ file { "/etc/nfs.conf":
source => [
- "/modules/nfs/files/file.$host",
- "/modules/nfs/files/file.$operatingsystem",
- "/modules/nfs/files/file"
+ "puppet:///modules/nfs/conf.$host",
+ "puppet:///modules/nfs/conf.$operatingsystem",
+ "puppet:///modules/nfs/conf"
]
}
- This will use the first found file as the source.
-
- You cannot currently copy links using this mechanism; set `links`
- to `follow` if any remote sources are links.
+ Alternately, when serving directories recursively, multiple sources can
+ be combined by setting the `sourceselect` attribute to `all`.
EOT
validate do |sources|
diff --git a/lib/puppet/type/file/target.rb b/lib/puppet/type/file/target.rb
index 017b4f4..e1dbdea 100644
--- a/lib/puppet/type/file/target.rb
+++ b/lib/puppet/type/file/target.rb
@@ -1,9 +1,10 @@
module Puppet
Puppet::Type.type(:file).newproperty(:target) do
desc "The target for creating a link. Currently, symlinks are the
- only type supported.
+ only type supported. This attribute is mutually exclusive with `source`
+ and `content`.
- You can make relative links:
+ Symlink targets can be relative, as well as absolute:
# (Useful on Solaris)
file { \"/etc/inetd.conf\":
@@ -11,10 +12,9 @@ module Puppet
target => \"inet/inetd.conf\",
}
- You can also make recursive symlinks, which will create a
- directory structure that maps to the target directory,
- with directories corresponding to each directory
- and links corresponding to each file."
+ Directories of symlinks can be served recursively by instead using the
+ `source` attribute, setting `ensure` to `directory`, and setting the
+ `links` attribute to `manage`."
newvalue(:notlink) do
# We do nothing if the value is absent
diff --git a/lib/puppet/type/group.rb b/lib/puppet/type/group.rb
index 8fd5761..93146b7 100755
--- a/lib/puppet/type/group.rb
+++ b/lib/puppet/type/group.rb
@@ -34,12 +34,13 @@ module Puppet
end
newproperty(:gid) do
- desc "The group ID. Must be specified numerically. If not
- specified, a number will be picked, which can result in ID
- differences across systems and thus is not recommended. The
- GID is picked according to local system standards.
+ desc "The group ID. Must be specified numerically. If no group ID is
+ specified when creating a new group, then one will be chosen
+ automatically according to local system standards. This will likely
+ result in the same group having different GIDs on different systems,
+ which is not recommended.
- On Windows, the property will return the group's security
+ On Windows, this property is read-only and will return the group's security
identifier (SID)."
def retrieve
@@ -91,13 +92,16 @@ def change_to_s(currentvalue, newvalue)
newparam(:name) do
desc "The group name. While naming limitations vary by operating system,
it is advisable to restrict names to the lowest common denominator,
- which is a maximum of 8 characters beginning with a letter."
+ which is a maximum of 8 characters beginning with a letter.
+
+ Note that Puppet considers group names to be case-sensitive, regardless
+ of the platform's own rules; be sure to always use the same case when
+ referring to a given group."
isnamevar
end
newparam(:allowdupe, :boolean => true) do
- desc "Whether to allow duplicate GIDs. This option does not work on
- FreeBSD (contract to the `pw` man page)."
+ desc "Whether to allow duplicate GIDs. Defaults to `false`."
newvalues(:true, :false)
diff --git a/lib/puppet/type/package.rb b/lib/puppet/type/package.rb
index 18ee854..bfd6e42 100644
--- a/lib/puppet/type/package.rb
+++ b/lib/puppet/type/package.rb
@@ -302,8 +302,25 @@ def should_to_s(newvalue = @should)
end
newparam(:install_options, :required_features => :install_options) do
- desc "A hash of options to be handled by the provider when
- installing a package."
+ desc <<-EOT
+ A hash of additional options to pass when installing a package. These
+ options are package-specific, and should be documented by the software
+ vendor. The most commonly implemented option is `INSTALLDIR`:
+
+ package { 'mysql':
+ ensure => installed,
+ provider => 'msi',
+ source => 'N:/packages/mysql-5.5.16-winx64.msi',
+ install_options => { 'INSTALLDIR' => 'C:\\mysql-5.5' },
+ }
+
+ Since these options are passed verbatim to `msiexec`, any file paths
+ specified in `install_options` should use a backslash as the separator
+ character rather than a forward slash. This is the **only** place in Puppet
+ where backslash separators should be used. Note that backslashes in
+ double-quoted strings _must_ be double-escaped and backslashes
+ in single-quoted strings _may_ be double-escaped.
+ EOT
end
autorequire(:file) do
diff --git a/lib/puppet/type/scheduled_task.rb b/lib/puppet/type/scheduled_task.rb
index d83adcb..4a0fe4e 100644
--- a/lib/puppet/type/scheduled_task.rb
+++ b/lib/puppet/type/scheduled_task.rb
@@ -3,98 +3,16 @@
Puppet::Type.newtype(:scheduled_task) do
include Puppet::Util
- @doc = "Installs and manages Windows Scheduled Tasks. All fields
- except the name, command, and start_time are optional; specifying
- no repetition parameters will result in a task that runs once on
- the start date.
-
- Examples:
-
- # Create a task that will fire on August 31st, 2011 at 8am in
- # the system's time-zone.
- scheduled_task { 'One-shot task':
- ensure => present,
- enabled => true,
- command => 'C:\path\to\command.exe',
- arguments => '/flags /to /pass',
- trigger => {
- schedule => once,
- start_date => '2011-08-31', # Defaults to 'today'
- start_time => '08:00', # Must be specified
- }
- }
-
- # Create a task that will fire every other day at 8am in the
- # system's time-zone, starting August 31st, 2011.
- scheduled_task { 'Daily task':
- ensure => present,
- enabled => true,
- command => 'C:\path\to\command.exe',
- arguments => '/flags /to /pass',
- trigger => {
- schedule => daily,
- every => 2 # Defaults to 1
- start_date => '2011-08-31', # Defaults to 'today'
- start_time => '08:00', # Must be specified
- }
- }
-
- # Create a task that will fire at 8am Monday every third week,
- # starting after August 31st, 2011.
- scheduled_task { 'Weekly task':
- ensure => present,
- enabled => true,
- command => 'C:\path\to\command.exe',
- arguments => '/flags /to /pass',
- trigger => {
- schedule => weekly,
- every => 3, # Defaults to 1
- start_date => '2011-08-31' # Defaults to 'today'
- start_time => '08:00', # Must be specified
- day_of_week => [mon], # Defaults to all
- }
- }
-
- # Create a task that will fire at 8am on the 1st, 15th, and last
- # day of the month in January, March, May, July, September, and
- # November starting August 31st, 2011.
- scheduled_task { 'Monthly date task':
- ensure => present,
- enabled => true,
- command => 'C:\path\to\command.exe',
- arguments => '/flags /to /pass',
- trigger => {
- schedule => monthly,
- start_date => '2011-08-31', # Defaults to 'today'
- start_time => '08:00', # Must be specified
- months => [1,3,5,7,9,11], # Defaults to all
- on => [1, 15, last], # Must be specified
- }
- }
-
- # Create a task that will fire at 8am on the first Monday of the
- # month for January, March, and May, after August 31st, 2011.
- scheduled_task { 'Monthly day of week task':
- enabled => true,
- ensure => present,
- command => 'C:\path\to\command.exe',
- arguments => '/flags /to /pass',
- trigger => {
- schedule => monthly,
- start_date => '2011-08-31', # Defaults to 'today'
- start_time => '08:00', # Must be specified
- months => [1,3,5], # Defaults to all
- which_occurrence => first, # Must be specified
- day_of_week => [mon], # Must be specified
- }
- }"
+ @doc = "Installs and manages Windows Scheduled Tasks. All attributes
+ except `name`, `command`, and `trigger` are optional; see the description
+ of the `trigger` attribute for details on setting schedules."
ensurable
newproperty(:enabled) do
- desc "Whether the triggers for this task are enabled. This only
- supports enabling or disabling all of the triggers for a task,
- not enabling or disabling them on an individual basis."
+ desc "Whether the triggers for this task should be enabled. This attribute
+ affects every trigger for the task; triggers cannot be enabled or
+ disabled individually."
newvalue(:true, :event => :task_enabled)
newvalue(:false, :event => :task_disabled)
@@ -110,8 +28,7 @@
end
newproperty(:command) do
- desc "The full path to the application to be run, without any
- arguments."
+ desc "The full path to the application to run, without any arguments."
validate do |value|
raise Puppet::Error.new('Must be specified using an absolute path.') unless absolute_path?(value)
@@ -119,8 +36,7 @@
end
newproperty(:working_dir) do
- desc "The full path of the directory in which to start the
- command"
+ desc "The full path of the directory in which to start the command."
validate do |value|
raise Puppet::Error.new('Must be specified using an absolute path.') unless absolute_path?(value)
@@ -128,7 +44,8 @@
end
newproperty(:arguments, :array_matching => :all) do
- desc "The optional arguments to pass to the command."
+ desc "Any arguments or flags that should be passed to the command. Multiple arguments
+ can be specified as an array or as a space-separated string."
end
newproperty(:user) do
@@ -149,7 +66,7 @@ def insync?(current)
end
newparam(:password) do
- desc "The password for the user specified in the 'user' property.
+ desc "The password for the user specified in the 'user' attribute.
This is only used if specifying a user other than 'SYSTEM'.
Since there is no way to retrieve the password used to set the
account information for a task, this parameter will not be used
@@ -157,43 +74,72 @@ def insync?(current)
end
newproperty(:trigger, :array_matching => :all) do
- desc "This is a hash defining the properties of the trigger used
- to fire the scheduled task. The one key that is always required
- is 'schedule', which can be one of 'daily', 'weekly', or
- 'monthly'. The other valid & required keys depend on the value
- of schedule.
-
- When schedule is 'daily', you can specify a value for 'every'
- which specifies that the task will trigger every N days. If
- 'every' is not specified, it defaults to 1 (running every day).
-
- When schedule is 'weekly', you can specify values for 'every',
- and 'day_of_week'. 'every' has similar behavior as when
- specified for 'daily', though it repeats every N weeks, instead
- of every N days. 'day_of_week' is used to specify on which days
- of the week the task should be run. This can be specified as an
- array where the possible values are 'mon', 'tues', 'wed',
- 'thurs', 'fri', 'sat', and 'sun', or as the string 'all'. The
- default is 'all'.
-
- When schedule is 'monthly', the syntax depends on whether you
- wish to specify the trigger using absolute, or relative dates.
- In either case, you can specify which months this trigger
- applies to using 'months', and specifying an array of integer
- months. 'months' defaults to all months.
-
- When specifying a monthly schedule with absolute dates, 'on'
- must be provided as an array of days (1-31, or the special value
- 'last' which will always be the last day of the month).
-
- When specifying a monthly schedule with relative dates,
- 'which_occurrence', and 'day_of_week' must be specified. The
- possible values for 'which_occurrence' are 'first', 'second',
- 'third', 'fourth', 'fifth', and 'last'. 'day_of_week' is an
- array where the possible values are 'mon', 'tues', 'wed',
- 'thurs', 'fri', 'sat', and 'sun'. These combine to be able to
- specify things like: The task should run on the first Monday of
- the specified month(s)."
+ desc <<-EOT
+ One or more triggers defining when the task should run. A single trigger is
+ represented as a hash, and multiple triggers can be specified with an array of
+ hashes.
+
+ A trigger can contain the following keys:
+
+ * For all triggers:
+ * `schedule` **(Required)** --- The schedule type. Valid values are
+ `daily`, `weekly`, `monthly`, or `once`.
+ * `start_time` **(Required)** --- The time of day when the trigger should
+ first become active. Several time formats will work, but we
+ suggest 24-hour time formatted as HH:MM.
+ * `start_date` --- The date when the trigger should first become active.
+ Defaults to "today." Several date formats will work, including
+ special dates like "today," but we suggest formatting dates as
+ YYYY-MM-DD.
+ * For daily triggers:
+ * `every` --- How often the task should run, as a number of days. Defaults
+ to 1. ("2" means every other day, "3" means every three days, etc.)
+ * For weekly triggers:
+ * `every` --- How often the task should run, as a number of weeks. Defaults
+ to 1. ("2" means every other week, "3" means every three weeks, etc.)
+ * `day_of_week` --- Which days of the week the task should run, as an array.
+ Defaults to all days. Each day must be one of `mon`, `tues`,
+ `wed`, `thurs`, `fri`, `sat`, `sun`, or `all`.
+ * For monthly-by-date triggers:
+ * `months` --- Which months the task should run, as an array. Defaults to
+ all months. Each month must be an integer between 1 and 12.
+ * `on` **(Required)** --- Which days of the month the task should run,
+ as an array. Each day must beeither an integer between 1 and 31,
+ or the special value `last,` which is always the last day of the month.
+ * For monthly-by-weekday triggers:
+ * `months` --- Which months the task should run, as an array. Defaults to
+ all months. Each month must be an integer between 1 and 12.
+ * `day_of_week` **(Required)** --- Which day of the week the task should
+ run, as an array with only one element. Each day must be one of `mon`,
+ `tues`, `wed`, `thurs`, `fri`, `sat`, `sun`, or `all`.
+ * `which_occurrence` **(Required)** --- The occurrence of the chosen weekday
+ when the task should run. Must be one of `first`, `second`, `third`,
+ `fourth`, `fifth`, or `last`.
+
+ Examples:
+
+ # Run at 8am on the 1st, 15th, and last day of the month in January, March,
+ # May, July, September, and November, starting after August 31st, 2011.
+ trigger => {
+ schedule => monthly,
+ start_date => '2011-08-31', # Defaults to 'today'
+ start_time => '08:00', # Must be specified
+ months => [1,3,5,7,9,11], # Defaults to all
+ on => [1, 15, last], # Must be specified
+ }
+
+ # Run at 8am on the first Monday of the month for January, March, and May,
+ # starting after August 31st, 2011.
+ trigger => {
+ schedule => monthly,
+ start_date => '2011-08-31', # Defaults to 'today'
+ start_time => '08:00', # Must be specified
+ months => [1,3,5], # Defaults to all
+ which_occurrence => first, # Must be specified
+ day_of_week => [mon], # Must be specified
+ }
+
+ EOT
validate do |value|
provider.validate_trigger(value)
diff --git a/lib/puppet/type/service.rb b/lib/puppet/type/service.rb
index 98099ee..63299af 100644
--- a/lib/puppet/type/service.rb
+++ b/lib/puppet/type/service.rb
@@ -124,8 +124,14 @@ def sync
defaultto :true
end
newparam(:name) do
- desc "The name of the service to run. This name is used to find
- the service in whatever service subsystem it is in."
+ desc <<-EOT
+ The name of the service to run.
+
+ This name is used to find the service; on platforms where services
+ have short system names and long display names, this should be the
+ short name. (To take an example from Windows, you would use "wuauserv"
+ rather than "Automatic Updates.")
+ EOT
isnamevar
end
diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb
index 71c2080..caadf91 100755
--- a/lib/puppet/type/user.rb
+++ b/lib/puppet/type/user.rb
@@ -113,8 +113,10 @@ def retrieve
end
newproperty(:gid) do
- desc "The user's primary group. Can be specified numerically or
- by name."
+ desc "The user's primary group. Can be specified numerically or by name.
+
+ Note that users on Windows systems do not have a primary group; manage groups
+ with the `groups` attribute instead."
munge do |value|
if value.is_a?(String) and value =~ /^[-0-9]+$/
@@ -156,14 +158,28 @@ def sync
newproperty(:shell) do
desc "The user's login shell. The shell must exist and be
- executable."
+ executable.
+
+ This attribute cannot be managed on Windows systems."
end
newproperty(:password, :required_features => :manages_passwords) do
desc %q{The user's password, in whatever encrypted format the local
- machine requires. Be sure to enclose any value that includes a dollar
- sign ($) in single quotes (') to avoid accidental variable
- interpolation.}
+ system requires.
+
+ * Most modern Unix-like systems use salted SHA1 password hashes. You can use
+ Puppet's built-in `sha1` function to generate a hash from a password.
+ * Mac OS X 10.5 and 10.6 also use salted SHA1 hashes.
+ * Mac OS X 10.7 (Lion) uses salted SHA512 hashes. The Puppet Labs [stdlib][]
+ module contains a `str2saltedsha512` function which can generate password
+ hashes for Lion.
+ * Windows passwords can only be managed in cleartext, as there is no Windows API
+ for setting the password hash.
+
+ [stdlib]: https://github.com/puppetlabs/puppetlabs-stdlib/
+
+ Be sure to enclose any value that includes a dollar sign ($) in single
+ quotes (') to avoid accidental variable interpolation.}
validate do |value|
raise ArgumentError, "Passwords cannot include ':'" if value.is_a?(String) and value.include?(":")
@@ -240,7 +256,11 @@ def should_to_s( newvalue )
newparam(:name) do
desc "The user name. While naming limitations vary by operating system,
it is advisable to restrict names to the lowest common denominator,
- which is a maximum of 8 characters beginning with a letter."
+ which is a maximum of 8 characters beginning with a letter.
+
+ Note that Puppet considers user names to be case-sensitive, regardless
+ of the platform's own rules; be sure to always use the same case when
+ referring to a given user."
isnamevar
end
diff --git a/lib/puppet/util/selinux.rb b/lib/puppet/util/selinux.rb
index 255388d..17c631b 100644
--- a/lib/puppet/util/selinux.rb
+++ b/lib/puppet/util/selinux.rb
@@ -163,7 +163,7 @@ def read_mounts
# Read all entries in /proc/mounts. The second column is the
# mountpoint and the third column is the filesystem type.
# We skip rootfs because it is always mounted at /
- mounts.collect do |line|
+ mounts.each_line do |line|
params = line.split(' ')
next if params[2] == 'rootfs'
mntpoint[params[1]] = params[2]
diff --git a/spec/integration/module_tool_spec.rb b/spec/integration/module_tool_spec.rb
index 1067bfa..bd3b126 100644
--- a/spec/integration/module_tool_spec.rb
+++ b/spec/integration/module_tool_spec.rb
@@ -8,7 +8,7 @@ def stub_repository_read(code, body)
kind = Net::HTTPResponse.send(:response_class, code.to_s)
response = kind.new('1.0', code.to_s, 'HTTP MESSAGE')
response.stubs(:read_body).returns(body)
- Puppet::Module::Tool::Repository.any_instance.stubs(:read_response).returns(response)
+ Puppet::Forge::Repository.any_instance.stubs(:read_response).returns(response)
end
def stub_installer_read(body)
@@ -16,7 +16,7 @@ def stub_installer_read(body)
end
def stub_cache_read(body)
- Puppet::Module::Tool::Cache.any_instance.stubs(:read_retrieve).returns(body)
+ Puppet::Forge::Cache.any_instance.stubs(:read_retrieve).returns(body)
end
# Return path to temparory directory for testing.
@@ -98,11 +98,11 @@ def run(&block)
before :each do
Puppet.settings.stubs(:parse)
- Puppet::Module::Tool::Cache.clean
+ Puppet::Forge::Cache.clean
end
after :each do
- Puppet::Module::Tool::Cache.clean
+ Puppet::Forge::Cache.clean
end
describe "generate" do
@@ -376,9 +376,8 @@ def run(&block)
stub_cache_read File.read("#{@full_module_name}/pkg/#{@release_name}.tar.gz")
FileUtils.rm_rf(@full_module_name)
- stub_installer_read <<-HERE
- {"file": "/foo/bar/#{@release_name}.tar.gz", "version": "#{@version}"}
- HERE
+ release = {"file" => "/foo/bar/#{@release_name}.tar.gz", "version" => "#{@version}"}
+ Puppet::Forge::Forge.any_instance.stubs(:get_release).returns(release)
Puppet::Module::Tool::Applications::Installer.run(@full_module_name, @options)
@@ -426,9 +425,8 @@ def run(&block)
stub_cache_read File.read("#{@full_module_name}/pkg/#{@release_name}.tar.gz")
FileUtils.rm_rf(@full_module_name)
- stub_installer_read <<-HERE
- {"file": "/foo/bar/#{@release_name}.tar.gz", "version": "#{@version}"}
- HERE
+ release = {"file" => "/foo/bar/#{@release_name}.tar.gz", "version" => "#{@version}"}
+ Puppet::Forge::Forge.any_instance.stubs(:get_release).returns(release)
Puppet::Module::Tool::Applications::Installer.run(@full_module_name, @options).should be_kind_of(Pathname)
end
@@ -441,9 +439,9 @@ def run(&block)
it "should clean cache" do
run do
build_and_install_module
- Puppet::Module::Tool::Cache.base_path.directory?.should == true
+ Puppet::Forge::Cache.base_path.directory?.should == true
Puppet::Module::Tool::Applications::Cleaner.run
- Puppet::Module::Tool::Cache.base_path.directory?.should == false
+ Puppet::Forge::Cache.base_path.directory?.should == false
end
end
diff --git a/spec/unit/application/apply_spec.rb b/spec/unit/application/apply_spec.rb
index 07a3922..1a15fc0 100755
--- a/spec/unit/application/apply_spec.rb
+++ b/spec/unit/application/apply_spec.rb
@@ -210,52 +210,12 @@
expect { @apply.main }.to exit_with 0
end
- it "should set the facts name based on the node_name_fact" do
- @facts = Puppet::Node::Facts.new(Puppet[:node_name_value], 'my_name_fact' => 'other_node_name')
- Puppet::Node::Facts.indirection.save(@facts)
-
- node = Puppet::Node.new('other_node_name')
- Puppet::Node.indirection.save(node)
-
- Puppet[:node_name_fact] = 'my_name_fact'
-
- expect { @apply.main }.to exit_with 0
-
- @facts.name.should == 'other_node_name'
- end
-
- it "should set the node_name_value based on the node_name_fact" do
- facts = Puppet::Node::Facts.new(Puppet[:node_name_value], 'my_name_fact' => 'other_node_name')
- Puppet::Node::Facts.indirection.save(facts)
- node = Puppet::Node.new('other_node_name')
- Puppet::Node.indirection.save(node)
- Puppet[:node_name_fact] = 'my_name_fact'
-
- expect { @apply.main }.to exit_with 0
-
- Puppet[:node_name_value].should == 'other_node_name'
- end
-
- it "should raise an error if we can't find the facts" do
- Puppet::Node::Facts.indirection.expects(:find).returns(nil)
-
- lambda { @apply.main }.should raise_error
- end
-
it "should raise an error if we can't find the node" do
Puppet::Node.indirection.expects(:find).returns(nil)
lambda { @apply.main }.should raise_error
end
- it "should merge in our node the loaded facts" do
- @facts.values = {'key' => 'value'}
-
- expect { @apply.main }.to exit_with 0
-
- @node.parameters['key'].should == 'value'
- end
-
it "should load custom classes if loadclasses" do
@apply.options[:loadclasses] = true
classfile = tmpfile('classfile')
@@ -308,6 +268,40 @@
expect { @apply.main }.to exit_with 0
end
+ describe "when using node_name_fact" do
+ before :each do
+ @facts = Puppet::Node::Facts.new(Puppet[:node_name_value], 'my_name_fact' => 'other_node_name')
+ Puppet::Node::Facts.indirection.save(@facts)
+ @node = Puppet::Node.new('other_node_name')
+ Puppet::Node.indirection.save(@node)
+ Puppet[:node_name_fact] = 'my_name_fact'
+ end
+
+ it "should set the facts name based on the node_name_fact" do
+ expect { @apply.main }.to exit_with 0
+ @facts.name.should == 'other_node_name'
+ end
+
+ it "should set the node_name_value based on the node_name_fact" do
+ expect { @apply.main }.to exit_with 0
+ Puppet[:node_name_value].should == 'other_node_name'
+ end
+
+ it "should merge in our node the loaded facts" do
+ @facts.values.merge!('key' => 'value')
+
+ expect { @apply.main }.to exit_with 0
+
+ @node.parameters['key'].should == 'value'
+ end
+
+ it "should raise an error if we can't find the facts" do
+ Puppet::Node::Facts.indirection.expects(:find).returns(nil)
+
+ lambda { @apply.main }.should raise_error
+ end
+ end
+
describe "with detailed_exitcodes" do
before :each do
@apply.options[:detailed_exitcodes] = true
diff --git a/spec/unit/application/device_spec.rb b/spec/unit/application/device_spec.rb
index 43048fb..fa200b1 100755
--- a/spec/unit/application/device_spec.rb
+++ b/spec/unit/application/device_spec.rb
@@ -320,22 +320,67 @@
[:vardir, :confdir].each do |setting|
it "should cleanup the #{setting} setting after the run" do
- configurer = states('configurer').starts_as('notrun')
- Puppet.settings.expects(:set_value).with(setting, make_absolute("/dummy/devices/device1"), :cli).when(configurer.is('notrun'))
- @configurer.expects(:run).twice.then(configurer.is('run'))
- Puppet.settings.expects(:set_value).with(setting, make_absolute("/dummy"), :cli).when(configurer.is('run'))
+ all_devices = Set.new(@device_hash.keys.map do |device_name| make_absolute("/dummy/devices/#{device_name}") end)
+ found_devices = Set.new()
+
+ # a block to use in a few places later to validate the arguments passed to "set_value"
+ p = Proc.new do |my_setting, my_value, my_type|
+ success =
+ (my_setting == setting) &&
+ (my_type == :cli) &&
+ (all_devices.include?(my_value))
+ found_devices.add(my_value) if success
+ success
+ end
+
+ seq = sequence("clean up dirs")
+
+ all_devices.size.times do
+ ## one occurrence of set / run / set("/dummy") for each device
+ Puppet.settings.expects(:set_value).with(&p).in_sequence(seq)
+ @configurer.expects(:run).in_sequence(seq)
+ Puppet.settings.expects(:set_value).with(setting, make_absolute("/dummy"), :cli).in_sequence(seq)
+ end
+
@device.main
+
+ # make sure that we were called with each of the defined devices
+ all_devices.should == found_devices
+
end
end
it "should cleanup the certname setting after the run" do
- configurer = states('configurer').starts_as('notrun')
- Puppet.settings.expects(:set_value).with(:certname, "device1", :cli).when(configurer.is('notrun'))
- @configurer.expects(:run).twice.then(configurer.is('run'))
- Puppet.settings.expects(:set_value).with(:certname, "certname", :cli).when(configurer.is('run'))
+ all_devices = Set.new(@device_hash.keys)
+ found_devices = Set.new()
+
+ # a block to use in a few places later to validate the arguments passed to "set_value"
+ p = Proc.new do |my_setting, my_value, my_type|
+ success =
+ (my_setting == :certname) &&
+ (my_type == :cli) &&
+ (all_devices.include?(my_value))
+ found_devices.add(my_value) if success
+ success
+ #true
+ end
+
+ seq = sequence("clean up certname")
+
+ all_devices.size.times do
+ ## one occurrence of set / run / set("certname") for each device
+ Puppet.settings.expects(:set_value).with(&p).in_sequence(seq)
+ @configurer.expects(:run).in_sequence(seq)
+ Puppet.settings.expects(:set_value).with(:certname, "certname", :cli).in_sequence(seq)
+ end
+
@device.main
+
+ # make sure that we were called with each of the defined devices
+ all_devices.should == found_devices
+
end
it "should expire all cached attributes" do
diff --git a/spec/unit/forge/repository_spec.rb b/spec/unit/forge/repository_spec.rb
new file mode 100644
index 0000000..6d8ce38
--- /dev/null
+++ b/spec/unit/forge/repository_spec.rb
@@ -0,0 +1,86 @@
+require 'spec_helper'
+require 'net/http'
+require 'puppet/forge/repository'
+require 'puppet/forge/cache'
+
+describe Puppet::Forge::Repository do
+ describe 'instances' do
+
+ let(:repository) { Puppet::Forge::Repository.new('http://fake.com') }
+
+ describe '#make_http_request' do
+ before do
+ # Do a mock of the Proxy call so we can do proper expects for
+ # Net::HTTP
+ Net::HTTP.expects(:Proxy).returns(Net::HTTP)
+ Net::HTTP.expects(:start)
+ end
+ context "when not given an :authenticate option" do
+ it "should authenticate" do
+ repository.expects(:authenticate).never
+ repository.make_http_request(nil)
+ end
+ end
+ context "when given an :authenticate option" do
+ it "should authenticate" do
+ repository.expects(:authenticate)
+ repository.make_http_request(nil, :authenticate => true)
+ end
+ end
+ end
+
+ describe '#authenticate' do
+ it "should set basic auth on the request" do
+ authenticated_request = stub
+ authenticated_request.expects(:basic_auth)
+ repository.expects(:prompt).twice
+ repository.authenticate(authenticated_request)
+ end
+ end
+
+ describe '#retrieve' do
+ before do
+ @uri = URI.parse('http://some.url.com')
+ end
+
+ it "should access the cache" do
+ repository.cache.expects(:retrieve).with(@uri)
+ repository.retrieve(@uri)
+ end
+ end
+
+ describe 'http_proxy support' do
+ before :each do
+ ENV["http_proxy"] = nil
+ end
+
+ after :each do
+ ENV["http_proxy"] = nil
+ end
+
+ it "should support environment variable for port and host" do
+ ENV["http_proxy"] = "http://test.com:8011"
+ repository.http_proxy_host.should == "test.com"
+ repository.http_proxy_port.should == 8011
+ end
+
+ it "should support puppet configuration for port and host" do
+ ENV["http_proxy"] = nil
+ Puppet.settings.stubs(:[]).with(:http_proxy_host).returns('test.com')
+ Puppet.settings.stubs(:[]).with(:http_proxy_port).returns(7456)
+
+ repository.http_proxy_port.should == 7456
+ repository.http_proxy_host.should == "test.com"
+ end
+
+ it "should use environment variable before puppet settings" do
+ ENV["http_proxy"] = "http://test1.com:8011"
+ Puppet.settings.stubs(:[]).with(:http_proxy_host).returns('test2.com')
+ Puppet.settings.stubs(:[]).with(:http_proxy_port).returns(7456)
+
+ repository.http_proxy_host.should == "test1.com"
+ repository.http_proxy_port.should == 8011
+ end
+ end
+ end
+end
diff --git a/spec/unit/forge_spec.rb b/spec/unit/forge_spec.rb
new file mode 100644
index 0000000..905f1bd
--- /dev/null
+++ b/spec/unit/forge_spec.rb
@@ -0,0 +1,114 @@
+require 'spec_helper'
+require 'puppet/forge'
+require 'net/http'
+
+describe Puppet::Forge::Forge do
+ before do
+ Puppet::Forge::Repository.any_instance.stubs(:make_http_request).returns(response)
+ Puppet::Forge::Repository.any_instance.stubs(:retrieve).returns("/tmp/foo")
+ end
+
+ let(:forge) { forge = Puppet::Forge::Forge.new('http://forge.puppetlabs.com') }
+
+ describe "the behavior of the search method" do
+ context "when there are matches for the search term" do
+ before do
+ Puppet::Forge::Repository.any_instance.stubs(:make_http_request).returns(response)
+ end
+
+ let(:response) { stub(:body => response_body, :code => '200') }
+ let(:response_body) do
+ <<-EOF
+ [
+ {
+ "author": "puppetlabs",
+ "name": "bacula",
+ "tag_list": ["backup", "bacula"],
+ "releases": [{"version": "0.0.1"}, {"version": "0.0.2"}],
+ "full_name": "puppetlabs/bacula",
+ "version": "0.0.2",
+ "project_url": "http://github.com/puppetlabs/puppetlabs-bacula",
+ "desc": "bacula"
+ }
+ ]
+ EOF
+ end
+
+ it "should return a list of matches from the forge" do
+ forge.search('bacula').should == PSON.load(response_body)
+ end
+ end
+
+ context "when the connection to the forge fails" do
+ let(:response) { stub(:body => '[]', :code => '404') }
+
+ it "should raise an error" do
+ lambda { forge.search('bacula') }.should raise_error RuntimeError
+ end
+ end
+ end
+
+ describe "the behavior of the get_release_package method" do
+
+ let(:response) do
+ response = mock()
+ response.stubs(:body).returns('{"file": "/system/releases/p/puppetlabs/puppetlabs-apache-0.0.3.tar.gz", "version": "0.0.3"}')
+ response
+ end
+
+ context "when source is not filesystem or repository" do
+ it "should raise an error" do
+ params = { :source => 'foo' }
+ lambda { forge.get_release_package(params) }.should
+ raise_error(ArgumentError, "Could not determine installation source")
+ end
+ end
+
+ context "when the source is a repository" do
+ let(:params) do
+ {
+ :source => :repository,
+ :author => 'fakeauthor',
+ :modname => 'fakemodule',
+ :version => '0.0.1'
+ }
+ end
+
+ it "should require author" do
+ params.delete(:author)
+ lambda { forge.get_release_package(params) }.should
+ raise_error(ArgumentError, ":author and :modename required")
+ end
+
+ it "should require modname" do
+ params.delete(:modname)
+ lambda { forge.get_release_package(params) }.should
+ raise_error(ArgumentError, ":author and :modename required")
+ end
+
+ it "should download the release package" do
+ forge.get_release_package(params).should == "/tmp/foo"
+ end
+ end
+
+ context "when the source is a filesystem" do
+ it "should require filename" do
+ params = { :source => :filesystem }
+ lambda { forge.get_release_package(params) }.should
+ raise_error(ArgumentError, ":filename required")
+ end
+ end
+ end
+
+ describe "the behavior of the get_releases method" do
+ let(:response) do
+ response = mock()
+ response.stubs(:body).returns('{"releases": [{"version": "0.0.1"}, {"version": "0.0.2"}, {"version": "0.0.3"}]}')
+ response
+ end
+
+ it "should return a list of module releases" do
+ forge.get_releases('fakeauthor', 'fakemodule').should == ["0.0.1", "0.0.2", "0.0.3"]
+ end
+ end
+end
diff --git a/spec/unit/module_tool/repository_spec.rb b/spec/unit/module_tool/repository_spec.rb
deleted file mode 100644
index 69be166..0000000
--- a/spec/unit/module_tool/repository_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-require 'spec_helper'
-require 'net/http'
-require 'puppet/module_tool'
-
-describe Puppet::Module::Tool::Repository do
- describe 'instances' do
- before do
- @repository = described_class.new('http://fake.com')
- end
-
- describe '#make_http_request' do
- before do
- # Do a mock of the Proxy call so we can do proper expects for
- # Net::HTTP
- Net::HTTP.expects(:Proxy).returns(Net::HTTP)
- Net::HTTP.expects(:start)
- end
- context "when not given an :authenticate option" do
- it "should authenticate" do
- @repository.expects(:authenticate).never
- @repository.make_http_request(nil)
- end
- end
- context "when given an :authenticate option" do
- it "should authenticate" do
- @repository.expects(:authenticate)
- @repository.make_http_request(nil, :authenticate => true)
- end
- end
- end
-
- describe '#authenticate' do
- it "should set basic auth on the request" do
- authenticated_request = stub
- authenticated_request.expects(:basic_auth)
- @repository.expects(:prompt).twice
- @repository.authenticate(authenticated_request)
- end
- end
-
- describe '#retrieve' do
- before do
- @uri = URI.parse('http://some.url.com')
- end
-
- it "should access the cache" do
- @repository.cache.expects(:retrieve).with(@uri)
- @repository.retrieve(@uri)
- end
- end
- end
-end
diff --git a/spec/unit/module_tool_spec.rb b/spec/unit/module_tool_spec.rb
index 15ca6c7..86d421e 100644
--- a/spec/unit/module_tool_spec.rb
+++ b/spec/unit/module_tool_spec.rb
@@ -2,37 +2,4 @@
require 'puppet/module_tool'
describe Puppet::Module::Tool do
- describe 'http_proxy support' do
- before :each do
- ENV["http_proxy"] = nil
- end
-
- after :each do
- ENV["http_proxy"] = nil
- end
-
- it "should support environment variable for port and host" do
- ENV["http_proxy"] = "http://test.com:8011"
- described_class.http_proxy_host.should == "test.com"
- described_class.http_proxy_port.should == 8011
- end
-
- it "should support puppet configuration for port and host" do
- ENV["http_proxy"] = nil
- Puppet.settings.stubs(:[]).with(:http_proxy_host).returns('test.com')
- Puppet.settings.stubs(:[]).with(:http_proxy_port).returns(7456)
-
- described_class.http_proxy_port.should == 7456
- described_class.http_proxy_host.should == "test.com"
- end
-
- it "should use environment variable before puppet settings" do
- ENV["http_proxy"] = "http://test1.com:8011"
- Puppet.settings.stubs(:[]).with(:http_proxy_host).returns('test2.com')
- Puppet.settings.stubs(:[]).with(:http_proxy_port).returns(7456)
-
- described_class.http_proxy_host.should == "test1.com"
- described_class.http_proxy_port.should == 8011
- end
- end
end
diff --git a/spec/unit/util/selinux_spec.rb b/spec/unit/util/selinux_spec.rb
index cc70b53..0eaf43c 100755
--- a/spec/unit/util/selinux_spec.rb
+++ b/spec/unit/util/selinux_spec.rb
@@ -33,7 +33,7 @@ def self.is_selinux_enabled
end
end
- describe "filesystem detection", :'fails_on_ruby_1.9.2' => true do
+ describe "filesystem detection" do
before :each do
fh = stub 'fh', :close => nil
File.stubs(:open).with("/proc/mounts").returns fh
@@ -192,7 +192,7 @@ def self.is_selinux_enabled
end
end
- describe "set_selinux_context", :'fails_on_ruby_1.9.2' => true do
+ describe "set_selinux_context" do
before :each do
fh = stub 'fh', :close => nil
File.stubs(:open).with("/proc/mounts").returns fh
Please review pull request #489: Feature/2.7.x/5454 pluginsync features autosign opened by (cprice-puppet)
Description:
We are removing "autosign" from the list of default arguments for
the with_master_running_on method in the acceptance test framework.
Thus, this test now needs to specify that argument explicitly.
Diff follows:
diff --git a/acceptance/tests/pluginsync/feature/pluginsync_should_sync_features.rb b/acceptance/tests/pluginsync/feature/pluginsync_should_sync_features.rb
index 869c1cc..e480393 100644
--- a/acceptance/tests/pluginsync/feature/pluginsync_should_sync_features.rb
+++ b/acceptance/tests/pluginsync/feature/pluginsync_should_sync_features.rb
@@ -214,7 +214,8 @@ def insync?(is)
with_master_running_on(master,
"--manifest=\"#{get_test_file_path(master, master_manifest_file)}\" " +
- "--modulepath=\"#{get_test_file_path(master, master_module_dir)}\" --pluginsync") do
+ "--modulepath=\"#{get_test_file_path(master, master_module_dir)}\" " +
+ "--autosign true --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
On Fri Feb 10 22:52:58 UTC 2012 pull request #488 was closed.
Feature/2.7.x/5454 pluginsync features autosign requested by (cprice-puppet)
On Fri Feb 10 23:46:01 UTC 2012 pull request #489 was closed.
Feature/2.7.x/5454 pluginsync features autosign requested by (cprice-puppet)
The pull request was merged by: joshcooper