From 3e9ac59b293769ac9243ec162467faa13ceb2b2d Mon Sep 17 00:00:00 2001 From: luke Date: Mon, 13 Aug 2007 19:54:51 +0000 Subject: [PATCH 1/6] Updating more milestone names git-svn-id: https://reductivelabs.com/svn/puppet/trunk@2771 980ebf18-57e1-0310-9a29-db15c13687c0 --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index f51e1f3c6..7364ccb79 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -87,7 +87,7 @@ Class names and node names now conflict (#620). -0.23.0 +0.23.0 (fozzie) Modified the fileserver to cache file information, so that each file isn't being read on every connection. Also, added londo's patch from #678 to avoid reading entire files From b59d396b504f40a471459c527b16a1962e32a878 Mon Sep 17 00:00:00 2001 From: luke Date: Mon, 13 Aug 2007 19:54:52 +0000 Subject: [PATCH 2/6] Revert "Updating more milestone names" This reverts commit 61a747fc2d9bdfbf1b74c4ac3fcaf89114b020e0. git-svn-id: https://reductivelabs.com/svn/puppet/trunk@2772 980ebf18-57e1-0310-9a29-db15c13687c0 --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 7364ccb79..f51e1f3c6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -87,7 +87,7 @@ Class names and node names now conflict (#620). -0.23.0 (fozzie) +0.23.0 Modified the fileserver to cache file information, so that each file isn't being read on every connection. Also, added londo's patch from #678 to avoid reading entire files From 40491ebe7ca9692b57fb533412ece8fb694b7d4c Mon Sep 17 00:00:00 2001 From: luke Date: Mon, 13 Aug 2007 20:12:07 +0000 Subject: [PATCH 3/6] Merge /opt/rl/git/puppet git-svn-id: https://reductivelabs.com/svn/puppet/trunk@2773 980ebf18-57e1-0310-9a29-db15c13687c0 --- lib/puppet/parser/interpreter.rb | 9 +++++++-- test/language/interpreter.rb | 18 +++++++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/puppet/parser/interpreter.rb b/lib/puppet/parser/interpreter.rb index 9da1928b3..3ba9c0c7a 100644 --- a/lib/puppet/parser/interpreter.rb +++ b/lib/puppet/parser/interpreter.rb @@ -480,9 +480,14 @@ class Puppet::Parser::Interpreter # Look for external node definitions. def nodesearch_external(name) return nil unless Puppet[:external_nodes] != "none" - + + # This is a very cheap way to do this, since it will break on + # commands that have spaces in the arguments. But it's good + # enough for most cases. + external_node_command = Puppet[:external_nodes].split + external_node_command << name begin - output = Puppet::Util.execute([Puppet[:external_nodes], name]) + output = Puppet::Util.execute(external_node_command) rescue Puppet::ExecutionFailure => detail if $?.exitstatus == 1 return nil diff --git a/test/language/interpreter.rb b/test/language/interpreter.rb index 6352a147e..75800cc41 100755 --- a/test/language/interpreter.rb +++ b/test/language/interpreter.rb @@ -440,15 +440,15 @@ class TestInterpreter < PuppetTest::TestCase File.open(mapper, "w") { |f| f.puts "#!#{ruby} require 'yaml' - name = ARGV[0].chomp + name = ARGV.last.chomp result = {} if name =~ /a/ - result[:parameters] = {'one' => ARGV[0] + '1', 'two' => ARGV[0] + '2'} + result[:parameters] = {'one' => ARGV.last + '1', 'two' => ARGV.last + '2'} end if name =~ /p/ - result['classes'] = [1,2,3].collect { |n| ARGV[0] + n.to_s } + result['classes'] = [1,2,3].collect { |n| ARGV.last + n.to_s } end puts YAML.dump(result) @@ -496,6 +496,18 @@ class TestInterpreter < PuppetTest::TestCase assert_nil(node) end + # Make sure a nodesearch with arguments works + def test_nodesearch_external_arguments + mapper = mk_node_mapper + Puppet[:external_nodes] = "#{mapper} -s something -p somethingelse" + interp = mkinterp + node = nil + assert_nothing_raised do + node = interp.nodesearch("apple") + end + assert_instance_of(NodeDef, node, "did not create node") + end + # A wrapper test, to make sure we're correctly calling the external search method. def test_nodesearch_external_functional mapper = mk_node_mapper From 58e3855bb1c98e45f7e366d0f1fc6d834e0e5e43 Mon Sep 17 00:00:00 2001 From: Jeffrey J McCune Date: Tue, 14 Aug 2007 09:50:42 -0400 Subject: [PATCH 4/6] Added optional per-module lib directory. Puppet now looks for a lib directory inside each module bundle, and adds the directory to the list searched by Puppet::Util::Autoload. The intent is to facilitate more sophisticated virtual types and flexibility within modules. --- examples/code/modules/sample-module.pp | 10 ++++++ .../code/modules/sample-module/README.txt | 17 +++++++++ .../puppet/parser/functions/hostname_to_dn.rb | 36 +++++++++++++++++++ .../modules/sample-module/manifests/init.pp | 12 +++++++ .../sample-module/templates/sample.erb | 5 +++ lib/puppet/util/autoload.rb | 8 ++++- 6 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 examples/code/modules/sample-module.pp create mode 100644 examples/code/modules/sample-module/README.txt create mode 100644 examples/code/modules/sample-module/lib/puppet/parser/functions/hostname_to_dn.rb create mode 100644 examples/code/modules/sample-module/manifests/init.pp create mode 100644 examples/code/modules/sample-module/templates/sample.erb diff --git a/examples/code/modules/sample-module.pp b/examples/code/modules/sample-module.pp new file mode 100644 index 000000000..57079a0aa --- /dev/null +++ b/examples/code/modules/sample-module.pp @@ -0,0 +1,10 @@ +# Jeff McCune +# 2007-08-14 +# +# Use: +# puppet --verbose --debug --modulepath=`pwd` ./sample-module.pp +# +# sample-module demonstrates the use of a custom language function +# included within the module bundle. + +include sample-module diff --git a/examples/code/modules/sample-module/README.txt b/examples/code/modules/sample-module/README.txt new file mode 100644 index 000000000..ee4b8201a --- /dev/null +++ b/examples/code/modules/sample-module/README.txt @@ -0,0 +1,17 @@ +Jeff McCune +2007-08-14 + +This small, sample module demonstrates how to extend the puppet language +with a new parser function. + +See: +manifests/init.pp +lib/puppet/parser/functions/hostname_to_dn.rb +templates/sample.erb + +Note the consistent naming of files for Puppet::Util::Autoload + +Reference Documents: +http://reductivelabs.com/trac/puppet/wiki/ModuleOrganisation +http://reductivelabs.com/trac/puppet/wiki/WritingYourOwnFunctions +http://reductivelabs.com/trac/puppet/wiki/FunctionReference diff --git a/examples/code/modules/sample-module/lib/puppet/parser/functions/hostname_to_dn.rb b/examples/code/modules/sample-module/lib/puppet/parser/functions/hostname_to_dn.rb new file mode 100644 index 000000000..9f732b5bc --- /dev/null +++ b/examples/code/modules/sample-module/lib/puppet/parser/functions/hostname_to_dn.rb @@ -0,0 +1,36 @@ +# Copyright (C) David Schmitt +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the Author nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +# Jeff McCune +# 2007-08-14 +# See: http://reductivelabs.com/trac/puppet/wiki/WritingYourOwnFunctions + +module Puppet::Parser::Functions + newfunction(:hostname_to_dn, :type => :rvalue, :doc => "Given 'foo.bar.com', return 'dc=foo,dc=bar,dc=com'.") do |args| + args[0].split(/\./).map do |s| "dc=%s"%[s] end.join(",") + end +end diff --git a/examples/code/modules/sample-module/manifests/init.pp b/examples/code/modules/sample-module/manifests/init.pp new file mode 100644 index 000000000..1af8dff1f --- /dev/null +++ b/examples/code/modules/sample-module/manifests/init.pp @@ -0,0 +1,12 @@ +# Jeff McCune +# +# Demonstration of a custom parser function and erb template within +# a module, working in concert. + +class sample-module { + $fqdn_to_dn = hostname_to_dn($domain) + $sample_template = template("sample-module/sample.erb") + + notice("hostname_to_dn module function returned: [$fqdn_to_dn]") + info("sample.erb looks like:\n$sample_template") +} diff --git a/examples/code/modules/sample-module/templates/sample.erb b/examples/code/modules/sample-module/templates/sample.erb new file mode 100644 index 000000000..b13561b45 --- /dev/null +++ b/examples/code/modules/sample-module/templates/sample.erb @@ -0,0 +1,5 @@ + +## Jeff McCune +fqdn: <%= fqdn %> +basedn: <%= fqdn_to_dn %> +## end sample.erb ## diff --git a/lib/puppet/util/autoload.rb b/lib/puppet/util/autoload.rb index 42aa56c32..be9e14671 100644 --- a/lib/puppet/util/autoload.rb +++ b/lib/puppet/util/autoload.rb @@ -141,7 +141,13 @@ class Puppet::Util::Autoload # The list of directories to search through for loadable plugins. def searchpath - [Puppet[:libdir], $:].flatten + # JJM: Search for optional lib directories in each module bundle. + module_lib_dirs = Puppet[:modulepath].split(":").collect do |d| + Dir.glob("%s/*/lib" % d).select do |f| + FileTest.directory?(f) + end + end.flatten + [module_lib_dirs, Puppet[:libdir], $:].flatten end end From 2ff15c015b45b5b0bcb9e4f2ab67f8dfe3814348 Mon Sep 17 00:00:00 2001 From: "Michael V. O'Brien" Date: Tue, 14 Aug 2007 18:35:32 -0500 Subject: [PATCH 5/6] Added shortname support to config.rb and refactored addargs --- CHANGELOG | 2 + lib/puppet/util/config.rb | 59 ++++++++++++++---- lib/puppet/util/suidmanager.rb | 1 + test/util/config.rb | 109 ++++++++++++++++++++++++++------- 4 files changed, 137 insertions(+), 34 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f51e1f3c6..27aa0fa5e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,6 @@ 0.23.2 (misspiggy) + Added shortname support to config.rb and refactored addargs + Fixed the problem in cron jobs where environment settings tended to multiple. (#749) diff --git a/lib/puppet/util/config.rb b/lib/puppet/util/config.rb index 6d42f0ea6..932314215 100644 --- a/lib/puppet/util/config.rb +++ b/lib/puppet/util/config.rb @@ -1,6 +1,8 @@ require 'puppet' require 'sync' require 'puppet/transportable' +require 'getoptlong' + # The class for handling configuration files. class Puppet::Util::Config @@ -67,19 +69,12 @@ class Puppet::Util::Config # Generate the list of valid arguments, in a format that GetoptLong can # understand, and add them to the passed option list. def addargs(options) - require 'getoptlong' - # Hackish, but acceptable. Copy the current ARGV for restarting. Puppet.args = ARGV.dup # Add all of the config parameters as valid options. - self.each { |param, obj| - if self.boolean?(param) - options << ["--#{param}", GetoptLong::NO_ARGUMENT] - options << ["--no-#{param}", GetoptLong::NO_ARGUMENT] - else - options << ["--#{param}", GetoptLong::REQUIRED_ARGUMENT] - end + self.each { |name, element| + element.getopt_args.each { |args| options << args } } return options @@ -195,10 +190,17 @@ class Puppet::Util::Config @config.include?(name) end + # check to see if a short name is already defined + def shortinclude?(short) + short = short.intern if name.is_a? String + @shortnames.include?(short) + end + # Create a new config object def initialize @order = [] @config = {} + @shortnames = {} @created = [] @returned = {} @@ -499,7 +501,14 @@ class Puppet::Util::Config if @config.include?(name) raise Puppet::Error, "Parameter %s is already defined" % name end - @config[name] = newelement(hash) + tryconfig = newelement(hash) + if short = tryconfig.short + if other = @shortnames[short] + raise ArgumentError, "Parameter %s is already using short name '%s'" % [other.name, short] + end + @shortnames[short] = tryconfig + end + @config[name] = tryconfig } end @@ -858,7 +867,7 @@ Generated on #{Time.now}. # The base element type. class CElement attr_accessor :name, :section, :default, :parent, :setbycli - attr_reader :desc + attr_reader :desc, :short # Unset any set value. def clear @@ -885,6 +894,15 @@ Generated on #{Time.now}. @desc = value.gsub(/^\s*/, '') end + # get the arguments in getopt format + def getopt_args + if short + [["--#{name}", "-#{short}", GetoptLong::REQUIRED_ARGUMENT]] + else + [["--#{name}", GetoptLong::REQUIRED_ARGUMENT]] + end + end + def hook=(block) meta_def :handle, &block end @@ -929,6 +947,14 @@ Generated on #{Time.now}. end end + # short name for the celement + def short=(value) + if value.to_s.length != 1 + raise ArgumentError, "Short names can only be one character." + end + @short = value.to_s + end + # Convert the object to a config statement. def to_config str = @desc.gsub(/^/, "# ") + "\n" @@ -1101,6 +1127,17 @@ Generated on #{Time.now}. # A simple boolean. class CBoolean < CElement + # get the arguments in getopt format + def getopt_args + if short + [["--#{name}", "-#{short}", GetoptLong::NO_ARGUMENT], + ["--no-#{name}", GetoptLong::NO_ARGUMENT]] + else + [["--#{name}", GetoptLong::NO_ARGUMENT], + ["--no-#{name}", GetoptLong::NO_ARGUMENT]] + end + end + def munge(value) case value when true, "true": return true diff --git a/lib/puppet/util/suidmanager.rb b/lib/puppet/util/suidmanager.rb index e15656d77..c1ff66248 100644 --- a/lib/puppet/util/suidmanager.rb +++ b/lib/puppet/util/suidmanager.rb @@ -1,5 +1,6 @@ require 'facter' require 'puppet/util/warnings' +require 'forwardable' module Puppet::Util::SUIDManager include Puppet::Util::Warnings diff --git a/test/util/config.rb b/test/util/config.rb index 71343556f..9a1017058 100755 --- a/test/util/config.rb +++ b/test/util/config.rb @@ -10,6 +10,8 @@ require 'puppettest/parsertesting' class TestConfig < Test::Unit::TestCase include PuppetTest include PuppetTest::ParserTesting + CElement = Puppet::Util::Config::CElement + CBoolean = Puppet::Util::Config::CBoolean def setup super @@ -535,34 +537,46 @@ yay = /a/path } end - def test_argadding - c = mkconfig + def test_addargs + @config.setdefaults("testing", + :onboolean => [true, "An on bool"], + :offboolean => [false, "An off bool"], + :string => ["a string", "A string arg"], + :file => ["/path/to/file", "A file arg"] + ) - assert_nothing_raised { - @config.setdefaults("testing", - :onboolean => [true, "An on bool"], - :offboolean => [false, "An off bool"], - :string => ["a string", "A string arg"], - :file => ["/path/to/file", "A file arg"] - ) + should = [] + @config.each { |name, element| + element.expects(:getopt_args).returns([name]) + should << name } - options = [] + result = [] + assert_nothing_raised("Add args failed") do + @config.addargs(result) + end + assert_equal(should, result, "Did not call addargs correctly.") - @config.addargs(options) + end - @config.each { |param, obj| - opt = "--%s" % param - assert(options.find { |ary| - ary[0] == opt - }, "Argument %s was not added" % opt) - - if @config.boolean?(param) - o = "--no-%s" % param - assert(options.find { |ary| - ary[0] == o - }, "Boolean off %s was not added" % o) + def test_addargs_functional + @config.setdefaults("testing", + :onboolean => [true, "An on bool"], + :string => ["a string", "A string arg"] + ) + result = [] + should = [] + assert_nothing_raised("Add args failed") do + @config.addargs(result) + end + @config.each do |name, element| + if name == :onboolean + should << ["--onboolean", GetoptLong::NO_ARGUMENT] + should << ["--no-onboolean", GetoptLong::NO_ARGUMENT] + elsif name == :string + should << ["--string", GetoptLong::REQUIRED_ARGUMENT] end - } + end + assert_equal(should, result, "Add args functional test failed") end def test_usesection @@ -1243,6 +1257,55 @@ inttest = 27 # And make sure other params are unchanged assert_equal("unval", @config[:unchanged], "Unchanged value has somehow changed") end + + # Test to make sure that we can set and get a short name + def test_celement_short_name + element = nil + assert_nothing_raised("Could not create celement") do + element = CElement.new :short => "n", :desc => "anything" + end + assert_equal("n", element.short, "Short value is not retained") + + assert_raise(ArgumentError,"Allowed multicharactered short names.") do + element = CElement.new :short => "no", :desc => "anything" + end + end + + # Test to make sure that no two celements have the same short name + def test_celement_short_name_not_duplicated + config = mkconfig + assert_nothing_raised("Could not create celement with short name.") do + config.setdefaults(:main, + :one => { :default => "blah", :desc => "anything", :short => "o" }) + end + assert_nothing_raised("Could not create second celement with short name.") do + config.setdefaults(:main, + :two => { :default => "blah", :desc => "anything", :short => "i" }) + end + assert_raise(ArgumentError, "Could create second celement with duplicate short name.") do + config.setdefaults(:main, + :three => { :default => "blah", :desc => "anything", :short => "i" }) + end + # make sure that when the above raises an expection that the config is not included + assert(!config.include?(:three), "Invalid configuration item was retained") + end + + # Tell getopt which arguments are valid + def test_get_getopt_args + element = CElement.new :name => "foo", :desc => "anything" + assert_equal([["--foo", GetoptLong::REQUIRED_ARGUMENT]], element.getopt_args, "Did not produce appropriate getopt args") + + element.short = "n" + assert_equal([["--foo", "-n", GetoptLong::REQUIRED_ARGUMENT]], element.getopt_args, "Did not produce appropriate getopt args") + + element = CBoolean.new :name => "foo", :desc => "anything" + assert_equal([["--foo", GetoptLong::NO_ARGUMENT], ["--no-foo", GetoptLong::NO_ARGUMENT]], + element.getopt_args, "Did not produce appropriate getopt args") + + element.short = "n" + assert_equal([["--foo", "-n", GetoptLong::NO_ARGUMENT],["--no-foo", GetoptLong::NO_ARGUMENT]], + element.getopt_args, "Did not produce appropriate getopt args") + end end # $Id$ From 282ec893ef895e0d386126ba70494a3b086030b9 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Thu, 16 Aug 2007 00:00:28 -0500 Subject: [PATCH 6/6] Fixing the spec library so it correctly can see its version --- test/lib/spec/version.rb | 58 ++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/test/lib/spec/version.rb b/test/lib/spec/version.rb index 924d8458a..e692a87ee 100644 --- a/test/lib/spec/version.rb +++ b/test/lib/spec/version.rb @@ -1,30 +1,30 @@ -module Spec - module VERSION - def self.build_tag - tag = "REL_" + [MAJOR, MINOR, TINY].join('_') - if defined?(RELEASE_CANDIDATE) - tag << "_" << RELEASE_CANDIDATE - end - tag - end - - unless defined? MAJOR - MAJOR = 0 - MINOR = 8 - TINY = 2 - # RELEASE_CANDIDATE = "RC1" - +module Spec + module VERSION + def self.build_tag + tag = "REL_" + [MAJOR, MINOR, TINY].join('_') + if defined?(RELEASE_CANDIDATE) + tag << "_" << RELEASE_CANDIDATE + end + tag + end + + unless defined? MAJOR + MAJOR = 0 + MINOR = 8 + TINY = 2 + # RELEASE_CANDIDATE = "RC1" + # RANDOM_TOKEN: 0.375509844656552 - REV = "$LastChangedRevision$".match(/LastChangedRevision: (\d+)/)[1] - - STRING = [MAJOR, MINOR, TINY].join('.') - FULL_VERSION = "#{STRING} (r#{REV})" - TAG = build_tag - - NAME = "RSpec" - URL = "http://rspec.rubyforge.org/" - - DESCRIPTION = "#{NAME}-#{FULL_VERSION} - BDD for Ruby\n#{URL}" - end - end -end \ No newline at end of file + REV = "$LastChangedRevision: 2283$".match(/LastChangedRevision: (\d+)/)[1] + + STRING = [MAJOR, MINOR, TINY].join('.') + FULL_VERSION = "#{STRING} (r#{REV})" + TAG = build_tag + + NAME = "RSpec" + URL = "http://rspec.rubyforge.org/" + + DESCRIPTION = "#{NAME}-#{FULL_VERSION} - BDD for Ruby\n#{URL}" + end + end +end