summaryrefslogtreecommitdiff
path: root/lib/puppet/parser
diff options
context:
space:
mode:
authorMicah Anderson <micah@riseup.net>2013-05-26 16:19:56 -0400
committerMicah Anderson <micah@riseup.net>2013-05-26 16:19:56 -0400
commit966f3b349a60b3997e58af1095bbd96671952fac (patch)
tree3c1dcdb0cd353427eb066f6926610445700a2a66 /lib/puppet/parser
parent66e0fa8f1bc5062e9d753598ad17602c378a2994 (diff)
parent9c8c8275abd76878d38a0f6f3af52dc468656283 (diff)
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'lib/puppet/parser')
-rw-r--r--lib/puppet/parser/functions/any2array.rb33
-rw-r--r--lib/puppet/parser/functions/base64.rb37
-rw-r--r--lib/puppet/parser/functions/concat.rb37
-rw-r--r--lib/puppet/parser/functions/count.rb22
-rw-r--r--lib/puppet/parser/functions/difference.rb36
-rw-r--r--lib/puppet/parser/functions/dirname.rb15
-rw-r--r--lib/puppet/parser/functions/ensure_resource.rb22
-rw-r--r--lib/puppet/parser/functions/flatten.rb2
-rw-r--r--lib/puppet/parser/functions/floor.rb20
-rw-r--r--lib/puppet/parser/functions/getparam.rb35
-rw-r--r--lib/puppet/parser/functions/hash.rb2
-rw-r--r--lib/puppet/parser/functions/intersection.rb34
-rw-r--r--lib/puppet/parser/functions/is_float.rb2
-rw-r--r--lib/puppet/parser/functions/is_function_available.rb23
-rw-r--r--lib/puppet/parser/functions/is_integer.rb2
-rw-r--r--lib/puppet/parser/functions/is_numeric.rb2
-rw-r--r--lib/puppet/parser/functions/max.rb10
-rw-r--r--lib/puppet/parser/functions/merge.rb1
-rw-r--r--lib/puppet/parser/functions/min.rb10
-rw-r--r--lib/puppet/parser/functions/num2bool.rb43
-rw-r--r--lib/puppet/parser/functions/prefix.rb6
-rw-r--r--lib/puppet/parser/functions/str2bool.rb5
-rw-r--r--lib/puppet/parser/functions/suffix.rb45
-rw-r--r--lib/puppet/parser/functions/union.rb34
-rw-r--r--lib/puppet/parser/functions/validate_augeas.rb81
-rw-r--r--lib/puppet/parser/functions/validate_cmd.rb47
26 files changed, 570 insertions, 36 deletions
diff --git a/lib/puppet/parser/functions/any2array.rb b/lib/puppet/parser/functions/any2array.rb
new file mode 100644
index 0000000..e71407e
--- /dev/null
+++ b/lib/puppet/parser/functions/any2array.rb
@@ -0,0 +1,33 @@
+#
+# any2array.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:any2array, :type => :rvalue, :doc => <<-EOS
+This converts any object to an array containing that object. Empty argument
+lists are converted to an empty array. Arrays are left untouched. Hashes are
+converted to arrays of alternating keys and values.
+ EOS
+ ) do |arguments|
+
+ if arguments.empty?
+ return []
+ end
+
+ if arguments.length == 1
+ if arguments[0].kind_of?(Array)
+ return arguments[0]
+ elsif arguments[0].kind_of?(Hash)
+ result = []
+ arguments[0].each do |key, value|
+ result << key << value
+ end
+ return result
+ end
+ end
+
+ return arguments
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/base64.rb b/lib/puppet/parser/functions/base64.rb
new file mode 100644
index 0000000..d9a590a
--- /dev/null
+++ b/lib/puppet/parser/functions/base64.rb
@@ -0,0 +1,37 @@
+module Puppet::Parser::Functions
+
+ newfunction(:base64, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
+
+ Base64 encode or decode a string based on the command and the string submitted
+
+ Usage:
+
+ $encodestring = base64('encode','thestring')
+ $decodestring = base64('decode','dGhlc3RyaW5n')
+
+ ENDHEREDOC
+
+ require 'base64'
+
+ raise Puppet::ParseError, ("base64(): Wrong number of arguments (#{args.length}; must be = 2)") unless args.length == 2
+
+ actions = ['encode','decode']
+
+ unless actions.include?(args[0])
+ raise Puppet::ParseError, ("base64(): the first argument must be one of 'encode' or 'decode'")
+ end
+
+ unless args[1].is_a?(String)
+ raise Puppet::ParseError, ("base64(): the second argument must be a string to base64")
+ end
+
+ case args[0]
+ when 'encode'
+ result = Base64.encode64(args[1])
+ when 'decode'
+ result = Base64.decode64(args[1])
+ end
+
+ return result
+ end
+end
diff --git a/lib/puppet/parser/functions/concat.rb b/lib/puppet/parser/functions/concat.rb
new file mode 100644
index 0000000..c86aa00
--- /dev/null
+++ b/lib/puppet/parser/functions/concat.rb
@@ -0,0 +1,37 @@
+#
+# concat.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:concat, :type => :rvalue, :doc => <<-EOS
+Appends the contents of array 2 onto array 1.
+
+*Example:*
+
+ concat(['1','2','3'],['4','5','6'])
+
+Would result in:
+
+ ['1','2','3','4','5','6']
+ EOS
+ ) do |arguments|
+
+ # Check that 2 arguments have been given ...
+ raise(Puppet::ParseError, "concat(): Wrong number of arguments " +
+ "given (#{arguments.size} for 2)") if arguments.size != 2
+
+ a = arguments[0]
+ b = arguments[1]
+
+ # Check that both args are arrays.
+ unless a.is_a?(Array) and b.is_a?(Array)
+ raise(Puppet::ParseError, 'concat(): Requires array to work with')
+ end
+
+ result = a.concat(b)
+
+ return result
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/count.rb b/lib/puppet/parser/functions/count.rb
new file mode 100644
index 0000000..52de1b8
--- /dev/null
+++ b/lib/puppet/parser/functions/count.rb
@@ -0,0 +1,22 @@
+module Puppet::Parser::Functions
+ newfunction(:count, :type => :rvalue, :arity => -2, :doc => <<-EOS
+Takes an array as first argument and an optional second argument.
+Count the number of elements in array that matches second argument.
+If called with only an array it counts the number of elements that are not nil/undef.
+ EOS
+ ) do |args|
+
+ if (args.size > 2) then
+ raise(ArgumentError, "count(): Wrong number of arguments "+
+ "given #{args.size} for 1 or 2.")
+ end
+
+ collection, item = args
+
+ if item then
+ collection.count item
+ else
+ collection.count { |obj| obj != nil && obj != :undef && obj != '' }
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/difference.rb b/lib/puppet/parser/functions/difference.rb
new file mode 100644
index 0000000..cd258f7
--- /dev/null
+++ b/lib/puppet/parser/functions/difference.rb
@@ -0,0 +1,36 @@
+#
+# difference.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:difference, :type => :rvalue, :doc => <<-EOS
+This function returns the difference between two arrays.
+The returned array is a copy of the original array, removing any items that
+also appear in the second array.
+
+*Examples:*
+
+ difference(["a","b","c"],["b","c","d"])
+
+Would return: ["a"]
+ EOS
+ ) do |arguments|
+
+ # Two arguments are required
+ raise(Puppet::ParseError, "difference(): Wrong number of arguments " +
+ "given (#{arguments.size} for 2)") if arguments.size != 2
+
+ first = arguments[0]
+ second = arguments[1]
+
+ unless first.is_a?(Array) && second.is_a?(Array)
+ raise(Puppet::ParseError, 'difference(): Requires 2 arrays')
+ end
+
+ result = first - second
+
+ return result
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/dirname.rb b/lib/puppet/parser/functions/dirname.rb
new file mode 100644
index 0000000..ea8cc1e
--- /dev/null
+++ b/lib/puppet/parser/functions/dirname.rb
@@ -0,0 +1,15 @@
+module Puppet::Parser::Functions
+ newfunction(:dirname, :type => :rvalue, :doc => <<-EOS
+ Returns the dirname of a path.
+ EOS
+ ) do |arguments|
+
+ raise(Puppet::ParseError, "dirname(): Wrong number of arguments " +
+ "given (#{arguments.size} for 1)") if arguments.size < 1
+
+ path = arguments[0]
+ return File.dirname(path)
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/ensure_resource.rb b/lib/puppet/parser/functions/ensure_resource.rb
index fba2035..a9a1733 100644
--- a/lib/puppet/parser/functions/ensure_resource.rb
+++ b/lib/puppet/parser/functions/ensure_resource.rb
@@ -19,17 +19,27 @@ If the resource already exists but does not match the specified parameters,
this function will attempt to recreate the resource leading to a duplicate
resource definition error.
+An array of resources can also be passed in and each will be created with
+the type and parameters specified if it doesn't already exist.
+
+ ensure_resource('user', ['dan','alex'], {'ensure' => 'present'})
+
ENDOFDOC
) do |vals|
type, title, params = vals
raise(ArgumentError, 'Must specify a type') unless type
raise(ArgumentError, 'Must specify a title') unless title
params ||= {}
- Puppet::Parser::Functions.function(:defined_with_params)
- if function_defined_with_params(["#{type}[#{title}]", params])
- Puppet.debug("Resource #{type}[#{title}] not created b/c it already exists")
- else
- Puppet::Parser::Functions.function(:create_resources)
- function_create_resources([type.capitalize, { title => params }])
+
+ items = [title].flatten
+
+ items.each do |item|
+ Puppet::Parser::Functions.function(:defined_with_params)
+ if function_defined_with_params(["#{type}[#{item}]", params])
+ Puppet.debug("Resource #{type}[#{item}] not created because it already exists")
+ else
+ Puppet::Parser::Functions.function(:create_resources)
+ function_create_resources([type.capitalize, { item => params }])
+ end
end
end
diff --git a/lib/puppet/parser/functions/flatten.rb b/lib/puppet/parser/functions/flatten.rb
index 781da78..a1ed183 100644
--- a/lib/puppet/parser/functions/flatten.rb
+++ b/lib/puppet/parser/functions/flatten.rb
@@ -16,7 +16,7 @@ Would return: ['a','b','c']
) do |arguments|
raise(Puppet::ParseError, "flatten(): Wrong number of arguments " +
- "given (#{arguments.size} for 1)") if arguments.size < 1
+ "given (#{arguments.size} for 1)") if arguments.size != 1
array = arguments[0]
diff --git a/lib/puppet/parser/functions/floor.rb b/lib/puppet/parser/functions/floor.rb
new file mode 100644
index 0000000..a401923
--- /dev/null
+++ b/lib/puppet/parser/functions/floor.rb
@@ -0,0 +1,20 @@
+module Puppet::Parser::Functions
+ newfunction(:floor, :type => :rvalue, :doc => <<-EOS
+ Returns the largest integer less or equal to the argument.
+ Takes a single numeric value as an argument.
+ EOS
+ ) do |arguments|
+
+ raise(Puppet::ParseError, "floor(): Wrong number of arguments " +
+ "given (#{arguments.size} for 1)") if arguments.size != 1
+
+ arg = arguments[0]
+
+ raise(Puppet::ParseError, "floor(): Wrong argument type " +
+ "given (#{arg.class} for Numeric)") if arg.is_a?(Numeric) == false
+
+ arg.floor
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/getparam.rb b/lib/puppet/parser/functions/getparam.rb
new file mode 100644
index 0000000..6d51006
--- /dev/null
+++ b/lib/puppet/parser/functions/getparam.rb
@@ -0,0 +1,35 @@
+# Test whether a given class or definition is defined
+require 'puppet/parser/functions'
+
+Puppet::Parser::Functions.newfunction(:getparam,
+ :type => :rvalue,
+ :doc => <<-'ENDOFDOC'
+Takes a resource reference and name of the parameter and
+returns value of resource's parameter.
+
+*Examples:*
+
+ define example_resource($param) {
+ }
+
+ example_resource { "example_resource_instance":
+ param => "param_value"
+ }
+
+ getparam(Example_resource["example_resource_instance"], "param")
+
+Would return: param_value
+ENDOFDOC
+) do |vals|
+ reference, param = vals
+ raise(ArgumentError, 'Must specify a reference') unless reference
+ raise(ArgumentError, 'Must specify name of a parameter') unless param and param.instance_of? String
+
+ return '' if param.empty?
+
+ if resource = findresource(reference.to_s)
+ return resource[param] if resource[param]
+ end
+
+ return ''
+end
diff --git a/lib/puppet/parser/functions/hash.rb b/lib/puppet/parser/functions/hash.rb
index 453ba1e..8cc4823 100644
--- a/lib/puppet/parser/functions/hash.rb
+++ b/lib/puppet/parser/functions/hash.rb
@@ -4,7 +4,7 @@
module Puppet::Parser::Functions
newfunction(:hash, :type => :rvalue, :doc => <<-EOS
-This function converts and array into a hash.
+This function converts an array into a hash.
*Examples:*
diff --git a/lib/puppet/parser/functions/intersection.rb b/lib/puppet/parser/functions/intersection.rb
new file mode 100644
index 0000000..48f02e9
--- /dev/null
+++ b/lib/puppet/parser/functions/intersection.rb
@@ -0,0 +1,34 @@
+#
+# intersection.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:intersection, :type => :rvalue, :doc => <<-EOS
+This function returns an array an intersection of two.
+
+*Examples:*
+
+ intersection(["a","b","c"],["b","c","d"])
+
+Would return: ["b","c"]
+ EOS
+ ) do |arguments|
+
+ # Two arguments are required
+ raise(Puppet::ParseError, "intersection(): Wrong number of arguments " +
+ "given (#{arguments.size} for 2)") if arguments.size != 2
+
+ first = arguments[0]
+ second = arguments[1]
+
+ unless first.is_a?(Array) && second.is_a?(Array)
+ raise(Puppet::ParseError, 'intersection(): Requires 2 arrays')
+ end
+
+ result = first & second
+
+ return result
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/is_float.rb b/lib/puppet/parser/functions/is_float.rb
index 2fc05ba..911f3c2 100644
--- a/lib/puppet/parser/functions/is_float.rb
+++ b/lib/puppet/parser/functions/is_float.rb
@@ -15,7 +15,7 @@ Returns true if the variable passed to this function is a float.
value = arguments[0]
- if value != value.to_f.to_s then
+ if value != value.to_f.to_s and !value.is_a? Float then
return false
else
return true
diff --git a/lib/puppet/parser/functions/is_function_available.rb b/lib/puppet/parser/functions/is_function_available.rb
new file mode 100644
index 0000000..6cbd35c
--- /dev/null
+++ b/lib/puppet/parser/functions/is_function_available.rb
@@ -0,0 +1,23 @@
+#
+# is_function_available.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:is_function_available, :type => :rvalue, :doc => <<-EOS
+This function accepts a string as an argument, determines whether the
+Puppet runtime has access to a function by that name. It returns a
+true if the function exists, false if not.
+ EOS
+ ) do |arguments|
+
+ if (arguments.size != 1) then
+ raise(Puppet::ParseError, "is_function_available?(): Wrong number of arguments "+
+ "given #{arguments.size} for 1")
+ end
+
+ function = Puppet::Parser::Functions.function(arguments[0].to_sym)
+ function.is_a?(String) and not function.empty?
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/is_integer.rb b/lib/puppet/parser/functions/is_integer.rb
index 8ee34f6..6b29e98 100644
--- a/lib/puppet/parser/functions/is_integer.rb
+++ b/lib/puppet/parser/functions/is_integer.rb
@@ -15,7 +15,7 @@ Returns true if the variable returned to this string is an integer.
value = arguments[0]
- if value != value.to_i.to_s then
+ if value != value.to_i.to_s and !value.is_a? Fixnum then
return false
else
return true
diff --git a/lib/puppet/parser/functions/is_numeric.rb b/lib/puppet/parser/functions/is_numeric.rb
index ce13ece..abf0321 100644
--- a/lib/puppet/parser/functions/is_numeric.rb
+++ b/lib/puppet/parser/functions/is_numeric.rb
@@ -15,7 +15,7 @@ Returns true if the variable passed to this function is a number.
value = arguments[0]
- if value == value.to_f.to_s or value == value.to_i.to_s then
+ if value == value.to_f.to_s or value == value.to_i.to_s or value.is_a? Numeric then
return true
else
return false
diff --git a/lib/puppet/parser/functions/max.rb b/lib/puppet/parser/functions/max.rb
index 10b6f74..60fb94a 100644
--- a/lib/puppet/parser/functions/max.rb
+++ b/lib/puppet/parser/functions/max.rb
@@ -8,6 +8,14 @@ module Puppet::Parser::Functions
raise(Puppet::ParseError, "max(): Wrong number of arguments " +
"need at least one") if args.size == 0
- return args.max
+ # Sometimes we get numbers as numerics and sometimes as strings.
+ # We try to compare them as numbers when possible
+ return args.max do |a,b|
+ if a.to_s =~ /\A-?\d+(.\d+)?\z/ and b.to_s =~ /\A-?\d+(.\d+)?\z/ then
+ a.to_f <=> b.to_f
+ else
+ a.to_s <=> b.to_s
+ end
+ end
end
end
diff --git a/lib/puppet/parser/functions/merge.rb b/lib/puppet/parser/functions/merge.rb
index 6ec085e..1b39f20 100644
--- a/lib/puppet/parser/functions/merge.rb
+++ b/lib/puppet/parser/functions/merge.rb
@@ -22,6 +22,7 @@ module Puppet::Parser::Functions
accumulator = Hash.new
# Merge into the accumulator hash
args.each do |arg|
+ next if arg.is_a? String and arg.empty? # empty string is synonym for puppet's undef
unless arg.is_a?(Hash)
raise Puppet::ParseError, "merge: unexpected argument type #{arg.class}, only expects hash arguments"
end
diff --git a/lib/puppet/parser/functions/min.rb b/lib/puppet/parser/functions/min.rb
index abf1b62..6bd6ebf 100644
--- a/lib/puppet/parser/functions/min.rb
+++ b/lib/puppet/parser/functions/min.rb
@@ -8,6 +8,14 @@ module Puppet::Parser::Functions
raise(Puppet::ParseError, "min(): Wrong number of arguments " +
"need at least one") if args.size == 0
- return args.min
+ # Sometimes we get numbers as numerics and sometimes as strings.
+ # We try to compare them as numbers when possible
+ return args.min do |a,b|
+ if a.to_s =~ /\A^-?\d+(.\d+)?\z/ and b.to_s =~ /\A-?\d+(.\d+)?\z/ then
+ a.to_f <=> b.to_f
+ else
+ a.to_s <=> b.to_s
+ end
+ end
end
end
diff --git a/lib/puppet/parser/functions/num2bool.rb b/lib/puppet/parser/functions/num2bool.rb
index 874db22..af0e6ed 100644
--- a/lib/puppet/parser/functions/num2bool.rb
+++ b/lib/puppet/parser/functions/num2bool.rb
@@ -2,38 +2,41 @@
# num2bool.rb
#
-# TODO(Krzysztof Wilczynski): We probably need to approach numeric values differently ...
-
module Puppet::Parser::Functions
newfunction(:num2bool, :type => :rvalue, :doc => <<-EOS
-This function converts a number into a true boolean. Zero becomes false. Numbers
-higher then 0 become true.
+This function converts a number or a string representation of a number into a
+true boolean. Zero or anything non-numeric becomes false. Numbers higher then 0
+become true.
EOS
) do |arguments|
raise(Puppet::ParseError, "num2bool(): Wrong number of arguments " +
- "given (#{arguments.size} for 1)") if arguments.size < 1
+ "given (#{arguments.size} for 1)") if arguments.size != 1
number = arguments[0]
- # Only numbers allowed ...
- unless number.match(/^\-?\d+$/)
- raise(Puppet::ParseError, 'num2bool(): Requires integer to work with')
+ case number
+ when Numeric
+ # Yay, it's a number
+ when String
+ begin
+ number = Float(number)
+ rescue ArgumentError => ex
+ raise(Puppet::ParseError, "num2bool(): '#{number}' does not look like a number: #{ex.message}")
+ end
+ else
+ begin
+ number = number.to_s
+ rescue NoMethodError => ex
+ raise(Puppet::ParseError, "num2bool(): Unable to parse argument: #{ex.message}")
+ end
end
- result = case number
- when /^0$/
- false
- when /^\-?\d+$/
- # Numbers in Puppet are often string-encoded which is troublesome ...
- number = number.to_i
- # We yield true for any positive number and false otherwise ...
- number > 0 ? true : false
- else
- raise(Puppet::ParseError, 'num2bool(): Unknown numeric format given')
- end
+ # Truncate Floats
+ number = number.to_i
- return result
+ # Return true for any positive number and false otherwise
+ return number > 0
end
end
diff --git a/lib/puppet/parser/functions/prefix.rb b/lib/puppet/parser/functions/prefix.rb
index 4593976..62211ae 100644
--- a/lib/puppet/parser/functions/prefix.rb
+++ b/lib/puppet/parser/functions/prefix.rb
@@ -6,7 +6,7 @@ module Puppet::Parser::Functions
newfunction(:prefix, :type => :rvalue, :doc => <<-EOS
This function applies a prefix to all elements in an array.
-*Examles:*
+*Examples:*
prefix(['a','b','c'], 'p')
@@ -21,14 +21,14 @@ Will return: ['pa','pb','pc']
array = arguments[0]
unless array.is_a?(Array)
- raise(Puppet::ParseError, 'prefix(): Requires array to work with')
+ raise Puppet::ParseError, "prefix(): expected first argument to be an Array, got #{array.inspect}"
end
prefix = arguments[1] if arguments[1]
if prefix
unless prefix.is_a?(String)
- raise(Puppet::ParseError, 'prefix(): Requires string to work with')
+ raise Puppet::ParseError, "prefix(): expected second argument to be a String, got #{suffix.inspect}"
end
end
diff --git a/lib/puppet/parser/functions/str2bool.rb b/lib/puppet/parser/functions/str2bool.rb
index 0509c2b..fece7a6 100644
--- a/lib/puppet/parser/functions/str2bool.rb
+++ b/lib/puppet/parser/functions/str2bool.rb
@@ -14,6 +14,11 @@ like: 0, f, n, false, no to 'false'.
"given (#{arguments.size} for 1)") if arguments.size < 1
string = arguments[0]
+
+ # If string is already Boolean, return it
+ if !!string == string
+ return string
+ end
unless string.is_a?(String)
raise(Puppet::ParseError, 'str2bool(): Requires either ' +
diff --git a/lib/puppet/parser/functions/suffix.rb b/lib/puppet/parser/functions/suffix.rb
new file mode 100644
index 0000000..f7792d6
--- /dev/null
+++ b/lib/puppet/parser/functions/suffix.rb
@@ -0,0 +1,45 @@
+#
+# suffix.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:suffix, :type => :rvalue, :doc => <<-EOS
+This function applies a suffix to all elements in an array.
+
+*Examples:*
+
+ suffix(['a','b','c'], 'p')
+
+Will return: ['ap','bp','cp']
+ EOS
+ ) do |arguments|
+
+ # Technically we support two arguments but only first is mandatory ...
+ raise(Puppet::ParseError, "suffix(): Wrong number of arguments " +
+ "given (#{arguments.size} for 1)") if arguments.size < 1
+
+ array = arguments[0]
+
+ unless array.is_a?(Array)
+ raise Puppet::ParseError, "suffix(): expected first argument to be an Array, got #{array.inspect}"
+ end
+
+ suffix = arguments[1] if arguments[1]
+
+ if suffix
+ unless suffix.is_a? String
+ raise Puppet::ParseError, "suffix(): expected second argument to be a String, got #{suffix.inspect}"
+ end
+ end
+
+ # Turn everything into string same as join would do ...
+ result = array.collect do |i|
+ i = i.to_s
+ suffix ? i + suffix : i
+ end
+
+ return result
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/union.rb b/lib/puppet/parser/functions/union.rb
new file mode 100644
index 0000000..c91bb80
--- /dev/null
+++ b/lib/puppet/parser/functions/union.rb
@@ -0,0 +1,34 @@
+#
+# union.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:union, :type => :rvalue, :doc => <<-EOS
+This function returns a union of two arrays.
+
+*Examples:*
+
+ union(["a","b","c"],["b","c","d"])
+
+Would return: ["a","b","c","d"]
+ EOS
+ ) do |arguments|
+
+ # Two arguments are required
+ raise(Puppet::ParseError, "union(): Wrong number of arguments " +
+ "given (#{arguments.size} for 2)") if arguments.size != 2
+
+ first = arguments[0]
+ second = arguments[1]
+
+ unless first.is_a?(Array) && second.is_a?(Array)
+ raise(Puppet::ParseError, 'union(): Requires 2 arrays')
+ end
+
+ result = first | second
+
+ return result
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/validate_augeas.rb b/lib/puppet/parser/functions/validate_augeas.rb
new file mode 100644
index 0000000..154d660
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_augeas.rb
@@ -0,0 +1,81 @@
+module Puppet::Parser::Functions
+ newfunction(:validate_augeas, :doc => <<-'ENDHEREDOC') do |args|
+ Perform validation of a string using an Augeas lens
+ The first argument of this function should be a string to
+ test, and the second argument should be the name of the Augeas lens to use.
+ If Augeas fails to parse the string with the lens, the compilation will
+ abort with a parse error.
+
+ A third argument can be specified, listing paths which should
+ not be found in the file. The `$file` variable points to the location
+ of the temporary file being tested in the Augeas tree.
+
+ For example, if you want to make sure your passwd content never contains
+ a user `foo`, you could write:
+
+ validate_augeas($passwdcontent, 'Passwd.lns', ['$file/foo'])
+
+ Or if you wanted to ensure that no users used the '/bin/barsh' shell,
+ you could use:
+
+ validate_augeas($passwdcontent, 'Passwd.lns', ['$file/*[shell="/bin/barsh"]']
+
+ If a fourth argument is specified, this will be the error message raised and
+ seen by the user.
+
+ A helpful error message can be returned like this:
+
+ validate_augeas($sudoerscontent, 'Sudoers.lns', [], 'Failed to validate sudoers content with Augeas')
+
+ ENDHEREDOC
+ unless Puppet.features.augeas?
+ raise Puppet::ParseError, ("validate_augeas(): this function requires the augeas feature. See http://projects.puppetlabs.com/projects/puppet/wiki/Puppet_Augeas#Pre-requisites for how to activate it.")
+ end
+
+ if (args.length < 2) or (args.length > 4) then
+ raise Puppet::ParseError, ("validate_augeas(): wrong number of arguments (#{args.length}; must be 2, 3, or 4)")
+ end
+
+ msg = args[3] || "validate_augeas(): Failed to validate content against #{args[1].inspect}"
+
+ require 'augeas'
+ aug = Augeas::open(nil, nil, Augeas::NO_MODL_AUTOLOAD)
+ begin
+ content = args[0]
+
+ # Test content in a temporary file
+ tmpfile = Tempfile.new("validate_augeas")
+ begin
+ tmpfile.write(content)
+ ensure
+ tmpfile.close
+ end
+
+ # Check for syntax
+ lens = args[1]
+ aug.transform(
+ :lens => lens,
+ :name => 'Validate_augeas',
+ :incl => tmpfile.path
+ )
+ aug.load!
+
+ unless aug.match("/augeas/files#{tmpfile.path}//error").empty?
+ error = aug.get("/augeas/files#{tmpfile.path}//error/message")
+ msg += " with error: #{error}"
+ raise Puppet::ParseError, (msg)
+ end
+
+ # Launch unit tests
+ tests = args[2] || []
+ aug.defvar('file', "/files#{tmpfile.path}")
+ tests.each do |t|
+ msg += " testing path #{t}"
+ raise Puppet::ParseError, (msg) unless aug.match(t).empty?
+ end
+ ensure
+ aug.close
+ tmpfile.unlink
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/validate_cmd.rb b/lib/puppet/parser/functions/validate_cmd.rb
new file mode 100644
index 0000000..344a80c
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_cmd.rb
@@ -0,0 +1,47 @@
+require 'puppet/util/execution'
+
+module Puppet::Parser::Functions
+ newfunction(:validate_cmd, :doc => <<-'ENDHEREDOC') do |args|
+ Perform validation of a string with an external command.
+ The first argument of this function should be a string to
+ test, and the second argument should be a path to a test command
+ taking a file as last argument. If the command, launched against
+ a tempfile containing the passed string, returns a non-null value,
+ compilation will abort with a parse error.
+
+ If a third argument is specified, this will be the error message raised and
+ seen by the user.
+
+ A helpful error message can be returned like this:
+
+ Example:
+
+ validate_cmd($sudoerscontent, '/usr/sbin/visudo -c -f', 'Visudo failed to validate sudoers content')
+
+ ENDHEREDOC
+ if (args.length < 2) or (args.length > 3) then
+ raise Puppet::ParseError, ("validate_cmd(): wrong number of arguments (#{args.length}; must be 2 or 3)")
+ end
+
+ msg = args[2] || "validate_cmd(): failed to validate content with command #{args[1].inspect}"
+
+ content = args[0]
+ checkscript = args[1]
+
+ # Test content in a temporary file
+ tmpfile = Tempfile.new("validate_cmd")
+ begin
+ tmpfile.write(content)
+ if Puppet::Util::Execution.respond_to?('execute')
+ Puppet::Util::Execution.execute("#{checkscript} #{tmpfile.path}")
+ else
+ Puppet::Util.execute("#{checkscript} #{tmpfile.path}")
+ end
+ rescue Puppet::ExecutionFailure => detail
+ msg += "\n#{detail}"
+ raise Puppet::ParseError, msg
+ ensure
+ tmpfile.unlink
+ end
+ end
+end