diff options
author | Jeff McCune <jeff@puppetlabs.com> | 2011-08-08 16:58:14 -0700 |
---|---|---|
committer | Jeff McCune <jeff@puppetlabs.com> | 2011-08-08 16:58:40 -0700 |
commit | 33887f9be50c4fd94bbd08d7c00d9b3d97e29d21 (patch) | |
tree | b7c5b8cd3595b1db0a835f31e551f5baf6b2c0ed /lib/puppet/parser/functions | |
parent | e8fb6917d102d8a45d5682b79f33b1ac0d52d73b (diff) | |
parent | aa27fc76c7d5fa090ea1d47027856c3e70c6ae8f (diff) | |
download | puppet-stdlib-33887f9be50c4fd94bbd08d7c00d9b3d97e29d21.tar.gz puppet-stdlib-33887f9be50c4fd94bbd08d7c00d9b3d97e29d21.tar.bz2 |
Merge branch 'issue/master/8797_puppetlabs-functions_merge'
Closes pull request #12
Reviewed-by: Jeff McCune
Verified all spec tests pass using rspec **/*_spec.rb
* issue/master/8797_puppetlabs-functions_merge: (164 commits)
* Moved kwalify to puppetlabs-kwalify project * Re-arranged tests in line with puppetlabs-stdlib
Prep for stdlib merge * Renamed load_yaml & load_json to parseyaml & parsejson * Renamed is_valid_* functions and remove the 'valid_'
Fix some ruby 1.9.2 issues.
(#3) Provide documentation for remaining functions.
(#3) Apply missing documentation to more functions.
Remove rand.
Some improvements to values_at tests.
(#1) provide some more detailed tests for a number of functions.
Removed date stub since this functinality is available in strftime anyway.
(#2) fix is_string finally so it also makes sure numbers return false.
(#2) unstub is_valid_domain_name
Added doc strings for first five functions
Removed join_with_prefix.
(#2) unstub is_valid_mac_address.
Allow sort for strings.
Count functionality overlaps with size - so removing it.
Removed crontab functions instead of unstubbing them.
Removed load_variables. load_yaml is sufficient to solve this problem on its own.
Remove is_valid_netmask instead of unstubbing. Doesn't seem like a sensible function on its own.
(#2) unstub is_numeric function.
...
Diffstat (limited to 'lib/puppet/parser/functions')
47 files changed, 1865 insertions, 0 deletions
diff --git a/lib/puppet/parser/functions/abs.rb b/lib/puppet/parser/functions/abs.rb new file mode 100644 index 0000000..ade5462 --- /dev/null +++ b/lib/puppet/parser/functions/abs.rb @@ -0,0 +1,36 @@ +# +# abs.rb +# + +module Puppet::Parser::Functions + newfunction(:abs, :type => :rvalue, :doc => <<-EOS + Returns the absolute value of a number, for example -34.56 becomes + 34.56. Takes a single integer and float value as an argument. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "abs(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + + # Numbers in Puppet are often string-encoded which is troublesome ... + if value.is_a?(String) + if value.match(/^-?(?:\d+)(?:\.\d+){1}$/) + value = value.to_f + elsif value.match(/^-?\d+$/) + value = value.to_i + else + raise(Puppet::ParseError, 'abs(): Requires float or ' + + 'integer to work with') + end + end + + # We have numeric value to handle ... + result = value.abs + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/bool2num.rb b/lib/puppet/parser/functions/bool2num.rb new file mode 100644 index 0000000..9a07a8a --- /dev/null +++ b/lib/puppet/parser/functions/bool2num.rb @@ -0,0 +1,49 @@ +# +# bool2num.rb +# + +module Puppet::Parser::Functions + newfunction(:bool2num, :type => :rvalue, :doc => <<-EOS + Converts a boolean to a number. Converts the values: + false, f, 0, n, and no to 0 + true, t, 1, y, and yes to 1 + Requires a single boolean or string as an input. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "bool2num(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + klass = value.class + + # We can have either true or false, or string which resembles boolean ... + unless [FalseClass, TrueClass, String].include?(klass) + raise(Puppet::ParseError, 'bool2num(): Requires either ' + + 'boolean or string to work with') + end + + if value.is_a?(String) + # We consider all the yes, no, y, n and so on too ... + value = case value + # + # This is how undef looks like in Puppet ... + # We yield 0 (or false if you wish) in this case. + # + when /^$/, '' then false # Empty string will be false ... + when /^(1|t|y|true|yes)$/ then true + when /^(0|f|n|false|no)$/ then false + when /^(undef|undefined)$/ then false # This is not likely to happen ... + else + raise(Puppet::ParseError, 'bool2num(): Unknown type of boolean given') + end + end + + # We have real boolean values as well ... + result = value ? 1 : 0 + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/capitalize.rb b/lib/puppet/parser/functions/capitalize.rb new file mode 100644 index 0000000..640d00b --- /dev/null +++ b/lib/puppet/parser/functions/capitalize.rb @@ -0,0 +1,34 @@ +# +# capitalize.rb +# + +module Puppet::Parser::Functions + newfunction(:capitalize, :type => :rvalue, :doc => <<-EOS + Capitalizes the first letter of a string or array of strings. + Requires either a single string or an array as an input. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "capitalize(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + klass = value.class + + unless [Array, String].include?(klass) + raise(Puppet::ParseError, 'capitalize(): Requires either ' + + 'array or string to work with') + end + + if value.is_a?(Array) + # Numbers in Puppet are often string-encoded which is troublesome ... + result = value.collect { |i| i.is_a?(String) ? i.capitalize : i } + else + result = value.capitalize + end + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/chomp.rb b/lib/puppet/parser/functions/chomp.rb new file mode 100644 index 0000000..c99d139 --- /dev/null +++ b/lib/puppet/parser/functions/chomp.rb @@ -0,0 +1,35 @@ +# +# chomp.rb +# + +module Puppet::Parser::Functions + newfunction(:chomp, :type => :rvalue, :doc => <<-'EOS' + Removes the record separator from the end of a string or an array of + strings, for example `hello\n` becomes `hello`. + Requires a single string or array as an input. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "chomp(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + klass = value.class + + unless [Array, String].include?(klass) + raise(Puppet::ParseError, 'chomp(): Requires either ' + + 'array or string to work with') + end + + if value.is_a?(Array) + # Numbers in Puppet are often string-encoded which is troublesome ... + result = value.collect { |i| i.is_a?(String) ? i.chomp : i } + else + result = value.chomp + end + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/chop.rb b/lib/puppet/parser/functions/chop.rb new file mode 100644 index 0000000..636b990 --- /dev/null +++ b/lib/puppet/parser/functions/chop.rb @@ -0,0 +1,37 @@ +# +# chop.rb +# + +module Puppet::Parser::Functions + newfunction(:chop, :type => :rvalue, :doc => <<-'EOS' + Returns a new string with the last character removed. If the string ends + with `\r\n`, both characters are removed. Applying chop to an empty + string returns an empty string. If you wish to merely remove record + separators then you should use the `chomp` function. + Requires a string or array of strings as input. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "chop(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + klass = value.class + + unless [Array, String].include?(klass) + raise(Puppet::ParseError, 'chop(): Requires either an ' + + 'array or string to work with') + end + + if value.is_a?(Array) + # Numbers in Puppet are often string-encoded which is troublesome ... + result = value.collect { |i| i.is_a?(String) ? i.chop : i } + else + result = value.chop + end + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/delete.rb b/lib/puppet/parser/functions/delete.rb new file mode 100644 index 0000000..ab8f75b --- /dev/null +++ b/lib/puppet/parser/functions/delete.rb @@ -0,0 +1,34 @@ +# +# delete.rb +# + +# TODO(Krzysztof Wilczynski): We need to add support for regular expression ... +# TODO(Krzysztof Wilczynski): Support for strings and hashes too ... + +module Puppet::Parser::Functions + newfunction(:delete, :type => :rvalue, :doc => <<-EOS +Deletes a selected element from an array. + +*Examples:* + + delete(['a','b','c'], 'b') + +Would return: ['a','c'] + EOS + ) do |arguments| + + if (arguments.size != 2) then + raise(Puppet::ParseError, "delete(): Wrong number of arguments "+ + "given #{arguments.size} for 2") + end + + a = arguments[0] + item = arguments[1] + + a.delete(item) + a + + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/delete_at.rb b/lib/puppet/parser/functions/delete_at.rb new file mode 100644 index 0000000..3eb4b53 --- /dev/null +++ b/lib/puppet/parser/functions/delete_at.rb @@ -0,0 +1,49 @@ +# +# delete_at.rb +# + +module Puppet::Parser::Functions + newfunction(:delete_at, :type => :rvalue, :doc => <<-EOS +Deletes a determined indexed value from an array. + +*Examples:* + + delete_at(['a','b','c'], 1) + +Would return: ['a','c'] + EOS + ) do |arguments| + + raise(Puppet::ParseError, "delete_at(): Wrong number of arguments " + + "given (#{arguments.size} for 2)") if arguments.size < 2 + + array = arguments[0] + + unless array.is_a?(Array) + raise(Puppet::ParseError, 'delete_at(): Requires array to work with') + end + + index = arguments[1] + + if index.is_a?(String) and not index.match(/^\d+$/) + raise(Puppet::ParseError, 'delete_at(): You must provide ' + + 'non-negative numeric index') + end + + result = array.clone + + # Numbers in Puppet are often string-encoded which is troublesome ... + index = index.to_i + + if index > result.size - 1 # First element is at index 0 is it not? + raise(Puppet::ParseError, 'delete_at(): Given index ' + + 'exceeds size of array given') + end + + result.delete_at(index) # We ignore the element that got deleted ... + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/downcase.rb b/lib/puppet/parser/functions/downcase.rb new file mode 100644 index 0000000..4066d21 --- /dev/null +++ b/lib/puppet/parser/functions/downcase.rb @@ -0,0 +1,33 @@ +# +# downcase.rb +# + +module Puppet::Parser::Functions + newfunction(:downcase, :type => :rvalue, :doc => <<-EOS +Converts the case of a string or all strings in an array to lower case. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "downcase(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + klass = value.class + + unless [Array, String].include?(klass) + raise(Puppet::ParseError, 'downcase(): Requires either ' + + 'array or string to work with') + end + + if value.is_a?(Array) + # Numbers in Puppet are often string-encoded which is troublesome ... + result = value.collect { |i| i.is_a?(String) ? i.downcase : i } + else + result = value.downcase + end + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/empty.rb b/lib/puppet/parser/functions/empty.rb new file mode 100644 index 0000000..80ebb86 --- /dev/null +++ b/lib/puppet/parser/functions/empty.rb @@ -0,0 +1,28 @@ +# +# empty.rb +# + +module Puppet::Parser::Functions + newfunction(:empty, :type => :rvalue, :doc => <<-EOS +Returns true if the variable is empty. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "empty(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + klass = value.class + + unless [Array, Hash, String].include?(klass) + raise(Puppet::ParseError, 'empty(): Requires either ' + + 'array, hash or string to work with') + end + + result = value.empty? + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/flatten.rb b/lib/puppet/parser/functions/flatten.rb new file mode 100644 index 0000000..781da78 --- /dev/null +++ b/lib/puppet/parser/functions/flatten.rb @@ -0,0 +1,33 @@ +# +# flatten.rb +# + +module Puppet::Parser::Functions + newfunction(:flatten, :type => :rvalue, :doc => <<-EOS +This function flattens any deeply nested arrays and returns a single flat array +as a result. + +*Examples:* + + flatten(['a', ['b', ['c']]]) + +Would return: ['a','b','c'] + EOS + ) do |arguments| + + raise(Puppet::ParseError, "flatten(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + array = arguments[0] + + unless array.is_a?(Array) + raise(Puppet::ParseError, 'flatten(): Requires array to work with') + end + + result = array.flatten + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/grep.rb b/lib/puppet/parser/functions/grep.rb new file mode 100644 index 0000000..ceba9ec --- /dev/null +++ b/lib/puppet/parser/functions/grep.rb @@ -0,0 +1,33 @@ +# +# grep.rb +# + +module Puppet::Parser::Functions + newfunction(:grep, :type => :rvalue, :doc => <<-EOS +This function searches through an array and returns any elements that match +the provided regular expression. + +*Examples:* + + grep(['aaa','bbb','ccc','aaaddd'], 'aaa') + +Would return: + + ['aaa','aaaddd'] + EOS + ) do |arguments| + + if (arguments.size != 2) then + raise(Puppet::ParseError, "grep(): Wrong number of arguments "+ + "given #{arguments.size} for 2") + end + + a = arguments[0] + pattern = Regexp.new(arguments[1]) + + a.grep(pattern) + + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/hash.rb b/lib/puppet/parser/functions/hash.rb new file mode 100644 index 0000000..453ba1e --- /dev/null +++ b/lib/puppet/parser/functions/hash.rb @@ -0,0 +1,41 @@ +# +# hash.rb +# + +module Puppet::Parser::Functions + newfunction(:hash, :type => :rvalue, :doc => <<-EOS +This function converts and array into a hash. + +*Examples:* + + hash(['a',1,'b',2,'c',3]) + +Would return: {'a'=>1,'b'=>2,'c'=>3} + EOS + ) do |arguments| + + raise(Puppet::ParseError, "hash(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + array = arguments[0] + + unless array.is_a?(Array) + raise(Puppet::ParseError, 'hash(): Requires array to work with') + end + + result = {} + + begin + # This is to make it compatible with older version of Ruby ... + array = array.flatten + result = Hash[*array] + rescue Exception + raise(Puppet::ParseError, 'hash(): Unable to compute ' + + 'hash from array given') + end + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/is_array.rb b/lib/puppet/parser/functions/is_array.rb new file mode 100644 index 0000000..b39e184 --- /dev/null +++ b/lib/puppet/parser/functions/is_array.rb @@ -0,0 +1,22 @@ +# +# is_array.rb +# + +module Puppet::Parser::Functions + newfunction(:is_array, :type => :rvalue, :doc => <<-EOS +Returns true if the variable passed to this function is an array. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "is_array(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + type = arguments[0] + + result = type.is_a?(Array) + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/is_domain_name.rb b/lib/puppet/parser/functions/is_domain_name.rb new file mode 100644 index 0000000..4e92939 --- /dev/null +++ b/lib/puppet/parser/functions/is_domain_name.rb @@ -0,0 +1,27 @@ +# +# is_domain_name.rb +# + +module Puppet::Parser::Functions + newfunction(:is_domain_name, :type => :rvalue, :doc => <<-EOS +Returns true if the string passed to this function is a valid IP address. Support for IPv4 and IPv6 address types is included. + EOS + ) do |arguments| + + if (arguments.size != 1) then + raise(Puppet::ParseError, "is_domain_name(): Wrong number of arguments "+ + "given #{arguments.size} for 1") + end + + domain = arguments[0] + + if domain =~ /^(([a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])\.?$/ then + return true + else + return false + end + + 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 new file mode 100644 index 0000000..2fc05ba --- /dev/null +++ b/lib/puppet/parser/functions/is_float.rb @@ -0,0 +1,27 @@ +# +# is_float.rb +# + +module Puppet::Parser::Functions + newfunction(:is_float, :type => :rvalue, :doc => <<-EOS +Returns true if the variable passed to this function is a float. + EOS + ) do |arguments| + + if (arguments.size != 1) then + raise(Puppet::ParseError, "is_float(): Wrong number of arguments "+ + "given #{arguments.size} for 1") + end + + value = arguments[0] + + if value != value.to_f.to_s then + return false + else + return true + end + + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/is_hash.rb b/lib/puppet/parser/functions/is_hash.rb new file mode 100644 index 0000000..ad907f0 --- /dev/null +++ b/lib/puppet/parser/functions/is_hash.rb @@ -0,0 +1,22 @@ +# +# is_hash.rb +# + +module Puppet::Parser::Functions + newfunction(:is_hash, :type => :rvalue, :doc => <<-EOS +Returns true if the variable passed to this function is a hash. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "is_hash(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size != 1 + + type = arguments[0] + + result = type.is_a?(Hash) + + return result + 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 new file mode 100644 index 0000000..8ee34f6 --- /dev/null +++ b/lib/puppet/parser/functions/is_integer.rb @@ -0,0 +1,27 @@ +# +# is_integer.rb +# + +module Puppet::Parser::Functions + newfunction(:is_integer, :type => :rvalue, :doc => <<-EOS +Returns true if the variable returned to this string is an integer. + EOS + ) do |arguments| + + if (arguments.size != 1) then + raise(Puppet::ParseError, "is_integer(): Wrong number of arguments "+ + "given #{arguments.size} for 1") + end + + value = arguments[0] + + if value != value.to_i.to_s then + return false + else + return true + end + + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/is_ip_address.rb b/lib/puppet/parser/functions/is_ip_address.rb new file mode 100644 index 0000000..b4a9a15 --- /dev/null +++ b/lib/puppet/parser/functions/is_ip_address.rb @@ -0,0 +1,32 @@ +# +# is_ip_address.rb +# + +module Puppet::Parser::Functions + newfunction(:is_ip_address, :type => :rvalue, :doc => <<-EOS +Returns true if the string passed to this function is a valid IP address. + EOS + ) do |arguments| + + require 'ipaddr' + + if (arguments.size != 1) then + raise(Puppet::ParseError, "is_ip_address(): Wrong number of arguments "+ + "given #{arguments.size} for 1") + end + + begin + ip = IPAddr.new(arguments[0]) + rescue ArgumentError + return false + end + + if ip.ipv4? or ip.ipv6? then + return true + else + return false + end + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/is_mac_address.rb b/lib/puppet/parser/functions/is_mac_address.rb new file mode 100644 index 0000000..1b3088a --- /dev/null +++ b/lib/puppet/parser/functions/is_mac_address.rb @@ -0,0 +1,27 @@ +# +# is_mac_address.rb +# + +module Puppet::Parser::Functions + newfunction(:is_mac_address, :type => :rvalue, :doc => <<-EOS +Returns true if the string passed to this function is a valid mac address. + EOS + ) do |arguments| + + if (arguments.size != 1) then + raise(Puppet::ParseError, "is_mac_address(): Wrong number of arguments "+ + "given #{arguments.size} for 1") + end + + mac = arguments[0] + + if /^[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}$/.match(mac) then + return true + else + return false + end + + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/is_numeric.rb b/lib/puppet/parser/functions/is_numeric.rb new file mode 100644 index 0000000..ce13ece --- /dev/null +++ b/lib/puppet/parser/functions/is_numeric.rb @@ -0,0 +1,27 @@ +# +# is_numeric.rb +# + +module Puppet::Parser::Functions + newfunction(:is_numeric, :type => :rvalue, :doc => <<-EOS +Returns true if the variable passed to this function is a number. + EOS + ) do |arguments| + + if (arguments.size != 1) then + raise(Puppet::ParseError, "is_numeric(): Wrong number of arguments "+ + "given #{arguments.size} for 1") + end + + value = arguments[0] + + if value == value.to_f.to_s or value == value.to_i.to_s then + return true + else + return false + end + + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/is_string.rb b/lib/puppet/parser/functions/is_string.rb new file mode 100644 index 0000000..f5bef04 --- /dev/null +++ b/lib/puppet/parser/functions/is_string.rb @@ -0,0 +1,26 @@ +# +# is_string.rb +# + +module Puppet::Parser::Functions + newfunction(:is_string, :type => :rvalue, :doc => <<-EOS +Returns true if the variable passed to this function is a string. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "is_string(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + type = arguments[0] + + result = type.is_a?(String) + + if result and (type == type.to_f.to_s or type == type.to_i.to_s) then + return false + end + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/join.rb b/lib/puppet/parser/functions/join.rb new file mode 100644 index 0000000..005a46e --- /dev/null +++ b/lib/puppet/parser/functions/join.rb @@ -0,0 +1,41 @@ +# +# join.rb +# + +module Puppet::Parser::Functions + newfunction(:join, :type => :rvalue, :doc => <<-EOS +This function joins an array into a string using a seperator. + +*Examples:* + + join(['a','b','c'], ",") + +Would result in: "a,b,c" + EOS + ) do |arguments| + + # Technically we support two arguments but only first is mandatory ... + raise(Puppet::ParseError, "join(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + array = arguments[0] + + unless array.is_a?(Array) + raise(Puppet::ParseError, 'join(): Requires array to work with') + end + + suffix = arguments[1] if arguments[1] + + if suffix + unless suffix.is_a?(String) + raise(Puppet::ParseError, 'join(): Requires string to work with') + end + end + + result = suffix ? array.join(suffix) : array.join + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/keys.rb b/lib/puppet/parser/functions/keys.rb new file mode 100644 index 0000000..f0d13b6 --- /dev/null +++ b/lib/puppet/parser/functions/keys.rb @@ -0,0 +1,26 @@ +# +# keys.rb +# + +module Puppet::Parser::Functions + newfunction(:keys, :type => :rvalue, :doc => <<-EOS +Returns the keys of a hash as an array. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "keys(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + hash = arguments[0] + + unless hash.is_a?(Hash) + raise(Puppet::ParseError, 'keys(): Requires hash to work with') + end + + result = hash.keys + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/lstrip.rb b/lib/puppet/parser/functions/lstrip.rb new file mode 100644 index 0000000..3a64de3 --- /dev/null +++ b/lib/puppet/parser/functions/lstrip.rb @@ -0,0 +1,33 @@ +# +# lstrip.rb +# + +module Puppet::Parser::Functions + newfunction(:lstrip, :type => :rvalue, :doc => <<-EOS +Strips leading spaces to the left of a string. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "lstrip(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + klass = value.class + + unless [Array, String].include?(klass) + raise(Puppet::ParseError, 'lstrip(): Requires either ' + + 'array or string to work with') + end + + if value.is_a?(Array) + # Numbers in Puppet are often string-encoded which is troublesome ... + result = value.collect { |i| i.is_a?(String) ? i.lstrip : i } + else + result = value.lstrip + end + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/member.rb b/lib/puppet/parser/functions/member.rb new file mode 100644 index 0000000..43d76af --- /dev/null +++ b/lib/puppet/parser/functions/member.rb @@ -0,0 +1,44 @@ +# +# member.rb +# + +# TODO(Krzysztof Wilczynski): We need to add support for regular expression ... +# TODO(Krzysztof Wilczynski): Support for strings and hashes too ... + +module Puppet::Parser::Functions + newfunction(:member, :type => :rvalue, :doc => <<-EOS +This function determines if a variable is a member of an array. + +*Examples:* + + member(['a','b'], 'b') + +Would return: true + + member(['a','b'], 'c') + +Would return: false + EOS + ) do |arguments| + + raise(Puppet::ParseError, "member(): Wrong number of arguments " + + "given (#{arguments.size} for 2)") if arguments.size < 2 + + array = arguments[0] + + unless array.is_a?(Array) + raise(Puppet::ParseError, 'member(): Requires array to work with') + end + + item = arguments[1] + + raise(Puppet::ParseError, 'member(): You must provide item ' + + 'to search for within array given') if item.empty? + + result = array.include?(item) + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/num2bool.rb b/lib/puppet/parser/functions/num2bool.rb new file mode 100644 index 0000000..874db22 --- /dev/null +++ b/lib/puppet/parser/functions/num2bool.rb @@ -0,0 +1,40 @@ +# +# 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. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "num2bool(): Wrong number of arguments " + + "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') + 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 + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/parsejson.rb b/lib/puppet/parser/functions/parsejson.rb new file mode 100644 index 0000000..cf3b12c --- /dev/null +++ b/lib/puppet/parser/functions/parsejson.rb @@ -0,0 +1,26 @@ +# +# parsejson.rb +# + +module Puppet::Parser::Functions + newfunction(:parsejson, :type => :rvalue, :doc => <<-EOS +This function accepts JSON as a string and converts into the correct Puppet +structure. + EOS + ) do |arguments| + + if (arguments.size != 1) then + raise(Puppet::ParseError, "parsejson(): Wrong number of arguments "+ + "given #{arguments.size} for 1") + end + + json = arguments[0] + + require 'json' + + JSON.load(json) + + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/parseyaml.rb b/lib/puppet/parser/functions/parseyaml.rb new file mode 100644 index 0000000..e8ac8a4 --- /dev/null +++ b/lib/puppet/parser/functions/parseyaml.rb @@ -0,0 +1,24 @@ +# +# parseyaml.rb +# + +module Puppet::Parser::Functions + newfunction(:parseyaml, :type => :rvalue, :doc => <<-EOS +This function accepts YAML as a string and converts it into the correct +Puppet structure. + EOS + ) do |arguments| + + if (arguments.size != 1) then + raise(Puppet::ParseError, "parseyaml(): Wrong number of arguments "+ + "given #{arguments.size} for 1") + end + + require 'yaml' + + YAML::load(arguments[0]) + + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/prefix.rb b/lib/puppet/parser/functions/prefix.rb new file mode 100644 index 0000000..4593976 --- /dev/null +++ b/lib/puppet/parser/functions/prefix.rb @@ -0,0 +1,45 @@ +# +# prefix.rb +# + +module Puppet::Parser::Functions + newfunction(:prefix, :type => :rvalue, :doc => <<-EOS +This function applies a prefix to all elements in an array. + +*Examles:* + + prefix(['a','b','c'], 'p') + +Will return: ['pa','pb','pc'] + EOS + ) do |arguments| + + # Technically we support two arguments but only first is mandatory ... + raise(Puppet::ParseError, "prefix(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + array = arguments[0] + + unless array.is_a?(Array) + raise(Puppet::ParseError, 'prefix(): Requires array to work with') + end + + prefix = arguments[1] if arguments[1] + + if prefix + unless prefix.is_a?(String) + raise(Puppet::ParseError, 'prefix(): Requires string to work with') + end + end + + # Turn everything into string same as join would do ... + result = array.collect do |i| + i = i.to_s + prefix ? prefix + i : i + end + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/range.rb b/lib/puppet/parser/functions/range.rb new file mode 100644 index 0000000..6e85422 --- /dev/null +++ b/lib/puppet/parser/functions/range.rb @@ -0,0 +1,71 @@ +# +# range.rb +# + +# TODO(Krzysztof Wilczynski): We probably need to approach numeric values differently ... + +module Puppet::Parser::Functions + newfunction(:range, :type => :rvalue, :doc => <<-EOS +When given range in the form of (start, stop) it will extrapolate a range as +an array. + +*Examples:* + + range("0", "9") + +Will return: [0,1,2,3,4,5,6,7,8,9] + + range("a", "c") + +Will return: ["a","b","c"] + EOS + ) do |arguments| + + # We support more than one argument but at least one is mandatory ... + raise(Puppet::ParseError, "range(): Wrong number of " + + "arguments given (#{arguments.size} for 1)") if arguments.size < 1 + + if arguments.size > 1 + start = arguments[0] + stop = arguments[1] + + type = '..' # We select simplest type for Range available in Ruby ... + + elsif arguments.size > 0 + value = arguments[0] + + if m = value.match(/^(\w+)(\.\.\.?|\-)(\w+)$/) + start = m[1] + stop = m[3] + + type = m[2] + + elsif value.match(/^.+$/) + raise(Puppet::ParseError, 'range(): Unable to compute range ' + + 'from the value given') + else + raise(Puppet::ParseError, 'range(): Unknown format of range given') + end + end + + # Check whether we have integer value if so then make it so ... + if start.match(/^\d+$/) + start = start.to_i + stop = stop.to_i + else + start = start.to_s + stop = stop.to_s + end + + range = case type + when /^(\.\.|\-)$/ then (start .. stop) + when /^(\.\.\.)$/ then (start ... stop) # Exclusive of last element ... + end + + result = range.collect { |i| i } # Get them all ... Pokemon ... + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/reverse.rb b/lib/puppet/parser/functions/reverse.rb new file mode 100644 index 0000000..fe04869 --- /dev/null +++ b/lib/puppet/parser/functions/reverse.rb @@ -0,0 +1,28 @@ +# +# reverse.rb +# + +module Puppet::Parser::Functions + newfunction(:reverse, :type => :rvalue, :doc => <<-EOS +Reverses the order of a string or array. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "reverse(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + klass = value.class + + unless [Array, String].include?(klass) + raise(Puppet::ParseError, 'reverse(): Requires either ' + + 'array or string to work with') + end + + result = value.reverse + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/rstrip.rb b/lib/puppet/parser/functions/rstrip.rb new file mode 100644 index 0000000..29b0998 --- /dev/null +++ b/lib/puppet/parser/functions/rstrip.rb @@ -0,0 +1,32 @@ +# +# rstrip.rb +# + +module Puppet::Parser::Functions + newfunction(:rstrip, :type => :rvalue, :doc => <<-EOS +Strips leading spaces to the right of the string. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "rstrip(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + klass = value.class + + unless [Array, String].include?(klass) + raise(Puppet::ParseError, 'rstrip(): Requires either ' + + 'array or string to work with') + end + + if value.is_a?(Array) + result = value.collect { |i| i.is_a?(String) ? i.rstrip : i } + else + result = value.rstrip + end + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/shuffle.rb b/lib/puppet/parser/functions/shuffle.rb new file mode 100644 index 0000000..18134ab --- /dev/null +++ b/lib/puppet/parser/functions/shuffle.rb @@ -0,0 +1,46 @@ +# +# shuffle.rb +# + +module Puppet::Parser::Functions + newfunction(:shuffle, :type => :rvalue, :doc => <<-EOS +Randomizes the order of a string or array elements. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "shuffle(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + klass = value.class + + unless [Array, String].include?(klass) + raise(Puppet::ParseError, 'shuffle(): Requires either ' + + 'array or string to work with') + end + + result = value.clone + + string = value.is_a?(String) ? true : false + + # Check whether it makes sense to shuffle ... + return result if result.size <= 1 + + # We turn any string value into an array to be able to shuffle ... + result = string ? result.split('') : result + + elements = result.size + + # Simple implementation of Fisher–Yates in-place shuffle ... + elements.times do |i| + j = rand(elements - i) + i + result[j], result[i] = result[i], result[j] + end + + result = string ? result.join : result + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/size.rb b/lib/puppet/parser/functions/size.rb new file mode 100644 index 0000000..cc207e3 --- /dev/null +++ b/lib/puppet/parser/functions/size.rb @@ -0,0 +1,48 @@ +# +# size.rb +# + +# TODO(Krzysztof Wilczynski): Support for hashes would be nice too ... + +module Puppet::Parser::Functions + newfunction(:size, :type => :rvalue, :doc => <<-EOS +Returns the number of elements in a string or array. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "size(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + item = arguments[0] + + if item.is_a?(String) + + begin + # + # Check whether your item is a numeric value or not ... + # This will take care about positive and/or negative numbers + # for both integer and floating-point values ... + # + # Please note that Puppet has no notion of hexadecimal + # nor octal numbers for its DSL at this point in time ... + # + Float(item) + + raise(Puppet::ParseError, 'size(): Requires either ' + + 'string or array to work with') + + rescue ArgumentError + result = item.size + end + + elsif item.is_a?(Array) + result = item.size + else + raise(Puppet::ParseError, 'size(): Unknown type given') + end + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/sort.rb b/lib/puppet/parser/functions/sort.rb new file mode 100644 index 0000000..cefbe54 --- /dev/null +++ b/lib/puppet/parser/functions/sort.rb @@ -0,0 +1,27 @@ +# +# sort.rb +# + +module Puppet::Parser::Functions + newfunction(:sort, :type => :rvalue, :doc => <<-EOS +Sorts strings and arrays lexically. + EOS + ) do |arguments| + + if (arguments.size != 1) then + raise(Puppet::ParseError, "sort(): Wrong number of arguments "+ + "given #{arguments.size} for 1") + end + + value = arguments[0] + + if value.is_a?(Array) then + value.sort + elsif value.is_a?(String) then + value.split("").sort.join("") + end + + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/squeeze.rb b/lib/puppet/parser/functions/squeeze.rb new file mode 100644 index 0000000..65c174a --- /dev/null +++ b/lib/puppet/parser/functions/squeeze.rb @@ -0,0 +1,36 @@ +# +# squeeze.rb +# + +module Puppet::Parser::Functions + newfunction(:squeeze, :type => :rvalue, :doc => <<-EOS +Returns a new string where runs of the same character that occur in this set are replaced by a single character. + EOS + ) do |arguments| + + if ((arguments.size != 2) and (arguments.size != 1)) then + raise(Puppet::ParseError, "squeeze(): Wrong number of arguments "+ + "given #{arguments.size} for 2 or 1") + end + + item = arguments[0] + squeezeval = arguments[1] + + if item.is_a?(Array) then + if squeezeval then + item.collect { |i| i.squeeze(squeezeval) } + else + item.collect { |i| i.squeeze } + end + else + if squeezeval then + item.squeeze(squeezeval) + else + item.squeeze + end + end + + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/str2bool.rb b/lib/puppet/parser/functions/str2bool.rb new file mode 100644 index 0000000..c320da6 --- /dev/null +++ b/lib/puppet/parser/functions/str2bool.rb @@ -0,0 +1,41 @@ +# +# str2bool.rb +# + +module Puppet::Parser::Functions + newfunction(:str2bool, :type => :rvalue, :doc => <<-EOS +This converts a string to a boolean. This attempt to convert strings that +contain things like: y, 1, t, true to 'true' and strings that contain things +like: 0, f, n, false, no to 'false'. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "str2bool(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + string = arguments[0] + + unless string.is_a?(String) + raise(Puppet::ParseError, 'str2bool(): Requires either ' + + 'string to work with') + end + + # We consider all the yes, no, y, n and so on too ... + result = case string + # + # This is how undef looks like in Puppet ... + # We yield false in this case. + # + when /^$/, '' then false # Empty string will be false ... + when /^(1|t|y|true|yes)$/ then true + when /^(0|f|n|false|no)$/ then false + when /^(undef|undefined)$/ then false # This is not likely to happen ... + else + raise(Puppet::ParseError, 'str2bool(): Unknown type of boolean given') + end + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/strftime.rb b/lib/puppet/parser/functions/strftime.rb new file mode 100644 index 0000000..0b52ade --- /dev/null +++ b/lib/puppet/parser/functions/strftime.rb @@ -0,0 +1,107 @@ +# +# strftime.rb +# + +module Puppet::Parser::Functions + newfunction(:strftime, :type => :rvalue, :doc => <<-EOS +This function returns formatted time. + +*Examples:* + +To return the time since epoch: + + strftime("%s") + +To return the date: + + strftime("%Y-%m-%d") + +*Format meaning:* + + %a - The abbreviated weekday name (``Sun'') + %A - The full weekday name (``Sunday'') + %b - The abbreviated month name (``Jan'') + %B - The full month name (``January'') + %c - The preferred local date and time representation + %C - Century (20 in 2009) + %d - Day of the month (01..31) + %D - Date (%m/%d/%y) + %e - Day of the month, blank-padded ( 1..31) + %F - Equivalent to %Y-%m-%d (the ISO 8601 date format) + %h - Equivalent to %b + %H - Hour of the day, 24-hour clock (00..23) + %I - Hour of the day, 12-hour clock (01..12) + %j - Day of the year (001..366) + %k - hour, 24-hour clock, blank-padded ( 0..23) + %l - hour, 12-hour clock, blank-padded ( 0..12) + %L - Millisecond of the second (000..999) + %m - Month of the year (01..12) + %M - Minute of the hour (00..59) + %n - Newline (\n) + %N - Fractional seconds digits, default is 9 digits (nanosecond) + %3N millisecond (3 digits) + %6N microsecond (6 digits) + %9N nanosecond (9 digits) + %p - Meridian indicator (``AM'' or ``PM'') + %P - Meridian indicator (``am'' or ``pm'') + %r - time, 12-hour (same as %I:%M:%S %p) + %R - time, 24-hour (%H:%M) + %s - Number of seconds since 1970-01-01 00:00:00 UTC. + %S - Second of the minute (00..60) + %t - Tab character (\t) + %T - time, 24-hour (%H:%M:%S) + %u - Day of the week as a decimal, Monday being 1. (1..7) + %U - Week number of the current year, + starting with the first Sunday as the first + day of the first week (00..53) + %v - VMS date (%e-%b-%Y) + %V - Week number of year according to ISO 8601 (01..53) + %W - Week number of the current year, + starting with the first Monday as the first + day of the first week (00..53) + %w - Day of the week (Sunday is 0, 0..6) + %x - Preferred representation for the date alone, no time + %X - Preferred representation for the time alone, no date + %y - Year without a century (00..99) + %Y - Year with century + %z - Time zone as hour offset from UTC (e.g. +0900) + %Z - Time zone name + %% - Literal ``%'' character + EOS + ) do |arguments| + + # Technically we support two arguments but only first is mandatory ... + raise(Puppet::ParseError, "strftime(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + format = arguments[0] + + raise(Puppet::ParseError, 'strftime(): You must provide ' + + 'format for evaluation') if format.empty? + + # The Time Zone argument is optional ... + time_zone = arguments[1] if arguments[1] + + time = Time.new + + # There is probably a better way to handle Time Zone ... + if time_zone and not time_zone.empty? + original_zone = ENV['TZ'] + + local_time = time.clone + local_time = local_time.utc + + ENV['TZ'] = time_zone + + time = local_time.localtime + + ENV['TZ'] = original_zone + end + + result = time.strftime(format) + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/strip.rb b/lib/puppet/parser/functions/strip.rb new file mode 100644 index 0000000..5f4630d --- /dev/null +++ b/lib/puppet/parser/functions/strip.rb @@ -0,0 +1,39 @@ +# +# strip.rb +# + +module Puppet::Parser::Functions + newfunction(:strip, :type => :rvalue, :doc => <<-EOS +This function removes leading and trailing whitespace from a string or from +every string inside an array. + +*Examples:* + + strip(" aaa ") + +Would result in: "aaa" + EOS + ) do |arguments| + + raise(Puppet::ParseError, "strip(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + klass = value.class + + unless [Array, String].include?(klass) + raise(Puppet::ParseError, 'strip(): Requires either ' + + 'array or string to work with') + end + + if value.is_a?(Array) + result = value.collect { |i| i.is_a?(String) ? i.strip : i } + else + result = value.strip + end + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/swapcase.rb b/lib/puppet/parser/functions/swapcase.rb new file mode 100644 index 0000000..b9e6632 --- /dev/null +++ b/lib/puppet/parser/functions/swapcase.rb @@ -0,0 +1,39 @@ +# +# swapcase.rb +# + +module Puppet::Parser::Functions + newfunction(:swapcase, :type => :rvalue, :doc => <<-EOS +This function will swap the existing case of a string. + +*Examples:* + + swapcase("aBcD") + +Would result in: "AbCd" + EOS + ) do |arguments| + + raise(Puppet::ParseError, "swapcase(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + klass = value.class + + unless [Array, String].include?(klass) + raise(Puppet::ParseError, 'swapcase(): Requires either ' + + 'array or string to work with') + end + + if value.is_a?(Array) + # Numbers in Puppet are often string-encoded which is troublesome ... + result = value.collect { |i| i.is_a?(String) ? i.swapcase : i } + else + result = value.swapcase + end + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/time.rb b/lib/puppet/parser/functions/time.rb new file mode 100644 index 0000000..0cddaf8 --- /dev/null +++ b/lib/puppet/parser/functions/time.rb @@ -0,0 +1,49 @@ +# +# time.rb +# + +module Puppet::Parser::Functions + newfunction(:time, :type => :rvalue, :doc => <<-EOS +This function will return the current time since epoch as an integer. + +*Examples:* + + time() + +Will return something like: 1311972653 + EOS + ) do |arguments| + + # The Time Zone argument is optional ... + time_zone = arguments[0] if arguments[0] + + if (arguments.size != 0) and (arguments.size != 1) then + raise(Puppet::ParseError, "time(): Wrong number of arguments "+ + "given #{arguments.size} for 0 or 1") + end + + time = Time.new + + # There is probably a better way to handle Time Zone ... + if time_zone and not time_zone.empty? + original_zone = ENV['TZ'] + + local_time = time.clone + local_time = local_time.utc + + ENV['TZ'] = time_zone + + time = local_time.localtime + + ENV['TZ'] = original_zone + end + + # Calling Time#to_i on a receiver changes it. Trust me I am the Doctor. + result = time.strftime('%s') + result = result.to_i + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/type.rb b/lib/puppet/parser/functions/type.rb new file mode 100644 index 0000000..8d85f11 --- /dev/null +++ b/lib/puppet/parser/functions/type.rb @@ -0,0 +1,50 @@ +# +# type.rb +# + +module Puppet::Parser::Functions + newfunction(:type, :type => :rvalue, :doc => <<-EOS +Returns the type when passed a variable. Type can be one of: + +* string +* array +* hash +* float +* integer +* boolean + EOS + ) do |arguments| + + raise(Puppet::ParseError, "type(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + + klass = value.class + + if not [TrueClass, FalseClass, Array, Bignum, Fixnum, Float, Hash, String].include?(klass) + raise(Puppet::ParseError, 'type(): Unknown type') + end + + klass = klass.to_s # Ugly ... + + # We note that Integer is the parent to Bignum and Fixnum ... + result = case klass + when /^(?:Big|Fix)num$/ then 'integer' + when /^(?:True|False)Class$/ then 'boolean' + else klass + end + + if result == "String" then + if value == value.to_i.to_s then + result = "Integer" + elsif value == value.to_f.to_s then + result = "Float" + end + end + + return result.downcase + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/unique.rb b/lib/puppet/parser/functions/unique.rb new file mode 100644 index 0000000..8844a74 --- /dev/null +++ b/lib/puppet/parser/functions/unique.rb @@ -0,0 +1,51 @@ +# +# unique.rb +# + +module Puppet::Parser::Functions + newfunction(:unique, :type => :rvalue, :doc => <<-EOS +This function will remove duplicates from strings and arrays. + +*Examples:* + + unique("aabbcc") + +Will return: + + abc + +You can also use this with arrays: + + unique(["a","a","b","b","c","c"]) + +This returns: + + ["a","b","c"] + EOS + ) do |arguments| + + raise(Puppet::ParseError, "unique(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + klass = value.class + + unless [Array, String].include?(klass) + raise(Puppet::ParseError, 'unique(): Requires either ' + + 'array or string to work with') + end + + result = value.clone + + string = value.is_a?(String) ? true : false + + # We turn any string value into an array to be able to shuffle ... + result = string ? result.split('') : result + result = result.uniq # Remove duplicates ... + result = string ? result.join : result + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/upcase.rb b/lib/puppet/parser/functions/upcase.rb new file mode 100644 index 0000000..fe6cadc --- /dev/null +++ b/lib/puppet/parser/functions/upcase.rb @@ -0,0 +1,41 @@ +# +# upcase.rb +# + +module Puppet::Parser::Functions + newfunction(:upcase, :type => :rvalue, :doc => <<-EOS +Converts a string or an array of strings to uppercase. + +*Examples:* + + upcase("abcd") + +Will return: + + ASDF + EOS + ) do |arguments| + + raise(Puppet::ParseError, "upcase(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + value = arguments[0] + klass = value.class + + unless [Array, String].include?(klass) + raise(Puppet::ParseError, 'upcase(): Requires either ' + + 'array or string to work with') + end + + if value.is_a?(Array) + # Numbers in Puppet are often string-encoded which is troublesome ... + result = value.collect { |i| i.is_a?(String) ? i.upcase : i } + else + result = value.upcase + end + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/values.rb b/lib/puppet/parser/functions/values.rb new file mode 100644 index 0000000..1606756 --- /dev/null +++ b/lib/puppet/parser/functions/values.rb @@ -0,0 +1,39 @@ +# +# values.rb +# + +module Puppet::Parser::Functions + newfunction(:values, :type => :rvalue, :doc => <<-EOS +When given a hash this function will return the values of that hash. + +*Examples:* + + $hash = { + 'a' => 1, + 'b' => 2, + 'c' => 3, + } + values($hash) + +This example would return: + + [1,2,3] + EOS + ) do |arguments| + + raise(Puppet::ParseError, "values(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + hash = arguments[0] + + unless hash.is_a?(Hash) + raise(Puppet::ParseError, 'values(): Requires hash to work with') + end + + result = hash.values + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/values_at.rb b/lib/puppet/parser/functions/values_at.rb new file mode 100644 index 0000000..d3e69d9 --- /dev/null +++ b/lib/puppet/parser/functions/values_at.rb @@ -0,0 +1,98 @@ +# +# values_at.rb +# + +module Puppet::Parser::Functions + newfunction(:values_at, :type => :rvalue, :doc => <<-EOS +Finds value inside an array based on location. + +The first argument is the array you want to analyze, and the second element can +be a combination of: + +* A single numeric index +* A range in the form of 'start-stop' (eg. 4-9) +* An array combining the above + +*Examples*: + + values_at(['a','b','c'], 2) + +Would return ['c']. + + values_at(['a','b','c'], ["0-1"]) + +Would return ['a','b']. + + values_at(['a','b','c','d','e'], [0, "2-3"]) + +Would return ['a','c','d']. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "values_at(): Wrong number of " + + "arguments given (#{arguments.size} for 2)") if arguments.size < 2 + + array = arguments.shift + + unless array.is_a?(Array) + raise(Puppet::ParseError, 'values_at(): Requires array to work with') + end + + indices = [arguments.shift].flatten() # Get them all ... Pokemon ... + + if not indices or indices.empty? + raise(Puppet::ParseError, 'values_at(): You must provide ' + + 'at least one positive index to collect') + end + + result = [] + indices_list = [] + + indices.each do |i| + if m = i.match(/^(\d+)(\.\.\.?|\-)(\d+)$/) + start = m[1].to_i + stop = m[3].to_i + + type = m[2] + + if start > stop + raise(Puppet::ParseError, 'values_at(): Stop index in ' + + 'given indices range is smaller than the start index') + elsif stop > array.size - 1 # First element is at index 0 is it not? + raise(Puppet::ParseError, 'values_at(): Stop index in ' + + 'given indices range exceeds array size') + end + + range = case type + when /^(\.\.|\-)$/ then (start .. stop) + when /^(\.\.\.)$/ then (start ... stop) # Exclusive of last element ... + end + + range.each { |i| indices_list << i.to_i } + else + # Only positive numbers allowed in this case ... + if not i.match(/^\d+$/) + raise(Puppet::ParseError, 'values_at(): Unknown format ' + + 'of given index') + end + + # In Puppet numbers are often string-encoded ... + i = i.to_i + + if i > array.size - 1 # Same story. First element is at index 0 ... + raise(Puppet::ParseError, 'values_at(): Given index ' + + 'exceeds array size') + end + + indices_list << i + end + end + + # We remove nil values as they make no sense in Puppet DSL ... + result = indices_list.collect { |i| array[i] }.compact + + return result + end +end + +# vim: set ts=2 sw=2 et : diff --git a/lib/puppet/parser/functions/zip.rb b/lib/puppet/parser/functions/zip.rb new file mode 100644 index 0000000..2b56e9c --- /dev/null +++ b/lib/puppet/parser/functions/zip.rb @@ -0,0 +1,65 @@ +# +# zip.rb +# + +module Puppet::Parser::Functions + newfunction(:zip, :type => :rvalue, :doc => <<-EOS +Takes one element from first array and merges corresponding elements from second array. This generates a sequence of n-element arrays, where n is one more than the count of arguments. + +*Example:* + + zip(['1','2','3'],['4','5','6']) + +Would result in: + + ["1", "4"], ["2", "5"], ["3", "6"] + EOS + ) do |arguments| + + # Technically we support three arguments but only first is mandatory ... + raise(Puppet::ParseError, "zip(): Wrong number of arguments " + + "given (#{arguments.size} for 2)") if arguments.size < 2 + + a = arguments[0] + b = arguments[1] + + unless a.is_a?(Array) and b.is_a?(Array) + raise(Puppet::ParseError, 'zip(): Requires array to work with') + end + + flatten = arguments[2] if arguments[2] + + if flatten + klass = flatten.class + + # We can have either true or false, or string which resembles boolean ... + unless [FalseClass, TrueClass, String].include?(klass) + raise(Puppet::ParseError, 'zip(): Requires either ' + + 'boolean or string to work with') + end + + if flatten.is_a?(String) + # We consider all the yes, no, y, n and so on too ... + flatten = case flatten + # + # This is how undef looks like in Puppet ... + # We yield false in this case. + # + when /^$/, '' then false # Empty string will be false ... + when /^(1|t|y|true|yes)$/ then true + when /^(0|f|n|false|no)$/ then false + when /^(undef|undefined)$/ then false # This is not likely to happen ... + else + raise(Puppet::ParseError, 'zip(): Unknown type of boolean given') + end + end + end + + result = a.zip(b) + result = flatten ? result.flatten : result + + return result + end +end + +# vim: set ts=2 sw=2 et : |