+100 :-)
On Wed, Aug 20, 2008 at 9:35 AM, James Turnbull <[EMAIL PROTECTED]> wrote:
>
>
> Signed-off-by: James Turnbull <[EMAIL PROTECTED]>
> ---
> CHANGELOG | 4 +
> lib/puppet/parser/functions.rb | 224
> +-----------------------------
> lib/puppet/parser/functions/defined.rb | 27 ++++
> lib/puppet/parser/functions/fail.rb | 4 +
> lib/puppet/parser/functions/file.rb | 21 +++
> lib/puppet/parser/functions/fqdn_rand.rb | 15 ++
> lib/puppet/parser/functions/generate.rb | 35 +++++
> lib/puppet/parser/functions/include.rb | 26 ++++
> lib/puppet/parser/functions/realize.rb | 14 ++
> lib/puppet/parser/functions/search.rb | 7 +
> lib/puppet/parser/functions/sha1.rb | 6 +
> lib/puppet/parser/functions/tag.rb | 6 +
> lib/puppet/parser/functions/tagged.rb | 18 +++
> lib/puppet/parser/functions/template.rb | 22 +++
> 14 files changed, 212 insertions(+), 217 deletions(-)
> create mode 100644 lib/puppet/parser/functions/defined.rb
> create mode 100644 lib/puppet/parser/functions/fail.rb
> create mode 100644 lib/puppet/parser/functions/file.rb
> create mode 100644 lib/puppet/parser/functions/fqdn_rand.rb
> create mode 100644 lib/puppet/parser/functions/generate.rb
> create mode 100644 lib/puppet/parser/functions/include.rb
> create mode 100644 lib/puppet/parser/functions/realize.rb
> create mode 100644 lib/puppet/parser/functions/search.rb
> create mode 100644 lib/puppet/parser/functions/sha1.rb
> create mode 100644 lib/puppet/parser/functions/tag.rb
> create mode 100644 lib/puppet/parser/functions/tagged.rb
> create mode 100644 lib/puppet/parser/functions/template.rb
>
> diff --git a/CHANGELOG b/CHANGELOG
> index bf0fea2..eb7f88a 100644
> --- a/CHANGELOG
> +++ b/CHANGELOG
> @@ -1,4 +1,8 @@
> 0.24.x
> + Fixed #1488 - Moved individual functions out of functions.rb into
> + lib/puppet/parser/functions directory. New functions should be created
> in
> + this directory.
> +
> Fixed #1508 - Added HP-UX package provider
>
> Fixed #1502 - Fixed poor stored configuration performance
> diff --git a/lib/puppet/parser/functions.rb b/lib/puppet/parser/functions.rb
> index 51903e9..5fb0439 100644
> --- a/lib/puppet/parser/functions.rb
> +++ b/lib/puppet/parser/functions.rb
> @@ -6,6 +6,8 @@ module Functions
> # A module for managing parser functions. Each specified function
> # becomes an instance method on the Scope class.
>
> + @functions = {}
> +
> class << self
> include Puppet::Util
> end
> @@ -23,7 +25,6 @@ module Functions
>
> # Create a new function type.
> def self.newfunction(name, options = {}, &block)
> - @functions ||= {}
> name = symbolize(name)
>
> if @functions.include? name
> @@ -105,226 +106,15 @@ module Functions
> return false
> end
> end
> -
> - # Include the specified classes
> - newfunction(:include, :doc => "Evaluate one or more classes.") do |vals|
> - vals = [vals] unless vals.is_a?(Array)
> -
> - # The 'false' disables lazy evaluation.
> - klasses = compiler.evaluate_classes(vals, self, false)
> -
> - missing = vals.find_all do |klass|
> - ! klasses.include?(klass)
> - end
> -
> - unless missing.empty?
> - # Throw an error if we didn't evaluate all of the classes.
> - str = "Could not find class"
> - if missing.length > 1
> - str += "es"
> - end
> -
> - str += " " + missing.join(", ")
> -
> - if n = namespaces and ! n.empty? and n != [""]
> - str += " in namespaces %s" % @namespaces.join(", ")
> - end
> - self.fail Puppet::ParseError, str
> - end
> - end
> -
> - # Tag the current scope with each passed name
> - newfunction(:tag, :doc => "Add the specified tags to the containing class
> - or definition. All contained objects will then acquire that tag, also.
> - ") do |vals|
> - self.resource.tag(*vals)
> - end
> -
> - # Test whether a given tag is set. This functions as a big OR -- if any
> of the
> - # specified tags are unset, we return false.
> - newfunction(:tagged, :type => :rvalue, :doc => "A boolean function that
> - tells you whether the current container is tagged with the specified
> tags.
> - The tags are ANDed, so that all of the specified tags must be included
> for
> - the function to return true.") do |vals|
> - configtags = compiler.catalog.tags
> - resourcetags = resource.tags
> -
> - retval = true
> - vals.each do |val|
> - unless configtags.include?(val) or resourcetags.include?(val)
> - retval = false
> - break
> - end
> - end
> -
> - return retval
> - end
> -
> - # Test whether a given class or definition is defined
> - newfunction(:defined, :type => :rvalue, :doc => "Determine whether a
> given
> - type is defined, either as a native type or a defined type, or whether a
> class is defined.
> - This is useful for checking whether a class is defined and only
> including it if it is.
> - This function can also test whether a resource has been defined, using
> resource references
> - (e.g., ``if defined(File['/tmp/myfile']) { ... }``). This function is
> unfortunately
> - dependent on the parse order of the configuration when testing whether a
> resource is defined.") do |vals|
> - result = false
> - vals.each do |val|
> - case val
> - when String:
> - # For some reason, it doesn't want me to return from here.
> - if Puppet::Type.type(val) or finddefine(val) or
> findclass(val)
> - result = true
> - break
> - end
> - when Puppet::Parser::Resource::Reference:
> - if findresource(val.to_s)
> - result = true
> - break
> - end
> - else
> - raise ArgumentError, "Invalid argument of type %s to
> 'defined'" % val.class
> - end
> - end
> - result
> - end
> -
> - newfunction(:fqdn_rand, :type => :rvalue, :doc => "Generates random
> - numbers based on the node's fqdn. The first argument sets the range.
> - The second argument specifies a number to add to the seed and is
> - optional.") do |args|
> - require 'md5'
> - max = args[0]
> - if args[1] then
> - seed = args[1]
> - else
> - seed = 1
> - end
> - fqdn_seed = MD5.new(lookupvar('fqdn')).to_s.hex
> - srand(seed+fqdn_seed)
> - rand(max).to_s
> - end
> -
> - newfunction(:fail, :doc => "Fail with a parse error.") do |vals|
> - vals = vals.collect { |s| s.to_s }.join(" ") if vals.is_a? Array
> - raise Puppet::ParseError, vals.to_s
> - end
> -
> +
> # Runs a newfunction to create a function for each of the log levels
> - Puppet::Util::Log.levels.each do |level|
> - newfunction(level, :doc => "Log a message on the server at level
> - #{level.to_s}.") do |vals|
> - send(level, vals.join(" "))
> - end
> - end
> -
> - newfunction(:template, :type => :rvalue, :doc => "Evaluate a template and
> - return its value. See `the templating docs
> </trac/puppet/wiki/PuppetTemplating>`_
> - for more information. Note that if multiple templates are specified,
> their
> - output is all concatenated and returned as the output of the function.
> - ") do |vals|
> - require 'erb'
> -
> - vals.collect do |file|
> - # Use a wrapper, so the template can't get access to the full
> - # Scope object.
> - debug "Retrieving template %s" % file
> - wrapper = Puppet::Parser::TemplateWrapper.new(self, file)
> -
> - begin
> - wrapper.result()
> - rescue => detail
> - raise Puppet::ParseError,
> - "Failed to parse template %s: %s" %
> - [file, detail]
> - end
> - end.join("")
> - end
> -
> - # This is just syntactic sugar for a collection, although it will
> generally
> - # be a good bit faster.
> - newfunction(:realize, :doc => "Make a virtual object real. This is
> useful
> - when you want to know the name of the virtual object and don't want
> to
> - bother with a full collection. It is slightly faster than a
> collection,
> - and, of course, is a bit shorter. You must pass the object using a
> - reference; e.g.: ``realize User[luke]``." ) do |vals|
> - coll = Puppet::Parser::Collector.new(self, :nomatter, nil, nil,
> :virtual)
> - vals = [vals] unless vals.is_a?(Array)
> - coll.resources = vals
>
> - compiler.add_collection(coll)
> - end
> -
> - newfunction(:search, :doc => "Add another namespace for this class to
> search.
> - This allows you to create classes with sets of definitions and add
> - those classes to another class's search path.") do |vals|
> - vals.each do |val|
> - add_namespace(val)
> + Puppet::Util::Log.levels.each do |level|
> + newfunction(level, :doc => "Log a message on the server at level
> + #{level.to_s}.") do |vals|
> + send(level, vals.join(" "))
> end
> end
>
> - newfunction(:file, :type => :rvalue,
> - :doc => "Return the contents of a file. Multiple files
> - can be passed, and the first file that exists will be read in.") do
> |vals|
> - ret = nil
> - vals.each do |file|
> - unless file =~ /^#{File::SEPARATOR}/
> - raise Puppet::ParseError, "Files must be fully qualified"
> - end
> - if FileTest.exists?(file)
> - ret = File.read(file)
> - break
> - end
> - end
> - if ret
> - ret
> - else
> - raise Puppet::ParseError, "Could not find any files from %s"
> %
> - vals.join(", ")
> - end
> - end
> -
> - newfunction(:generate, :type => :rvalue,
> - :doc => "Calls an external command and returns the results of the
> - command. Any arguments are passed to the external command as
> - arguments. If the generator does not exit with return code of 0,
> - the generator is considered to have failed and a parse error is
> - thrown. Generators can only have file separators, alphanumerics,
> dashes,
> - and periods in them. This function will attempt to protect you from
> - malicious generator calls (e.g., those with '..' in them), but it can
> - never be entirely safe. No subshell is used to execute
> - generators, so all shell metacharacters are passed directly to
> - the generator.") do |args|
> -
> - unless args[0] =~ /^#{File::SEPARATOR}/
> - raise Puppet::ParseError, "Generators must be fully
> qualified"
> - end
> -
> - unless args[0] =~ /^[-#{File::SEPARATOR}\w.]+$/
> - raise Puppet::ParseError,
> - "Generators can only contain alphanumerics, file
> separators, and dashes"
> - end
> -
> - if args[0] =~ /\.\./
> - raise Puppet::ParseError,
> - "Can not use generators with '..' in them."
> - end
> -
> - begin
> - output = Puppet::Util.execute(args)
> - rescue Puppet::ExecutionFailure => detail
> - raise Puppet::ParseError, "Failed to execute generator %s:
> %s" %
> - [args[0], detail]
> - end
> - output
> - end
> -
> - newfunction(:sha1, :type => :rvalue,
> - :doc => "Returns a SHA1 hash value from a provided string.") do
> |args|
> - require 'sha1'
> -
> - Digest::SHA1.hexdigest(args[0])
> - end
> -
> end
> end
> -
> diff --git a/lib/puppet/parser/functions/defined.rb
> b/lib/puppet/parser/functions/defined.rb
> new file mode 100644
> index 0000000..4e369ae
> --- /dev/null
> +++ b/lib/puppet/parser/functions/defined.rb
> @@ -0,0 +1,27 @@
> +# Test whether a given class or definition is defined
> +Puppet::Parser::Functions::newfunction(:defined, :type => :rvalue, :doc =>
> "Determine whether a given
> + type is defined, either as a native type or a defined type, or whether a
> class is defined.
> + This is useful for checking whether a class is defined and only
> including it if it is.
> + This function can also test whether a resource has been defined, using
> resource references
> + (e.g., ``if defined(File['/tmp/myfile']) { ... }``). This function is
> unfortunately
> + dependent on the parse order of the configuration when testing whether a
> resource is defined.") do |vals|
> + result = false
> + vals.each do |val|
> + case val
> + when String:
> + # For some reason, it doesn't want me to return from here.
> + if Puppet::Type.type(val) or finddefine(val) or
> findclass(val)
> + result = true
> + break
> + end
> + when Puppet::Parser::Resource::Reference:
> + if findresource(val.to_s)
> + result = true
> + break
> + end
> + else
> + raise ArgumentError, "Invalid argument of type %s to
> 'defined'" % val.class
> + end
> + end
> + result
> +end
> diff --git a/lib/puppet/parser/functions/fail.rb
> b/lib/puppet/parser/functions/fail.rb
> new file mode 100644
> index 0000000..35b20ee
> --- /dev/null
> +++ b/lib/puppet/parser/functions/fail.rb
> @@ -0,0 +1,4 @@
> +Puppet::Parser::Functions::newfunction(:fail, :doc => "Fail with a parse
> error.") do |vals|
> + vals = vals.collect { |s| s.to_s }.join(" ") if vals.is_a? Array
> + raise Puppet::ParseError, vals.to_s
> +end
> diff --git a/lib/puppet/parser/functions/file.rb
> b/lib/puppet/parser/functions/file.rb
> new file mode 100644
> index 0000000..47b3f96
> --- /dev/null
> +++ b/lib/puppet/parser/functions/file.rb
> @@ -0,0 +1,21 @@
> +# Returns the contents of a file
> +Puppet::Parser::Functions::newfunction(:file, :type => :rvalue,
> + :doc => "Return the contents of a file. Multiple files
> + can be passed, and the first file that exists will be read in.") do
> |vals|
> + ret = nil
> + vals.each do |file|
> + unless file =~ /^#{File::SEPARATOR}/
> + raise Puppet::ParseError, "Files must be fully qualified"
> + end
> + if FileTest.exists?(file)
> + ret = File.read(file)
> + break
> + end
> + end
> + if ret
> + ret
> + else
> + raise Puppet::ParseError, "Could not find any files from %s"
> %
> + vals.join(", ")
> + end
> +end
> diff --git a/lib/puppet/parser/functions/fqdn_rand.rb
> b/lib/puppet/parser/functions/fqdn_rand.rb
> new file mode 100644
> index 0000000..2ae46de
> --- /dev/null
> +++ b/lib/puppet/parser/functions/fqdn_rand.rb
> @@ -0,0 +1,15 @@
> +Puppet::Parser::Functions::newfunction(:fqdn_rand, :type => :rvalue, :doc =>
> + "Generates random numbers based on the node's fqdn. The first argument
> + sets the range. The second argument specifies a number to add to the
> + seed and is optional.") do |args|
> + require 'md5'
> + max = args[0]
> + if args[1] then
> + seed = args[1]
> + else
> + seed = 1
> + end
> + fqdn_seed = MD5.new(lookupvar('fqdn')).to_s.hex
> + srand(seed+fqdn_seed)
> + rand(max).to_s
> +end
> diff --git a/lib/puppet/parser/functions/generate.rb
> b/lib/puppet/parser/functions/generate.rb
> new file mode 100644
> index 0000000..1be9016
> --- /dev/null
> +++ b/lib/puppet/parser/functions/generate.rb
> @@ -0,0 +1,35 @@
> +# Runs an external command and returns the results
> +Puppet::Parser::Functions::newfunction(:generate, :type => :rvalue,
> + :doc => "Calls an external command and returns the results of the
> + command. Any arguments are passed to the external command as
> + arguments. If the generator does not exit with return code of 0,
> + the generator is considered to have failed and a parse error is
> + thrown. Generators can only have file separators, alphanumerics,
> dashes,
> + and periods in them. This function will attempt to protect you from
> + malicious generator calls (e.g., those with '..' in them), but it can
> + never be entirely safe. No subshell is used to execute
> + generators, so all shell metacharacters are passed directly to
> + the generator.") do |args|
> +
> + unless args[0] =~ /^#{File::SEPARATOR}/
> + raise Puppet::ParseError, "Generators must be fully
> qualified"
> + end
> +
> + unless args[0] =~ /^[-#{File::SEPARATOR}\w.]+$/
> + raise Puppet::ParseError,
> + "Generators can only contain alphanumerics, file
> separators, and dashes"
> + end
> +
> + if args[0] =~ /\.\./
> + raise Puppet::ParseError,
> + "Can not use generators with '..' in them."
> + end
> +
> + begin
> + output = Puppet::Util.execute(args)
> + rescue Puppet::ExecutionFailure => detail
> + raise Puppet::ParseError, "Failed to execute generator %s:
> %s" %
> + [args[0], detail]
> + end
> + output
> +end
> diff --git a/lib/puppet/parser/functions/include.rb
> b/lib/puppet/parser/functions/include.rb
> new file mode 100644
> index 0000000..213a041
> --- /dev/null
> +++ b/lib/puppet/parser/functions/include.rb
> @@ -0,0 +1,26 @@
> +# Include the specified classes
> +Puppet::Parser::Functions::newfunction(:include, :doc => "Evaluate one or
> more classes.") do |vals|
> + vals = [vals] unless vals.is_a?(Array)
> +
> + # The 'false' disables lazy evaluation.
> + klasses = compiler.evaluate_classes(vals, self, false)
> +
> + missing = vals.find_all do |klass|
> + ! klasses.include?(klass)
> + end
> +
> + unless missing.empty?
> + # Throw an error if we didn't evaluate all of the classes.
> + str = "Could not find class"
> + if missing.length > 1
> + str += "es"
> + end
> +
> + str += " " + missing.join(", ")
> +
> + if n = namespaces and ! n.empty? and n != [""]
> + str += " in namespaces %s" % @namespaces.join(", ")
> + end
> + self.fail Puppet::ParseError, str
> + end
> +end
> diff --git a/lib/puppet/parser/functions/realize.rb
> b/lib/puppet/parser/functions/realize.rb
> new file mode 100644
> index 0000000..1bdde23
> --- /dev/null
> +++ b/lib/puppet/parser/functions/realize.rb
> @@ -0,0 +1,14 @@
> +# This is just syntactic sugar for a collection, although it will generally
> +# be a good bit faster.
> +
> +Puppet::Parser::Functions::newfunction(:realize, :doc => "Make a virtual
> object real. This is useful
> + when you want to know the name of the virtual object and don't want
> to
> + bother with a full collection. It is slightly faster than a
> collection,
> + and, of course, is a bit shorter. You must pass the object using a
> + reference; e.g.: ``realize User[luke]``." ) do |vals|
> + coll = Puppet::Parser::Collector.new(self, :nomatter, nil, nil,
> :virtual)
> + vals = [vals] unless vals.is_a?(Array)
> + coll.resources = vals
> +
> + compiler.add_collection(coll)
> +end
> diff --git a/lib/puppet/parser/functions/search.rb
> b/lib/puppet/parser/functions/search.rb
> new file mode 100644
> index 0000000..87dd02d
> --- /dev/null
> +++ b/lib/puppet/parser/functions/search.rb
> @@ -0,0 +1,7 @@
> +Puppet::Parser::Functions::newfunction(:search, :doc => "Add another
> namespace for this class to search.
> + This allows you to create classes with sets of definitions and add
> + those classes to another class's search path.") do |vals|
> + vals.each do |val|
> + add_namespace(val)
> + end
> +end
> diff --git a/lib/puppet/parser/functions/sha1.rb
> b/lib/puppet/parser/functions/sha1.rb
> new file mode 100644
> index 0000000..09386a6
> --- /dev/null
> +++ b/lib/puppet/parser/functions/sha1.rb
> @@ -0,0 +1,6 @@
> +Puppet::Parser::Functions::newfunction(:sha1, :type => :rvalue,
> + :doc => "Returns a SHA1 hash value from a provided string.") do
> |args|
> + require 'sha1'
> +
> + Digest::SHA1.hexdigest(args[0])
> +end
> diff --git a/lib/puppet/parser/functions/tag.rb
> b/lib/puppet/parser/functions/tag.rb
> new file mode 100644
> index 0000000..3e487fe
> --- /dev/null
> +++ b/lib/puppet/parser/functions/tag.rb
> @@ -0,0 +1,6 @@
> +# Tag the current scope with each passed name
> +Puppet::Parser::Functions::newfunction(:tag, :doc => "Add the specified tags
> to the containing class
> + or definition. All contained objects will then acquire that tag, also.
> + ") do |vals|
> + self.resource.tag(*vals)
> +end
> diff --git a/lib/puppet/parser/functions/tagged.rb
> b/lib/puppet/parser/functions/tagged.rb
> new file mode 100644
> index 0000000..fccb132
> --- /dev/null
> +++ b/lib/puppet/parser/functions/tagged.rb
> @@ -0,0 +1,18 @@
> +# Test whether a given tag is set. This functions as a big OR -- if any of
> the specified tags are unset, we return false.
> +Puppet::Parser::Functions::newfunction(:tagged, :type => :rvalue, :doc => "A
> boolean function that
> + tells you whether the current container is tagged with the specified
> tags.
> + The tags are ANDed, so that all of the specified tags must be included
> for
> + the function to return true.") do |vals|
> + configtags = compiler.catalog.tags
> + resourcetags = resource.tags
> +
> + retval = true
> + vals.each do |val|
> + unless configtags.include?(val) or resourcetags.include?(val)
> + retval = false
> + break
> + end
> + end
> +
> + return retval
> +end
> diff --git a/lib/puppet/parser/functions/template.rb
> b/lib/puppet/parser/functions/template.rb
> new file mode 100644
> index 0000000..e62c3b3
> --- /dev/null
> +++ b/lib/puppet/parser/functions/template.rb
> @@ -0,0 +1,22 @@
> +Puppet::Parser::Functions::newfunction(:template, :type => :rvalue, :doc =>
> + "Evaluate a template and return its value. See `the templating docs
> + </trac/puppet/wiki/PuppetTemplating>`_ for more information. Note that
> + if multiple templates are specified, their output is all concatenated
> + and returned as the output of the function.") do |vals|
> + require 'erb'
> +
> + vals.collect do |file|
> + # Use a wrapper, so the template can't get access to the full
> + # Scope object.
> + debug "Retrieving template %s" % file
> + wrapper = Puppet::Parser::TemplateWrapper.new(self, file)
> +
> + begin
> + wrapper.result()
> + rescue => detail
> + raise Puppet::ParseError,
> + "Failed to parse template %s: %s" %
> + [file, detail]
> + end
> + end.join("")
> +end
> --
> 1.5.4.1
>
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Puppet Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/puppet-dev?hl=en
-~----------~----~----~----~------~----~------~--~---