From 99a93d366f2e1efb977fcc8fe300d3d8357c8214 Mon Sep 17 00:00:00 2001 From: Ken Barber Date: Fri, 29 Apr 2011 09:27:10 +0200 Subject: Convert to module format. --- lib/puppet/parser/functions/abs.rb | 34 ++++++++++ lib/puppet/parser/functions/bool2num.rb | 45 ++++++++++++ lib/puppet/parser/functions/count.rb | 36 ++++++++++ lib/puppet/parser/functions/delete_at.rb | 42 ++++++++++++ lib/puppet/parser/functions/empty.rb | 27 ++++++++ lib/puppet/parser/functions/fact.rb | 36 ++++++++++ lib/puppet/parser/functions/is_array.rb | 21 ++++++ lib/puppet/parser/functions/is_hash.rb | 21 ++++++ lib/puppet/parser/functions/is_string.rb | 21 ++++++ lib/puppet/parser/functions/join.rb | 34 ++++++++++ lib/puppet/parser/functions/join_with_prefix.rb | 38 +++++++++++ lib/puppet/parser/functions/keys.rb | 25 +++++++ lib/puppet/parser/functions/load_variables.rb | 77 +++++++++++++++++++++ lib/puppet/parser/functions/member.rb | 33 +++++++++ lib/puppet/parser/functions/num2bool.rb | 38 +++++++++++ .../parser/functions/persistent_crontab_minutes.rb | 63 +++++++++++++++++ lib/puppet/parser/functions/prefix.rb | 38 +++++++++++ .../parser/functions/random_crontab_minutes.rb | 31 +++++++++ lib/puppet/parser/functions/range.rb | 59 ++++++++++++++++ lib/puppet/parser/functions/reverse.rb | 27 ++++++++ lib/puppet/parser/functions/shuffle.rb | 45 ++++++++++++ lib/puppet/parser/functions/size.rb | 47 +++++++++++++ lib/puppet/parser/functions/strftime.rb | 44 ++++++++++++ lib/puppet/parser/functions/time.rb | 37 ++++++++++ lib/puppet/parser/functions/unique.rb | 34 ++++++++++ lib/puppet/parser/functions/values.rb | 25 +++++++ lib/puppet/parser/functions/values_at.rb | 79 ++++++++++++++++++++++ 27 files changed, 1057 insertions(+) create mode 100644 lib/puppet/parser/functions/abs.rb create mode 100644 lib/puppet/parser/functions/bool2num.rb create mode 100644 lib/puppet/parser/functions/count.rb create mode 100644 lib/puppet/parser/functions/delete_at.rb create mode 100644 lib/puppet/parser/functions/empty.rb create mode 100644 lib/puppet/parser/functions/fact.rb create mode 100644 lib/puppet/parser/functions/is_array.rb create mode 100644 lib/puppet/parser/functions/is_hash.rb create mode 100644 lib/puppet/parser/functions/is_string.rb create mode 100644 lib/puppet/parser/functions/join.rb create mode 100644 lib/puppet/parser/functions/join_with_prefix.rb create mode 100644 lib/puppet/parser/functions/keys.rb create mode 100644 lib/puppet/parser/functions/load_variables.rb create mode 100644 lib/puppet/parser/functions/member.rb create mode 100644 lib/puppet/parser/functions/num2bool.rb create mode 100644 lib/puppet/parser/functions/persistent_crontab_minutes.rb create mode 100644 lib/puppet/parser/functions/prefix.rb create mode 100644 lib/puppet/parser/functions/random_crontab_minutes.rb create mode 100644 lib/puppet/parser/functions/range.rb create mode 100644 lib/puppet/parser/functions/reverse.rb create mode 100644 lib/puppet/parser/functions/shuffle.rb create mode 100644 lib/puppet/parser/functions/size.rb create mode 100644 lib/puppet/parser/functions/strftime.rb create mode 100644 lib/puppet/parser/functions/time.rb create mode 100644 lib/puppet/parser/functions/unique.rb create mode 100644 lib/puppet/parser/functions/values.rb create mode 100644 lib/puppet/parser/functions/values_at.rb (limited to 'lib/puppet') diff --git a/lib/puppet/parser/functions/abs.rb b/lib/puppet/parser/functions/abs.rb new file mode 100644 index 0000000..0a554e4 --- /dev/null +++ b/lib/puppet/parser/functions/abs.rb @@ -0,0 +1,34 @@ +# +# abs.rb +# + +module Puppet::Parser::Functions + newfunction(:abs, :type => :rvalue, :doc => <<-EOS + 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..b2989d0 --- /dev/null +++ b/lib/puppet/parser/functions/bool2num.rb @@ -0,0 +1,45 @@ +# +# bool2num.rb +# + +module Puppet::Parser::Functions + newfunction(:bool2num, :type => :rvalue, :doc => <<-EOS + 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/count.rb b/lib/puppet/parser/functions/count.rb new file mode 100644 index 0000000..c4e2283 --- /dev/null +++ b/lib/puppet/parser/functions/count.rb @@ -0,0 +1,36 @@ +# +# count.rb +# + +# TODO(Krzysztof Wilczynski): We need to add support for regular expression ... +# TODO(Krzysztof Wilczynski): Support for hash values would be nice too ... + +module Puppet::Parser::Functions + newfunction(:count, :type => :rvalue, :doc => <<-EOS + EOS + ) do |arguments| + + # Technically we support two arguments but only first is mandatory ... + raise(Puppet::ParseError, "count(): 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, 'count(): Requires either ' + + 'array, hash or string to work with') + end + + item = arguments[1] if arguments[1] + + value = value.is_a?(Hash) ? value.keys : value + + # No item to look for and count? Then just return current size ... + result = item ? value.count(item) : value.size + + return result + 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..10190ba --- /dev/null +++ b/lib/puppet/parser/functions/delete_at.rb @@ -0,0 +1,42 @@ +# +# delete_at.rb +# + +module Puppet::Parser::Functions + newfunction(:delete_at, :type => :rvalue, :doc => <<-EOS + 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/empty.rb b/lib/puppet/parser/functions/empty.rb new file mode 100644 index 0000000..e78ebf0 --- /dev/null +++ b/lib/puppet/parser/functions/empty.rb @@ -0,0 +1,27 @@ +# +# empty.rb +# + +module Puppet::Parser::Functions + newfunction(:empty, :type => :rvalue, :doc => <<-EOS + 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/fact.rb b/lib/puppet/parser/functions/fact.rb new file mode 100644 index 0000000..27b7bb2 --- /dev/null +++ b/lib/puppet/parser/functions/fact.rb @@ -0,0 +1,36 @@ +# +# fact.rb +# + +module Puppet::Parser::Functions + newfunction(:fact, :type => :rvalue, :doc => <<-EOS + EOS + ) do |arguments| + + raise(Puppet::ParseError, "fact(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") if arguments.size < 1 + + fact = arguments[0] + + unless fact.is_a?(String) + raise(Puppet::ParseError, 'fact(): Requires fact name to be a string') + end + + raise(Puppet::ParseError, 'fact(): You must provide ' + + 'fact name') if fact.empty? + + result = lookupvar(fact) # Get the value of interest from Facter ... + + # + # Now this is a funny one ... Puppet does not have a concept of + # returning neither undef nor nil back for use within the Puppet DSL + # and empty string is as closest to actual undef as you we can get + # at this point in time ... + # + result = result.empty? ? '' : result + + 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..0b508fd --- /dev/null +++ b/lib/puppet/parser/functions/is_array.rb @@ -0,0 +1,21 @@ +# +# is_array.rb +# + +module Puppet::Parser::Functions + newfunction(:is_array, :type => :rvalue, :doc => <<-EOS + 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_hash.rb b/lib/puppet/parser/functions/is_hash.rb new file mode 100644 index 0000000..259809c --- /dev/null +++ b/lib/puppet/parser/functions/is_hash.rb @@ -0,0 +1,21 @@ +# +# is_hash.rb +# + +module Puppet::Parser::Functions + newfunction(:is_array, :type => :rvalue, :doc => <<-EOS + 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_string.rb b/lib/puppet/parser/functions/is_string.rb new file mode 100644 index 0000000..61037e3 --- /dev/null +++ b/lib/puppet/parser/functions/is_string.rb @@ -0,0 +1,21 @@ +# +# is_string.rb +# + +module Puppet::Parser::Functions + newfunction(:is_string, :type => :rvalue, :doc => <<-EOS + 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) + + 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..945556a --- /dev/null +++ b/lib/puppet/parser/functions/join.rb @@ -0,0 +1,34 @@ +# +# join.rb +# + +module Puppet::Parser::Functions + newfunction(:join, :type => :rvalue, :doc => <<-EOS + 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/join_with_prefix.rb b/lib/puppet/parser/functions/join_with_prefix.rb new file mode 100644 index 0000000..8bf96d9 --- /dev/null +++ b/lib/puppet/parser/functions/join_with_prefix.rb @@ -0,0 +1,38 @@ +# +# join_with_prefix.rb +# + +module Puppet::Parser::Functions + newfunction(:join_with_prefix, :type => :rvalue, :doc => <<-EOS + EOS + ) do |arguments| + + # Technically we support three 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_with_prefix(): Requires ' + + 'array to work with') + end + + prefix = arguments[1] if arguments[1] + suffix = arguments[2] if arguments[2] + + if prefix and suffix + result = prefix + array.join(suffix + prefix) + elsif prefix and not suffix + result = array.collect { |i| prefix ? prefix + i : i } + elsif suffix and not prefix + result = array.join(suffix) + else + result = array.join + end + + 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..3a92a47 --- /dev/null +++ b/lib/puppet/parser/functions/keys.rb @@ -0,0 +1,25 @@ +# +# keys.rb +# + +module Puppet::Parser::Functions + newfunction(:keys, :type => :rvalue, :doc => <<-EOS + 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/load_variables.rb b/lib/puppet/parser/functions/load_variables.rb new file mode 100644 index 0000000..a28c64b --- /dev/null +++ b/lib/puppet/parser/functions/load_variables.rb @@ -0,0 +1,77 @@ +# +# load_variables.rb +# + +module Puppet::Parser::Functions + newfunction(:load_variables, :type => :statement, :doc => <<-EOS +This function will allow for loading variables from an external YAML +file and expose them for further use inside the Puppet manifest file ... + +For example: + +Given following content of the data.yaml file: + + --- + host1.example.com: + foo: bar + baz: quux + question: 42 + host2.example.com: + abc: def + this: that + darth: vader + +Then calling load_variables in Puppet manifest file as follows: + + load_variables("/etc/puppet/data.yaml", $fqdn) + +Will result in addition of variables $foo, $baz and $question +for matching host name as per the variable $fqdn ... + +Another example which uses per-host file: + +Given following content of the file data-host1.example.com.yaml: + + --- + foo: bar + +Then when we call load_variables like this: + + load_variables("/etc/puppet/data-${fqdn}.yaml") + +This will result in a variable $foo being added and ready for use. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "load_variables(): Wrong number of " + + "arguments given (#{arguments.size} for 2)") if arguments.size < 2 + + data = {} + + file = arguments[0] + key = arguments[1] if arguments[1] + + if File.exists?(file) + + begin + data = YAML.load_file(file) + rescue => error + raise(Puppet::ParseError, "load_variables(): Unable to load data " + + "from the file `%s': %s" % file, error.to_s) + end + + raise(Puppet::ParseError, "load_variables(): Data in the file `%s' " + + "is not a hash" % file) unless data.is_a?(Hash) + + data = ((data[key] and data[key].is_a?(Hash)) ? data[key] : {}) if key + end + + data.each do |param, value| + value = strinterp(value) # Evaluate any interpolated variable names ... + + setvar(param, value) + end + 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..a491a76 --- /dev/null +++ b/lib/puppet/parser/functions/member.rb @@ -0,0 +1,33 @@ +# +# include.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(:includes, :type => :rvalue, :doc => <<-EOS + EOS + ) do |arguments| + + raise(Puppet::ParseError, "includes(): Wrong number of arguments " + + "given (#{arguments.size} for 2)") if arguments.size < 2 + + array = arguments[0] + + if not array.is_a?(Array) + raise(Puppet::ParseError, 'includes(): Requires an array to work with') + end + + item = arguments[1] + + raise(Puppet::ParseError, 'includes(): You must provide item ' + + 'to search for within given array') 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..2baef62 --- /dev/null +++ b/lib/puppet/parser/functions/num2bool.rb @@ -0,0 +1,38 @@ +# +# num2bool.rb +# + +# TODO(Krzysztof Wilczynski): We probably need to approach numeric values differently ... + +module Puppet::Parser::Functions + newfunction(:num2bool, :type => :rvalue, :doc => <<-EOS + 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/persistent_crontab_minutes.rb b/lib/puppet/parser/functions/persistent_crontab_minutes.rb new file mode 100644 index 0000000..cd80094 --- /dev/null +++ b/lib/puppet/parser/functions/persistent_crontab_minutes.rb @@ -0,0 +1,63 @@ +# +# persistent_crontab_minutes.rb +# + +module Puppet::Parser::Functions + newfunction(:persistent_crontab_minutes, :type => :rvalue, :doc => <<-EOS + EOS + ) do |arguments| + + raise(Puppet::ParseError, "Wrong number of arguments " + + "given (#{arguments.size} for 2)") if arguments.size < 2 + + require 'md5' + + value = 0 + + job = arguments[0] + host = arguments[1] + + environment = Puppet[:environment] + + # We select first directory that exists. This might not be the best idea ... + modules = Puppet[:modulepath].split(':').select { |i| File.exists?(i) }.first + + raise(Puppet::ParseError, "Unable to determine the storage " + + "directory for Puppet modules") unless modules + + # Prepare the file where we store current value ... + file = "/puppet/state/crontab/#{host}-#{job}.minutes" + file = File.join(modules, file) + + # Get the directory portion from the file name ... + directory = File.dirname(file) + + FileUtils.mkdir_p(directory) unless File.directory?(directory) + + if FileTest.exists?(file) + File.open(file, 'r') { |f| value = f.read.to_i } + + raise(Puppet::ParseError, "The value for minutes in the file `%s' " + + "is out of the range from 0 to 59 inclusive") unless value < 60 + else + # + # Pick a random number based on the job and host name. This will yield + # the same value for exactly the same combination of the job and host name. + # + value = MD5.new(job_name + host).to_s.hex % 60 + + # Minutes are from 0 to 59 inclusive ... + value = value < 60 ? value : 59 + + File.open(file, 'w') { |f| f.write(value) } + end + + # Tell Puppet to keep an eye on this file ... + parser = Puppet::Parser::Parser.new(environment) + parser.watch_file(file) if File.exists?(file) + + return value + 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..0e0cee2 --- /dev/null +++ b/lib/puppet/parser/functions/prefix.rb @@ -0,0 +1,38 @@ +# +# prefix.rb +# + +module Puppet::Parser::Functions + newfunction(:prefix, :type => :rvalue, :doc => <<-EOS + 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/random_crontab_minutes.rb b/lib/puppet/parser/functions/random_crontab_minutes.rb new file mode 100644 index 0000000..8ab29e1 --- /dev/null +++ b/lib/puppet/parser/functions/random_crontab_minutes.rb @@ -0,0 +1,31 @@ +# +# random_crontab_minutes.rb +# + +module Puppet::Parser::Functions + newfunction(:random_crontab_minutes, :type => :rvalue, :doc => <<-EOS + EOS + ) do |arguments| + + raise(Puppet::ParseError, "Wrong number of arguments " + + "given (#{arguments.size} for 2)") if arguments.size < 2 + + require 'md5' + + job_name = arguments[0] + host = arguments[1] + + # + # Pick a random number based on the job and host name. This will yield + # the same value for exactly the same combination of the job and host name. + # + value = MD5.new(job_name + host).to_s.hex % 60 + + # Minutes are from 0 to 59 inclusive ... + value = value < 60 ? value : 59 + + return value + 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..6afb50c --- /dev/null +++ b/lib/puppet/parser/functions/range.rb @@ -0,0 +1,59 @@ +# +# range.rb +# + +# TODO(Krzysztof Wilczynski): We probably need to approach numeric values differently ... + +module Puppet::Parser::Functions + newfunction(:range, :type => :rvalue, :doc => <<-EOS + 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..79e9b93 --- /dev/null +++ b/lib/puppet/parser/functions/reverse.rb @@ -0,0 +1,27 @@ +# +# reverse.rb +# + +module Puppet::Parser::Functions + newfunction(:reverse, :type => :rvalue, :doc => <<-EOS + 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/shuffle.rb b/lib/puppet/parser/functions/shuffle.rb new file mode 100644 index 0000000..73e798c --- /dev/null +++ b/lib/puppet/parser/functions/shuffle.rb @@ -0,0 +1,45 @@ +# +# shuffle.rb +# + +module Puppet::Parser::Functions + newfunction(:shuffle, :type => :rvalue, :doc => <<-EOS + 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..aa4f4ad --- /dev/null +++ b/lib/puppet/parser/functions/size.rb @@ -0,0 +1,47 @@ +# +# size.rb +# + +# TODO(Krzysztof Wilczynski): Support for hashes would be nice too ... + +module Puppet::Parser::Functions + newfunction(:size, :type => :rvalue, :doc => <<-EOS + 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/strftime.rb b/lib/puppet/parser/functions/strftime.rb new file mode 100644 index 0000000..c919320 --- /dev/null +++ b/lib/puppet/parser/functions/strftime.rb @@ -0,0 +1,44 @@ +# +# strftime.rb +# + +module Puppet::Parser::Functions + newfunction(:strftime, :type => :rvalue, :doc => <<-EOS + 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/time.rb b/lib/puppet/parser/functions/time.rb new file mode 100644 index 0000000..f7c1041 --- /dev/null +++ b/lib/puppet/parser/functions/time.rb @@ -0,0 +1,37 @@ +# +# time.rb +# + +module Puppet::Parser::Functions + newfunction(:time, :type => :rvalue, :doc => <<-EOS + EOS + ) do |arguments| + + # The Time Zone argument is optional ... + time_zone = arguments[0] if arguments[0] + + 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/unique.rb b/lib/puppet/parser/functions/unique.rb new file mode 100644 index 0000000..a922c94 --- /dev/null +++ b/lib/puppet/parser/functions/unique.rb @@ -0,0 +1,34 @@ +# +# unique.rb +# + +module Puppet::Parser::Functions + newfunction(:unique, :type => :rvalue, :doc => <<-EOS + 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/values.rb b/lib/puppet/parser/functions/values.rb new file mode 100644 index 0000000..c1c4a77 --- /dev/null +++ b/lib/puppet/parser/functions/values.rb @@ -0,0 +1,25 @@ +# +# values.rb +# + +module Puppet::Parser::Functions + newfunction(:values, :type => :rvalue, :doc => <<-EOS + 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..331af6a --- /dev/null +++ b/lib/puppet/parser/functions/values_at.rb @@ -0,0 +1,79 @@ +# +# values_at.rb +# + +# TODO(Krzysztof Wilczynski): Support for hashes would be nice too ... +# TODO(Krzysztof Wilczynski): We probably need to approach numeric values differently ... + +module Puppet::Parser::Functions + newfunction(:values_at, :type => :rvalue, :doc => <<-EOS + 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 # 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 : -- cgit v1.2.3