summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorvarac <varacanero@zeromail.org>2017-01-13 12:41:58 +0100
committervarac <varacanero@zeromail.org>2017-01-13 12:41:58 +0100
commit066c08f8362d53f0f30897cb8710d11260c726ea (patch)
treea6369eecd88bb731fe413d0bbc8af73d74d1f447 /lib
parent71123634744b9fe2ec7d6a3e38e9789fd84801e3 (diff)
parentb65dd1f45d10e10e45455358aeabb29167990e2c (diff)
Merge remote-tracking branch 'origin/master' into leap_master
Diffstat (limited to 'lib')
-rw-r--r--lib/facter/facter_dot_d.rb10
-rw-r--r--lib/facter/package_provider.rb21
-rw-r--r--lib/facter/pe_version.rb9
-rw-r--r--lib/facter/puppet_settings.rb43
-rw-r--r--lib/facter/puppet_vardir.rb26
-rw-r--r--lib/facter/root_home.rb13
-rw-r--r--lib/facter/service_provider.rb17
-rw-r--r--lib/puppet/functions/deprecation.rb29
-rw-r--r--lib/puppet/functions/is_a.rb32
-rw-r--r--lib/puppet/functions/is_absolute_path.rb15
-rw-r--r--lib/puppet/functions/is_array.rb15
-rw-r--r--lib/puppet/functions/is_bool.rb15
-rw-r--r--lib/puppet/functions/is_float.rb15
-rw-r--r--lib/puppet/functions/is_ip_address.rb15
-rw-r--r--lib/puppet/functions/is_ipv4_address.rb15
-rw-r--r--lib/puppet/functions/is_ipv6_address.rb15
-rw-r--r--lib/puppet/functions/is_numeric.rb15
-rw-r--r--lib/puppet/functions/is_string.rb15
-rw-r--r--lib/puppet/functions/type_of.rb2
-rw-r--r--lib/puppet/functions/validate_absolute_path.rb15
-rw-r--r--lib/puppet/functions/validate_array.rb15
-rw-r--r--lib/puppet/functions/validate_bool.rb15
-rw-r--r--lib/puppet/functions/validate_hash.rb15
-rw-r--r--lib/puppet/functions/validate_integer.rb15
-rw-r--r--lib/puppet/functions/validate_ip_address.rb15
-rw-r--r--lib/puppet/functions/validate_ipv4_address.rb15
-rw-r--r--lib/puppet/functions/validate_ipv6_address.rb15
-rw-r--r--lib/puppet/functions/validate_legacy.rb62
-rw-r--r--lib/puppet/functions/validate_numeric.rb15
-rw-r--r--lib/puppet/functions/validate_re.rb15
-rw-r--r--lib/puppet/functions/validate_slength.rb15
-rw-r--r--lib/puppet/functions/validate_string.rb15
-rw-r--r--lib/puppet/parser/functions/any2bool.rb55
-rw-r--r--lib/puppet/parser/functions/assert_private.rb29
-rw-r--r--lib/puppet/parser/functions/base64.rb41
-rw-r--r--lib/puppet/parser/functions/bool2str.rb26
-rw-r--r--lib/puppet/parser/functions/ceiling.rb25
-rw-r--r--lib/puppet/parser/functions/clamp.rb30
-rw-r--r--lib/puppet/parser/functions/concat.rb2
-rw-r--r--lib/puppet/parser/functions/convert_base.rb35
-rw-r--r--lib/puppet/parser/functions/defined_with_params.rb5
-rw-r--r--lib/puppet/parser/functions/delete.rb8
-rw-r--r--lib/puppet/parser/functions/delete_regex.rb45
-rw-r--r--lib/puppet/parser/functions/deprecation.rb17
-rw-r--r--lib/puppet/parser/functions/dig.rb16
-rw-r--r--lib/puppet/parser/functions/dig44.rb73
-rw-r--r--lib/puppet/parser/functions/dirname.rb14
-rw-r--r--lib/puppet/parser/functions/dos2unix.rb15
-rw-r--r--lib/puppet/parser/functions/empty.rb12
-rw-r--r--lib/puppet/parser/functions/enclose_ipv6.rb45
-rw-r--r--lib/puppet/parser/functions/ensure_packages.rb27
-rw-r--r--lib/puppet/parser/functions/ensure_resources.rb54
-rw-r--r--lib/puppet/parser/functions/fqdn_rand_string.rb34
-rw-r--r--lib/puppet/parser/functions/fqdn_rotate.rb38
-rw-r--r--lib/puppet/parser/functions/fqdn_uuid.rb92
-rw-r--r--lib/puppet/parser/functions/getparam.rb2
-rw-r--r--lib/puppet/parser/functions/getvar.rb8
-rw-r--r--lib/puppet/parser/functions/has_interface_with.rb7
-rw-r--r--lib/puppet/parser/functions/hash.rb2
-rw-r--r--lib/puppet/parser/functions/intersection.rb6
-rw-r--r--lib/puppet/parser/functions/is_absolute_path.rb50
-rw-r--r--lib/puppet/parser/functions/is_array.rb4
-rw-r--r--lib/puppet/parser/functions/is_bool.rb4
-rw-r--r--lib/puppet/parser/functions/is_domain_name.rb12
-rw-r--r--lib/puppet/parser/functions/is_email_address.rb21
-rw-r--r--lib/puppet/parser/functions/is_float.rb2
-rw-r--r--lib/puppet/parser/functions/is_integer.rb2
-rw-r--r--lib/puppet/parser/functions/is_ip_address.rb2
-rw-r--r--lib/puppet/parser/functions/is_ipv4_address.rb30
-rw-r--r--lib/puppet/parser/functions/is_ipv6_address.rb30
-rw-r--r--lib/puppet/parser/functions/is_mac_address.rb2
-rw-r--r--lib/puppet/parser/functions/is_numeric.rb4
-rw-r--r--lib/puppet/parser/functions/is_string.rb5
-rw-r--r--lib/puppet/parser/functions/join_keys_to_values.rb15
-rw-r--r--lib/puppet/parser/functions/load_module_metadata.rb24
-rw-r--r--lib/puppet/parser/functions/loadjson.rb34
-rw-r--r--lib/puppet/parser/functions/loadyaml.rb34
-rw-r--r--lib/puppet/parser/functions/member.rb2
-rw-r--r--lib/puppet/parser/functions/parsejson.rb25
-rw-r--r--lib/puppet/parser/functions/parseyaml.rb25
-rw-r--r--lib/puppet/parser/functions/prefix.rb23
-rw-r--r--lib/puppet/parser/functions/private.rb24
-rw-r--r--lib/puppet/parser/functions/pry.rb30
-rw-r--r--lib/puppet/parser/functions/pw_hash.rb56
-rw-r--r--lib/puppet/parser/functions/range.rb25
-rw-r--r--lib/puppet/parser/functions/regexpescape.rb31
-rw-r--r--lib/puppet/parser/functions/seeded_rand.rb22
-rw-r--r--lib/puppet/parser/functions/shell_escape.rb30
-rw-r--r--lib/puppet/parser/functions/shell_join.rb31
-rw-r--r--lib/puppet/parser/functions/shell_split.rb26
-rw-r--r--lib/puppet/parser/functions/size.rb8
-rw-r--r--lib/puppet/parser/functions/str2bool.rb10
-rw-r--r--lib/puppet/parser/functions/suffix.rb24
-rw-r--r--lib/puppet/parser/functions/time.rb5
-rw-r--r--lib/puppet/parser/functions/try_get_value.rb53
-rw-r--r--lib/puppet/parser/functions/union.rb17
-rw-r--r--lib/puppet/parser/functions/unix2dos.rb15
-rw-r--r--lib/puppet/parser/functions/upcase.rb19
-rw-r--r--lib/puppet/parser/functions/uriescape.rb2
-rw-r--r--lib/puppet/parser/functions/validate_absolute_path.rb27
-rw-r--r--lib/puppet/parser/functions/validate_array.rb2
-rw-r--r--lib/puppet/parser/functions/validate_augeas.rb2
-rw-r--r--lib/puppet/parser/functions/validate_bool.rb3
-rw-r--r--lib/puppet/parser/functions/validate_cmd.rb2
-rw-r--r--lib/puppet/parser/functions/validate_email_address.rb31
-rw-r--r--lib/puppet/parser/functions/validate_hash.rb2
-rw-r--r--lib/puppet/parser/functions/validate_integer.rb134
-rw-r--r--lib/puppet/parser/functions/validate_ip_address.rb52
-rw-r--r--lib/puppet/parser/functions/validate_ipv4_address.rb4
-rw-r--r--lib/puppet/parser/functions/validate_ipv6_address.rb2
-rw-r--r--lib/puppet/parser/functions/validate_numeric.rb96
-rw-r--r--lib/puppet/parser/functions/validate_re.rb14
-rw-r--r--lib/puppet/parser/functions/validate_slength.rb8
-rw-r--r--lib/puppet/parser/functions/validate_string.rb11
-rw-r--r--lib/puppet/parser/functions/validate_x509_rsa_key_pair.rb47
-rw-r--r--lib/puppet/provider/file_line/ruby.rb99
-rw-r--r--lib/puppet/type/file_line.rb76
117 files changed, 2453 insertions, 279 deletions
diff --git a/lib/facter/facter_dot_d.rb b/lib/facter/facter_dot_d.rb
index b058437..5c5fb1f 100644
--- a/lib/facter/facter_dot_d.rb
+++ b/lib/facter/facter_dot_d.rb
@@ -8,7 +8,7 @@
# contains a cache TTL. For foo.sh store the ttl as just
# a number in foo.sh.ttl
#
-# The cache is stored in /tmp/facts_cache.yaml as a mode
+# The cache is stored in $libdir/facts_dot_d.cache as a mode
# 600 file and will have the end result of not calling your
# fact scripts more often than is needed
@@ -48,7 +48,7 @@ class Facter::Util::DotD
end
end
end
- rescue Exception => e
+ rescue StandardError => e
Facter.warn("Failed to handle #{file} as text facts: #{e.class}: #{e}")
end
@@ -65,7 +65,7 @@ class Facter::Util::DotD
setcode { v }
end
end
- rescue Exception => e
+ rescue StandardError => e
Facter.warn("Failed to handle #{file} as json facts: #{e.class}: #{e}")
end
@@ -77,7 +77,7 @@ class Facter::Util::DotD
setcode { v }
end
end
- rescue Exception => e
+ rescue StandardError => e
Facter.warn("Failed to handle #{file} as yaml facts: #{e.class}: #{e}")
end
@@ -106,7 +106,7 @@ class Facter::Util::DotD
end
end
end
- rescue Exception => e
+ rescue StandardError => e
Facter.warn("Failed to handle #{file} as script facts: #{e.class}: #{e}")
Facter.debug(e.backtrace.join("\n\t"))
end
diff --git a/lib/facter/package_provider.rb b/lib/facter/package_provider.rb
new file mode 100644
index 0000000..3a9117f
--- /dev/null
+++ b/lib/facter/package_provider.rb
@@ -0,0 +1,21 @@
+# Fact: package_provider
+#
+# Purpose: Returns the default provider Puppet will choose to manage packages
+# on this system
+#
+# Resolution: Instantiates a dummy package resource and return the provider
+#
+# Caveats:
+#
+require 'puppet/type'
+require 'puppet/type/package'
+
+Facter.add(:package_provider) do
+ setcode do
+ if defined? Gem and Gem::Version.new(Facter.value(:puppetversion).split(' ')[0]) >= Gem::Version.new('3.6')
+ Puppet::Type.type(:package).newpackage(:name => 'dummy', :allow_virtual => 'true')[:provider].to_s
+ else
+ Puppet::Type.type(:package).newpackage(:name => 'dummy')[:provider].to_s
+ end
+ end
+end
diff --git a/lib/facter/pe_version.rb b/lib/facter/pe_version.rb
index 0cc0f64..c9f2181 100644
--- a/lib/facter/pe_version.rb
+++ b/lib/facter/pe_version.rb
@@ -10,8 +10,13 @@
#
Facter.add("pe_version") do
setcode do
- pe_ver = Facter.value("puppetversion").match(/Puppet Enterprise (\d+\.\d+\.\d+)/)
- pe_ver[1] if pe_ver
+ puppet_ver = Facter.value("puppetversion")
+ if puppet_ver != nil
+ pe_ver = puppet_ver.match(/Puppet Enterprise (\d+\.\d+\.\d+)/)
+ pe_ver[1] if pe_ver
+ else
+ nil
+ end
end
end
diff --git a/lib/facter/puppet_settings.rb b/lib/facter/puppet_settings.rb
new file mode 100644
index 0000000..eac9e97
--- /dev/null
+++ b/lib/facter/puppet_settings.rb
@@ -0,0 +1,43 @@
+# These facter facts return the value of the Puppet vardir and environment path
+# settings for the node running puppet or puppet agent. The intent is to
+# enable Puppet modules to automatically have insight into a place where they
+# can place variable data, or for modules running on the puppet master to know
+# where environments are stored.
+#
+# The values should be directly usable in a File resource path attribute.
+#
+begin
+ require 'facter/util/puppet_settings'
+rescue LoadError => e
+ # puppet apply does not add module lib directories to the $LOAD_PATH (See
+ # #4248). It should (in the future) but for the time being we need to be
+ # defensive which is what this rescue block is doing.
+ rb_file = File.join(File.dirname(__FILE__), 'util', 'puppet_settings.rb')
+ load rb_file if File.exists?(rb_file) or raise e
+end
+
+
+# These will be nil if Puppet is not available.
+Facter.add(:puppet_vardir) do
+ setcode do
+ Facter::Util::PuppetSettings.with_puppet do
+ Puppet[:vardir]
+ end
+ end
+end
+
+Facter.add(:puppet_environmentpath) do
+ setcode do
+ Facter::Util::PuppetSettings.with_puppet do
+ Puppet[:environmentpath]
+ end
+ end
+end
+
+Facter.add(:puppet_server) do
+ setcode do
+ Facter::Util::PuppetSettings.with_puppet do
+ Puppet[:server]
+ end
+ end
+end
diff --git a/lib/facter/puppet_vardir.rb b/lib/facter/puppet_vardir.rb
deleted file mode 100644
index 0e6af40..0000000
--- a/lib/facter/puppet_vardir.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# This facter fact returns the value of the Puppet vardir setting for the node
-# running puppet or puppet agent. The intent is to enable Puppet modules to
-# automatically have insight into a place where they can place variable data,
-# regardless of the node's platform.
-#
-# The value should be directly usable in a File resource path attribute.
-
-
-begin
- require 'facter/util/puppet_settings'
-rescue LoadError => e
- # puppet apply does not add module lib directories to the $LOAD_PATH (See
- # #4248). It should (in the future) but for the time being we need to be
- # defensive which is what this rescue block is doing.
- rb_file = File.join(File.dirname(__FILE__), 'util', 'puppet_settings.rb')
- load rb_file if File.exists?(rb_file) or raise e
-end
-
-Facter.add(:puppet_vardir) do
- setcode do
- # This will be nil if Puppet is not available.
- Facter::Util::PuppetSettings.with_puppet do
- Puppet[:vardir]
- end
- end
-end
diff --git a/lib/facter/root_home.rb b/lib/facter/root_home.rb
index b4f87ff..87c7657 100644
--- a/lib/facter/root_home.rb
+++ b/lib/facter/root_home.rb
@@ -30,3 +30,16 @@ Facter.add(:root_home) do
hash['dir'].strip
end
end
+
+Facter.add(:root_home) do
+ confine :kernel => :aix
+ root_home = nil
+ setcode do
+ str = Facter::Util::Resolution.exec("lsuser -c -a home root")
+ str && str.split("\n").each do |line|
+ next if line =~ /^#/
+ root_home = line.split(/:/)[1]
+ end
+ root_home
+ end
+end
diff --git a/lib/facter/service_provider.rb b/lib/facter/service_provider.rb
new file mode 100644
index 0000000..a117921
--- /dev/null
+++ b/lib/facter/service_provider.rb
@@ -0,0 +1,17 @@
+# Fact: service_provider
+#
+# Purpose: Returns the default provider Puppet will choose to manage services
+# on this system
+#
+# Resolution: Instantiates a dummy service resource and return the provider
+#
+# Caveats:
+#
+require 'puppet/type'
+require 'puppet/type/service'
+
+Facter.add(:service_provider) do
+ setcode do
+ Puppet::Type.type(:service).newservice(:name => 'dummy')[:provider].to_s
+ end
+end
diff --git a/lib/puppet/functions/deprecation.rb b/lib/puppet/functions/deprecation.rb
new file mode 100644
index 0000000..39d9bc7
--- /dev/null
+++ b/lib/puppet/functions/deprecation.rb
@@ -0,0 +1,29 @@
+# Function to print deprecation warnings, Logs a warning once for a given key. The uniqueness key - can appear once. The msg is the message text including any positional information that is formatted by the user/caller of the method It is affected by the puppet setting 'strict', which can be set to :error (outputs as an error message), :off (no message / error is displayed) and :warning (default, outputs a warning) *Type*: String, String.
+#
+
+Puppet::Functions.create_function(:deprecation) do
+ dispatch :deprecation do
+ param 'String', :key
+ param 'String', :message
+ end
+
+ def deprecation(key, message)
+ if defined? Puppet::Pops::PuppetStack.stacktrace()
+ stacktrace = Puppet::Pops::PuppetStack.stacktrace()
+ file = stacktrace[0]
+ line = stacktrace[1]
+ message = "#{message} at #{file}:#{line}"
+ end
+ # depending on configuration setting of strict
+ case Puppet.settings[:strict]
+ when :off
+ # do nothing
+ when :error
+ fail("deprecation. #{key}. #{message}")
+ else
+ unless ENV['STDLIB_LOG_DEPRECATIONS'] == 'false'
+ Puppet.deprecation_warning(message, key)
+ end
+ end
+ end
+end
diff --git a/lib/puppet/functions/is_a.rb b/lib/puppet/functions/is_a.rb
new file mode 100644
index 0000000..da98b03
--- /dev/null
+++ b/lib/puppet/functions/is_a.rb
@@ -0,0 +1,32 @@
+# Boolean check to determine whether a variable is of a given data type. This is equivalent to the `=~` type checks.
+#
+# @example how to check a data type
+# # check a data type
+# foo = 3
+# $bar = [1,2,3]
+# $baz = 'A string!'
+#
+# if $foo.is_a(Integer) {
+# notify { 'foo!': }
+# }
+# if $bar.is_a(Array) {
+# notify { 'bar!': }
+# }
+# if $baz.is_a(String) {
+# notify { 'baz!': }
+# }
+#
+# See the documentation for "The Puppet Type System" for more information about types.
+# See the `assert_type()` function for flexible ways to assert the type of a value.
+#
+Puppet::Functions.create_function(:is_a) do
+ dispatch :is_a do
+ param 'Any', :value
+ param 'Type', :type
+ end
+
+ def is_a(value, type)
+ # See puppet's lib/puppet/pops/evaluator/evaluator_impl.rb eval_MatchExpression
+ Puppet::Pops::Types::TypeCalculator.instance?(type, value)
+ end
+end
diff --git a/lib/puppet/functions/is_absolute_path.rb b/lib/puppet/functions/is_absolute_path.rb
new file mode 100644
index 0000000..b61064a
--- /dev/null
+++ b/lib/puppet/functions/is_absolute_path.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_absolute_path) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_absolute_path', "This method is deprecated, please use match expressions with Stdlib::Compat::Absolute_Path instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_absolute_path", args)
+ end
+end
diff --git a/lib/puppet/functions/is_array.rb b/lib/puppet/functions/is_array.rb
new file mode 100644
index 0000000..a29fe8a
--- /dev/null
+++ b/lib/puppet/functions/is_array.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_array) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_array', "This method is deprecated, please use match expressions with Stdlib::Compat::Array instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_array", args)
+ end
+end
diff --git a/lib/puppet/functions/is_bool.rb b/lib/puppet/functions/is_bool.rb
new file mode 100644
index 0000000..6e2c22b
--- /dev/null
+++ b/lib/puppet/functions/is_bool.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_bool) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_bool', "This method is deprecated, please use match expressions with Stdlib::Compat::Bool instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_bool", args)
+ end
+end
diff --git a/lib/puppet/functions/is_float.rb b/lib/puppet/functions/is_float.rb
new file mode 100644
index 0000000..c91aa5d
--- /dev/null
+++ b/lib/puppet/functions/is_float.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_float) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_float', "This method is deprecated, please use match expressions with Stdlib::Compat::Float instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_float", args)
+ end
+end
diff --git a/lib/puppet/functions/is_ip_address.rb b/lib/puppet/functions/is_ip_address.rb
new file mode 100644
index 0000000..4c72037
--- /dev/null
+++ b/lib/puppet/functions/is_ip_address.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_ip_address) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_ip_address', "This method is deprecated, please use match expressions with Stdlib::Compat::Ip_address instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_ip_address", args)
+ end
+end
diff --git a/lib/puppet/functions/is_ipv4_address.rb b/lib/puppet/functions/is_ipv4_address.rb
new file mode 100644
index 0000000..97b01ae
--- /dev/null
+++ b/lib/puppet/functions/is_ipv4_address.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_ipv4_address) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_ipv4_address', "This method is deprecated, please use match expressions with Stdlib::Compat::Ipv4 instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_ipv4_address", args)
+ end
+end
diff --git a/lib/puppet/functions/is_ipv6_address.rb b/lib/puppet/functions/is_ipv6_address.rb
new file mode 100644
index 0000000..be0c98a
--- /dev/null
+++ b/lib/puppet/functions/is_ipv6_address.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_ipv6_address) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_ipv4_address', "This method is deprecated, please use match expressions with Stdlib::Compat::Ipv6 instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_ipv6_address", args)
+ end
+end
diff --git a/lib/puppet/functions/is_numeric.rb b/lib/puppet/functions/is_numeric.rb
new file mode 100644
index 0000000..f5e9d41
--- /dev/null
+++ b/lib/puppet/functions/is_numeric.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_numeric) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_numeric', "This method is deprecated, please use match expressions with Stdlib::Compat::Numeric instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_numeric", args)
+ end
+end
diff --git a/lib/puppet/functions/is_string.rb b/lib/puppet/functions/is_string.rb
new file mode 100644
index 0000000..a05a796
--- /dev/null
+++ b/lib/puppet/functions/is_string.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_string) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_string', "This method is deprecated, please use match expressions with Stdlib::Compat::String instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_string", args)
+ end
+end
diff --git a/lib/puppet/functions/type_of.rb b/lib/puppet/functions/type_of.rb
index 02cdd4d..01f1f49 100644
--- a/lib/puppet/functions/type_of.rb
+++ b/lib/puppet/functions/type_of.rb
@@ -10,6 +10,8 @@
# See the documentation for "The Puppet Type System" for more information about types.
# See the `assert_type()` function for flexible ways to assert the type of a value.
#
+# The built-in type() function in puppet is generally preferred over this function
+# this function is provided for backwards compatibility.
Puppet::Functions.create_function(:type_of) do
def type_of(value)
Puppet::Pops::Types::TypeCalculator.infer_set(value)
diff --git a/lib/puppet/functions/validate_absolute_path.rb b/lib/puppet/functions/validate_absolute_path.rb
new file mode 100644
index 0000000..a3c696d
--- /dev/null
+++ b/lib/puppet/functions/validate_absolute_path.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_absolute_path) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_absolute_path', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Absolute_Path. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_absolute_path", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_array.rb b/lib/puppet/functions/validate_array.rb
new file mode 100644
index 0000000..f59c6b4
--- /dev/null
+++ b/lib/puppet/functions/validate_array.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_array) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_array', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Array. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_array", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_bool.rb b/lib/puppet/functions/validate_bool.rb
new file mode 100644
index 0000000..5cfb2ac
--- /dev/null
+++ b/lib/puppet/functions/validate_bool.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_bool) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_bool', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Bool. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_bool", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_hash.rb b/lib/puppet/functions/validate_hash.rb
new file mode 100644
index 0000000..89ad9ab
--- /dev/null
+++ b/lib/puppet/functions/validate_hash.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_hash) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_hash', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Hash. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_hash", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_integer.rb b/lib/puppet/functions/validate_integer.rb
new file mode 100644
index 0000000..475ea0f
--- /dev/null
+++ b/lib/puppet/functions/validate_integer.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_integer) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_integer', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Integer. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_integer", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_ip_address.rb b/lib/puppet/functions/validate_ip_address.rb
new file mode 100644
index 0000000..1521c08
--- /dev/null
+++ b/lib/puppet/functions/validate_ip_address.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_ip_address) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_ip_address', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ip_Address. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_ip_address", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_ipv4_address.rb b/lib/puppet/functions/validate_ipv4_address.rb
new file mode 100644
index 0000000..fe66ab3
--- /dev/null
+++ b/lib/puppet/functions/validate_ipv4_address.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_ipv4_address) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_ipv4_address', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ipv4_Address. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_ipv4_address", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_ipv6_address.rb b/lib/puppet/functions/validate_ipv6_address.rb
new file mode 100644
index 0000000..7cc3cbd
--- /dev/null
+++ b/lib/puppet/functions/validate_ipv6_address.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_ipv6_address) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_ipv6_address', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ipv6_address. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_ipv6_address", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_legacy.rb b/lib/puppet/functions/validate_legacy.rb
new file mode 100644
index 0000000..c9d1f56
--- /dev/null
+++ b/lib/puppet/functions/validate_legacy.rb
@@ -0,0 +1,62 @@
+Puppet::Functions.create_function(:validate_legacy) do
+ # The function checks a value against both the target_type (new) and the previous_validation function (old).
+
+ dispatch :validate_legacy do
+ param 'Any', :scope
+ param 'Type', :target_type
+ param 'String', :function_name
+ param 'Any', :value
+ repeated_param 'Any', :args
+ end
+
+ dispatch :validate_legacy_s do
+ param 'Any', :scope
+ param 'String', :type_string
+ param 'String', :function_name
+ param 'Any', :value
+ repeated_param 'Any', :args
+ end
+
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+
+ def validate_legacy_s(scope, type_string, *args)
+ t = Puppet::Pops::Types::TypeParser.new.parse(type_string, scope)
+ validate_legacy(scope, t, *args)
+ end
+
+ def validate_legacy(scope, target_type, function_name, value, *prev_args)
+ if assert_type(target_type, value)
+ if previous_validation(scope, function_name, value, *prev_args)
+ # Silently passes
+ else
+ Puppet.notice("Accepting previously invalid value for target type '#{target_type}'")
+ end
+ else
+ inferred_type = Puppet::Pops::Types::TypeCalculator.infer_set(value)
+ error_msg = Puppet::Pops::Types::TypeMismatchDescriber.new.describe_mismatch("validate_legacy(#{function_name})", target_type, inferred_type)
+ if previous_validation(scope, function_name, value, *prev_args)
+ call_function('deprecation', 'validate_legacy', error_msg)
+ else
+ call_function('fail', error_msg)
+ end
+ end
+ end
+
+ def previous_validation(scope, function_name, value, *prev_args)
+ # Call the previous validation function and catch any errors. Return true if no errors are thrown.
+ begin
+ scope.send("function_#{function_name}".to_s, [value, *prev_args])
+ true
+ rescue Puppet::ParseError
+ false
+ end
+ end
+
+ def assert_type(type, value)
+ Puppet::Pops::Types::TypeCalculator.instance?(type, value)
+ end
+end
diff --git a/lib/puppet/functions/validate_numeric.rb b/lib/puppet/functions/validate_numeric.rb
new file mode 100644
index 0000000..3052d35
--- /dev/null
+++ b/lib/puppet/functions/validate_numeric.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_numeric) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_numeric', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Numeric. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_numeric", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_re.rb b/lib/puppet/functions/validate_re.rb
new file mode 100644
index 0000000..19443a8
--- /dev/null
+++ b/lib/puppet/functions/validate_re.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_re) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_re', "This method is deprecated, please use the stdlib validate_legacy function, with Pattern[]. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_re", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_slength.rb b/lib/puppet/functions/validate_slength.rb
new file mode 100644
index 0000000..584232a
--- /dev/null
+++ b/lib/puppet/functions/validate_slength.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_slength) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_slength', "This method is deprecated, please use the stdlib validate_legacy function, with String[]. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_slength", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_string.rb b/lib/puppet/functions/validate_string.rb
new file mode 100644
index 0000000..91ff004
--- /dev/null
+++ b/lib/puppet/functions/validate_string.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_string) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_string', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::String. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_string", args)
+ end
+end
diff --git a/lib/puppet/parser/functions/any2bool.rb b/lib/puppet/parser/functions/any2bool.rb
new file mode 100644
index 0000000..f0f8f83
--- /dev/null
+++ b/lib/puppet/parser/functions/any2bool.rb
@@ -0,0 +1,55 @@
+#
+# any2bool.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:any2bool, :type => :rvalue, :doc => <<-EOS
+This converts 'anything' to a boolean. In practise it does the following:
+
+* Strings such as Y,y,1,T,t,TRUE,yes,'true' will return true
+* Strings such as 0,F,f,N,n,FALSE,no,'false' will return false
+* Booleans will just return their original value
+* Number (or a string representation of a number) > 0 will return true, otherwise false
+* undef will return false
+* Anything else will return true
+ EOS
+ ) do |arguments|
+
+ raise(Puppet::ParseError, "any2bool(): Wrong number of arguments " +
+ "given (#{arguments.size} for 1)") if arguments.size < 1
+
+ # If argument is already Boolean, return it
+ if !!arguments[0] == arguments[0]
+ return arguments[0]
+ end
+
+ arg = arguments[0]
+
+ if arg == nil
+ return false
+ end
+
+ if arg == :undef
+ return false
+ end
+
+ valid_float = !!Float(arg) rescue false
+
+ if arg.is_a?(Numeric)
+ return function_num2bool( [ arguments[0] ] )
+ end
+
+ if arg.is_a?(String)
+ if valid_float
+ return function_num2bool( [ arguments[0] ] )
+ else
+ return function_str2bool( [ arguments[0] ] )
+ end
+ end
+
+ return true
+
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/assert_private.rb b/lib/puppet/parser/functions/assert_private.rb
new file mode 100644
index 0000000..66c79cc
--- /dev/null
+++ b/lib/puppet/parser/functions/assert_private.rb
@@ -0,0 +1,29 @@
+#
+# assert_private.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:assert_private, :doc => <<-'EOS'
+ Sets the current class or definition as private.
+ Calling the class or definition from outside the current module will fail.
+ EOS
+ ) do |args|
+
+ raise(Puppet::ParseError, "assert_private(): Wrong number of arguments "+
+ "given (#{args.size}}) for 0 or 1)") if args.size > 1
+
+ scope = self
+ if scope.lookupvar('module_name') != scope.lookupvar('caller_module_name')
+ message = nil
+ if args[0] and args[0].is_a? String
+ message = args[0]
+ else
+ manifest_name = scope.source.name
+ manifest_type = scope.source.type
+ message = (manifest_type.to_s == 'hostclass') ? 'Class' : 'Definition'
+ message += " #{manifest_name} is private"
+ end
+ raise(Puppet::ParseError, message)
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/base64.rb b/lib/puppet/parser/functions/base64.rb
index 617ba31..a8998f2 100644
--- a/lib/puppet/parser/functions/base64.rb
+++ b/lib/puppet/parser/functions/base64.rb
@@ -6,14 +6,19 @@ module Puppet::Parser::Functions
Usage:
- $encodestring = base64('encode','thestring')
- $decodestring = base64('decode','dGhlc3RyaW5n')
+ $encodestring = base64('encode', 'thestring')
+ $decodestring = base64('decode', 'dGhlc3RyaW5n')
+
+ # explicitly define encode/decode method: default, strict, urlsafe
+ $method = 'default'
+ $encodestring = base64('encode', 'thestring', $method)
+ $decodestring = base64('decode', 'dGhlc3RyaW5n', $method)
ENDHEREDOC
require 'base64'
- raise Puppet::ParseError, ("base64(): Wrong number of arguments (#{args.length}; must be = 2)") unless args.length == 2
+ raise Puppet::ParseError, ("base64(): Wrong number of arguments (#{args.length}; must be >= 2)") unless args.length >= 2
actions = ['encode','decode']
@@ -25,11 +30,37 @@ module Puppet::Parser::Functions
raise Puppet::ParseError, ("base64(): the second argument must be a string to base64")
end
+ method = ['default','strict','urlsafe']
+
+ if args.length <= 2
+ chosenMethod = 'default'
+ else
+ chosenMethod = args[2]
+ end
+
+ unless method.include?(chosenMethod)
+ raise Puppet::ParseError, ("base64(): the third argument must be one of 'default', 'strict', or 'urlsafe'")
+ end
+
case args[0]
when 'encode'
- result = Base64.encode64(args[1])
+ case chosenMethod
+ when 'default'
+ result = Base64.encode64(args[1])
+ when 'strict'
+ result = Base64.strict_encode64(args[1])
+ when 'urlsafe'
+ result = Base64.urlsafe_encode64(args[1])
+ end
when 'decode'
- result = Base64.decode64(args[1])
+ case chosenMethod
+ when 'default'
+ result = Base64.decode64(args[1])
+ when 'strict'
+ result = Base64.strict_decode64(args[1])
+ when 'urlsafe'
+ result = Base64.urlsafe_decode64(args[1])
+ end
end
return result
diff --git a/lib/puppet/parser/functions/bool2str.rb b/lib/puppet/parser/functions/bool2str.rb
index fcd3791..7e36474 100644
--- a/lib/puppet/parser/functions/bool2str.rb
+++ b/lib/puppet/parser/functions/bool2str.rb
@@ -4,15 +4,29 @@
module Puppet::Parser::Functions
newfunction(:bool2str, :type => :rvalue, :doc => <<-EOS
- Converts a boolean to a string.
+ Converts a boolean to a string using optionally supplied arguments. The
+ optional second and third arguments represent what true and false will be
+ converted to respectively. If only one argument is given, it will be
+ converted from a boolean to a string containing 'true' or 'false'.
+
+ *Examples:*
+
+ bool2str(true) => 'true'
+ bool2str(true, 'yes', 'no') => 'yes'
+ bool2str(false, 't', 'f') => 'f'
+
Requires a single boolean as an input.
EOS
) do |arguments|
- raise(Puppet::ParseError, "bool2str(): Wrong number of arguments " +
- "given (#{arguments.size} for 1)") if arguments.size < 1
+ unless arguments.size == 1 or arguments.size == 3
+ raise(Puppet::ParseError, "bool2str(): Wrong number of arguments " +
+ "given (#{arguments.size} for 3)")
+ end
value = arguments[0]
+ true_string = arguments[1] || 'true'
+ false_string = arguments[2] || 'false'
klass = value.class
# We can have either true or false, and nothing else
@@ -20,7 +34,11 @@ module Puppet::Parser::Functions
raise(Puppet::ParseError, 'bool2str(): Requires a boolean to work with')
end
- return value.to_s
+ unless [true_string, false_string].all?{|x| x.kind_of?(String)}
+ raise(Puppet::ParseError, "bool2str(): Requires strings to convert to" )
+ end
+
+ return value ? true_string : false_string
end
end
diff --git a/lib/puppet/parser/functions/ceiling.rb b/lib/puppet/parser/functions/ceiling.rb
new file mode 100644
index 0000000..5f3b10b
--- /dev/null
+++ b/lib/puppet/parser/functions/ceiling.rb
@@ -0,0 +1,25 @@
+module Puppet::Parser::Functions
+ newfunction(:ceiling, :type => :rvalue, :doc => <<-EOS
+ Returns the smallest integer greater or equal to the argument.
+ Takes a single numeric value as an argument.
+ EOS
+ ) do |arguments|
+
+ raise(Puppet::ParseError, "ceiling(): Wrong number of arguments " +
+ "given (#{arguments.size} for 1)") if arguments.size != 1
+
+ begin
+ arg = Float(arguments[0])
+ rescue TypeError, ArgumentError => e
+ raise(Puppet::ParseError, "ceiling(): Wrong argument type " +
+ "given (#{arguments[0]} for Numeric)")
+ end
+
+ raise(Puppet::ParseError, "ceiling(): Wrong argument type " +
+ "given (#{arg.class} for Numeric)") if arg.is_a?(Numeric) == false
+
+ arg.ceil
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/clamp.rb b/lib/puppet/parser/functions/clamp.rb
new file mode 100644
index 0000000..432c7c1
--- /dev/null
+++ b/lib/puppet/parser/functions/clamp.rb
@@ -0,0 +1,30 @@
+#
+# clamp.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:clamp, :type => :rvalue, :arity => -2, :doc => <<-EOS
+ Clamps value to a range.
+ EOS
+ ) do |args|
+
+ args.flatten!
+
+ raise(Puppet::ParseError, 'clamp(): Wrong number of arguments, ' +
+ 'need three to clamp') if args.size != 3
+
+ # check values out
+ args.each do |value|
+ case [value.class]
+ when [String]
+ raise(Puppet::ParseError, "clamp(): Required explicit numeric (#{value}:String)") unless value =~ /^\d+$/
+ when [Hash]
+ raise(Puppet::ParseError, "clamp(): The Hash type is not allowed (#{value})")
+ end
+ end
+
+ # convert to numeric each element
+ # then sort them and get a middle value
+ args.map{ |n| n.to_i }.sort[1]
+ end
+end
diff --git a/lib/puppet/parser/functions/concat.rb b/lib/puppet/parser/functions/concat.rb
index 618e62d..91edb4e 100644
--- a/lib/puppet/parser/functions/concat.rb
+++ b/lib/puppet/parser/functions/concat.rb
@@ -31,7 +31,7 @@ Would result in:
arguments.shift
arguments.each do |x|
- result = result + Array(x)
+ result = result + (x.is_a?(Array) ? x : [x])
end
return result
diff --git a/lib/puppet/parser/functions/convert_base.rb b/lib/puppet/parser/functions/convert_base.rb
new file mode 100644
index 0000000..0fcbafe
--- /dev/null
+++ b/lib/puppet/parser/functions/convert_base.rb
@@ -0,0 +1,35 @@
+module Puppet::Parser::Functions
+
+ newfunction(:convert_base, :type => :rvalue, :arity => 2, :doc => <<-'ENDHEREDOC') do |args|
+
+ Converts a given integer or base 10 string representing an integer to a specified base, as a string.
+
+ Usage:
+
+ $binary_repr = convert_base(5, 2) # $binary_repr is now set to "101"
+ $hex_repr = convert_base("254", "16") # $hex_repr is now set to "fe"
+
+ ENDHEREDOC
+
+ raise Puppet::ParseError, ("convert_base(): First argument must be either a string or an integer") unless (args[0].is_a?(Integer) or args[0].is_a?(String))
+ raise Puppet::ParseError, ("convert_base(): Second argument must be either a string or an integer") unless (args[1].is_a?(Integer) or args[1].is_a?(String))
+
+ if args[0].is_a?(String)
+ raise Puppet::ParseError, ("convert_base(): First argument must be an integer or a string corresponding to an integer in base 10") unless args[0] =~ /^[0-9]+$/
+ end
+
+ if args[1].is_a?(String)
+ raise Puppet::ParseError, ("convert_base(): First argument must be an integer or a string corresponding to an integer in base 10") unless args[1] =~ /^[0-9]+$/
+ end
+
+ number_to_convert = args[0]
+ new_base = args[1]
+
+ number_to_convert = number_to_convert.to_i()
+ new_base = new_base.to_i()
+
+ raise Puppet::ParseError, ("convert_base(): base must be at least 2 and must not be greater than 36") unless new_base >= 2 and new_base <= 36
+
+ return number_to_convert.to_s(new_base)
+ end
+end
diff --git a/lib/puppet/parser/functions/defined_with_params.rb b/lib/puppet/parser/functions/defined_with_params.rb
index d7df306..99687ae 100644
--- a/lib/puppet/parser/functions/defined_with_params.rb
+++ b/lib/puppet/parser/functions/defined_with_params.rb
@@ -26,7 +26,10 @@ ENDOFDOC
ret = false
if resource = findresource(reference.to_s)
matches = params.collect do |key, value|
- resource[key] == value
+ # eql? avoids bugs caused by monkeypatching in puppet
+ resource_is_undef = resource[key].eql?(:undef) || resource[key].nil?
+ value_is_undef = value.eql?(:undef) || value.nil?
+ (resource_is_undef && value_is_undef) || (resource[key] == value)
end
ret = params.empty? || !matches.include?(false)
end
diff --git a/lib/puppet/parser/functions/delete.rb b/lib/puppet/parser/functions/delete.rb
index f548b44..466c55c 100644
--- a/lib/puppet/parser/functions/delete.rb
+++ b/lib/puppet/parser/functions/delete.rb
@@ -2,8 +2,6 @@
# delete.rb
#
-# TODO(Krzysztof Wilczynski): We need to add support for regular expression ...
-
module Puppet::Parser::Functions
newfunction(:delete, :type => :rvalue, :doc => <<-EOS
Deletes all instances of a given element from an array, substring from a
@@ -25,10 +23,8 @@ string, or key from a hash.
EOS
) do |arguments|
- if (arguments.size != 2) then
- raise(Puppet::ParseError, "delete(): Wrong number of arguments "+
- "given #{arguments.size} for 2.")
- end
+ raise(Puppet::ParseError, "delete(): Wrong number of arguments "+
+ "given #{arguments.size} for 2") unless arguments.size == 2
collection = arguments[0].dup
Array(arguments[1]).each do |item|
diff --git a/lib/puppet/parser/functions/delete_regex.rb b/lib/puppet/parser/functions/delete_regex.rb
new file mode 100644
index 0000000..d72b3e9
--- /dev/null
+++ b/lib/puppet/parser/functions/delete_regex.rb
@@ -0,0 +1,45 @@
+#
+# delete_regex.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:delete_regex, :type => :rvalue, :doc => <<-EOS
+deletes all instances of a given element that match a regular expression
+from an array or key from a hash. Multiple regular expressions are assumed
+to be matched as an OR.
+
+*Examples:*
+
+ delete_regex(['a','b','c','b'], 'b')
+ Would return: ['a','c']
+
+ delete_regex(['a','b','c','b'], ['b', 'c'])
+ Would return: ['a']
+
+ delete_regex({'a'=>1,'b'=>2,'c'=>3}, 'b')
+ Would return: {'a'=>1,'c'=>3}
+
+ delete_regex({'a'=>1,'b'=>2,'c'=>3}, '^a$')
+ Would return: {'b'=>2,'c'=>3}
+
+ EOS
+ ) do |arguments|
+
+ raise(Puppet::ParseError, "delete_regex(): Wrong number of arguments "+
+ "given #{arguments.size} for 2") unless arguments.size == 2
+
+ collection = arguments[0].dup
+ Array(arguments[1]).each do |item|
+ case collection
+ when Array, Hash, String
+ collection.reject! { |coll_item| (coll_item =~ %r{\b#{item}\b}) }
+ else
+ raise(TypeError, "delete_regex(): First argument must be an Array, " +
+ "Hash, or String. Given an argument of class #{collection.class}.")
+ end
+ end
+ collection
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/deprecation.rb b/lib/puppet/parser/functions/deprecation.rb
new file mode 100644
index 0000000..cd64fe2
--- /dev/null
+++ b/lib/puppet/parser/functions/deprecation.rb
@@ -0,0 +1,17 @@
+module Puppet::Parser::Functions
+ newfunction(:deprecation, :doc => <<-EOS
+ Function to print deprecation warnings (this is the 3.X version of it), The uniqueness key - can appear once. The msg is the message text including any positional information that is formatted by the user/caller of the method.).
+EOS
+ ) do |arguments|
+
+ raise(Puppet::ParseError, "deprecation: Wrong number of arguments " +
+ "given (#{arguments.size} for 2)") unless arguments.size == 2
+
+ key = arguments[0]
+ message = arguments[1]
+
+ if ENV['STDLIB_LOG_DEPRECATIONS'] == "true"
+ warning("deprecation. #{key}. #{message}")
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/dig.rb b/lib/puppet/parser/functions/dig.rb
new file mode 100644
index 0000000..34fa701
--- /dev/null
+++ b/lib/puppet/parser/functions/dig.rb
@@ -0,0 +1,16 @@
+#
+# dig.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:dig, :type => :rvalue, :doc => <<-EOS
+ DEPRECATED: This function has been replaced in Puppet 4.5.0, please use dig44() for backwards compatibility or use the new version.
+ EOS
+ ) do |arguments|
+ warning("dig() DEPRECATED: This function has been replaced in Puppet 4.5.0, please use dig44() for backwards compatibility or use the new version.")
+ if ! Puppet::Parser::Functions.autoloader.loaded?(:dig44)
+ Puppet::Parser::Functions.autoloader.load(:dig44)
+ end
+ function_dig44(arguments)
+ end
+end
diff --git a/lib/puppet/parser/functions/dig44.rb b/lib/puppet/parser/functions/dig44.rb
new file mode 100644
index 0000000..1e7c318
--- /dev/null
+++ b/lib/puppet/parser/functions/dig44.rb
@@ -0,0 +1,73 @@
+#
+# dig44.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(
+ :dig44,
+ :type => :rvalue,
+ :arity => -2,
+ :doc => <<-eos
+DEPRECATED: This function has been replaced in puppet 4.5.0.
+
+Looks up into a complex structure of arrays and hashes and returns a value
+or the default value if nothing was found.
+
+Key can contain slashes to describe path components. The function will go down
+the structure and try to extract the required value.
+
+$data = {
+ 'a' => {
+ 'b' => [
+ 'b1',
+ 'b2',
+ 'b3',
+ ]
+ }
+}
+
+$value = dig44($data, ['a', 'b', '2'], 'not_found')
+=> $value = 'b3'
+
+a -> first hash key
+b -> second hash key
+2 -> array index starting with 0
+
+not_found -> (optional) will be returned if there is no value or the path
+did not match. Defaults to nil.
+
+In addition to the required "key" argument, the function accepts a default
+argument. It will be returned if no value was found or a path component is
+missing. And the fourth argument can set a variable path separator.
+ eos
+ ) do |arguments|
+ # Two arguments are required
+ raise(Puppet::ParseError, "dig44(): Wrong number of arguments " +
+ "given (#{arguments.size} for at least 2)") if arguments.size < 2
+
+ data, path, default = *arguments
+
+ unless data.is_a?(Hash) or data.is_a?(Array)
+ raise(Puppet::ParseError, "dig44(): first argument must be a hash or an array, " <<
+ "given #{data.class.name}")
+ end
+
+ unless path.is_a? Array
+ raise(Puppet::ParseError, "dig44(): second argument must be an array, " <<
+ "given #{path.class.name}")
+ end
+
+ value = path.reduce(data) do |structure, key|
+ if structure.is_a? Hash or structure.is_a? Array
+ if structure.is_a? Array
+ key = Integer key rescue break
+ end
+ break if structure[key].nil? or structure[key] == :undef
+ structure[key]
+ else
+ break
+ end
+ end
+ value.nil? ? default : value
+ end
+end
diff --git a/lib/puppet/parser/functions/dirname.rb b/lib/puppet/parser/functions/dirname.rb
index ea8cc1e..40b300d 100644
--- a/lib/puppet/parser/functions/dirname.rb
+++ b/lib/puppet/parser/functions/dirname.rb
@@ -4,11 +4,17 @@ module Puppet::Parser::Functions
EOS
) do |arguments|
- raise(Puppet::ParseError, "dirname(): Wrong number of arguments " +
- "given (#{arguments.size} for 1)") if arguments.size < 1
+ if arguments.size < 1 then
+ raise(Puppet::ParseError, "dirname(): No arguments given")
+ end
+ if arguments.size > 1 then
+ raise(Puppet::ParseError, "dirname(): Too many arguments given (#{arguments.size})")
+ end
+ unless arguments[0].is_a?(String)
+ raise(Puppet::ParseError, 'dirname(): Requires string as argument')
+ end
- path = arguments[0]
- return File.dirname(path)
+ return File.dirname(arguments[0])
end
end
diff --git a/lib/puppet/parser/functions/dos2unix.rb b/lib/puppet/parser/functions/dos2unix.rb
new file mode 100644
index 0000000..ccac899
--- /dev/null
+++ b/lib/puppet/parser/functions/dos2unix.rb
@@ -0,0 +1,15 @@
+# Custom Puppet function to convert dos to unix format
+module Puppet::Parser::Functions
+ newfunction(:dos2unix, :type => :rvalue, :arity => 1, :doc => <<-EOS
+ Returns the Unix version of the given string.
+ Takes a single string argument.
+ EOS
+ ) do |arguments|
+
+ unless arguments[0].is_a?(String)
+ raise(Puppet::ParseError, 'dos2unix(): Requires string as argument')
+ end
+
+ arguments[0].gsub(/\r\n/, "\n")
+ end
+end
diff --git a/lib/puppet/parser/functions/empty.rb b/lib/puppet/parser/functions/empty.rb
index cca620f..b5a3cde 100644
--- a/lib/puppet/parser/functions/empty.rb
+++ b/lib/puppet/parser/functions/empty.rb
@@ -13,14 +13,18 @@ Returns true if the variable is empty.
value = arguments[0]
- unless value.is_a?(Array) || value.is_a?(Hash) || value.is_a?(String)
+ unless value.is_a?(Array) || value.is_a?(Hash) || value.is_a?(String) || value.is_a?(Numeric)
raise(Puppet::ParseError, 'empty(): Requires either ' +
- 'array, hash or string to work with')
+ 'array, hash, string or integer to work with')
end
- result = value.empty?
+ if value.is_a?(Numeric)
+ return false
+ else
+ result = value.empty?
- return result
+ return result
+ end
end
end
diff --git a/lib/puppet/parser/functions/enclose_ipv6.rb b/lib/puppet/parser/functions/enclose_ipv6.rb
new file mode 100644
index 0000000..80ffc3a
--- /dev/null
+++ b/lib/puppet/parser/functions/enclose_ipv6.rb
@@ -0,0 +1,45 @@
+#
+# enclose_ipv6.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:enclose_ipv6, :type => :rvalue, :doc => <<-EOS
+Takes an array of ip addresses and encloses the ipv6 addresses with square brackets.
+ EOS
+ ) do |arguments|
+
+ require 'ipaddr'
+
+ rescuable_exceptions = [ ArgumentError ]
+ if defined?(IPAddr::InvalidAddressError)
+ rescuable_exceptions << IPAddr::InvalidAddressError
+ end
+
+ if (arguments.size != 1) then
+ raise(Puppet::ParseError, "enclose_ipv6(): Wrong number of arguments "+
+ "given #{arguments.size} for 1")
+ end
+ unless arguments[0].is_a?(String) or arguments[0].is_a?(Array) then
+ raise(Puppet::ParseError, "enclose_ipv6(): Wrong argument type "+
+ "given #{arguments[0].class} expected String or Array")
+ end
+
+ input = [arguments[0]].flatten.compact
+ result = []
+
+ input.each do |val|
+ unless val == '*'
+ begin
+ ip = IPAddr.new(val)
+ rescue *rescuable_exceptions
+ raise(Puppet::ParseError, "enclose_ipv6(): Wrong argument "+
+ "given #{val} is not an ip address.")
+ end
+ val = "[#{ip.to_s}]" if ip.ipv6?
+ end
+ result << val
+ end
+
+ return result.uniq
+ end
+end
diff --git a/lib/puppet/parser/functions/ensure_packages.rb b/lib/puppet/parser/functions/ensure_packages.rb
index f1da4aa..439af1e 100644
--- a/lib/puppet/parser/functions/ensure_packages.rb
+++ b/lib/puppet/parser/functions/ensure_packages.rb
@@ -17,18 +17,29 @@ third argument to the ensure_resource() function.
raise(Puppet::ParseError, 'ensure_packages(): Requires second argument to be a Hash')
end
- packages = Array(arguments[0])
+ if arguments[0].is_a?(Hash)
+ if arguments[1]
+ defaults = { 'ensure' => 'present' }.merge(arguments[1])
+ else
+ defaults = { 'ensure' => 'present' }
+ end
- if arguments[1]
- defaults = { 'ensure' => 'present' }.merge(arguments[1])
+ Puppet::Parser::Functions.function(:ensure_resources)
+ function_ensure_resources(['package', arguments[0].dup, defaults ])
else
- defaults = { 'ensure' => 'present' }
- end
+ packages = Array(arguments[0])
+
+ if arguments[1]
+ defaults = { 'ensure' => 'present' }.merge(arguments[1])
+ else
+ defaults = { 'ensure' => 'present' }
+ end
- Puppet::Parser::Functions.function(:ensure_resource)
- packages.each { |package_name|
- function_ensure_resource(['package', package_name, defaults ])
+ Puppet::Parser::Functions.function(:ensure_resource)
+ packages.each { |package_name|
+ function_ensure_resource(['package', package_name, defaults ])
}
+ end
end
end
diff --git a/lib/puppet/parser/functions/ensure_resources.rb b/lib/puppet/parser/functions/ensure_resources.rb
new file mode 100644
index 0000000..b3c51e6
--- /dev/null
+++ b/lib/puppet/parser/functions/ensure_resources.rb
@@ -0,0 +1,54 @@
+require 'puppet/parser/functions'
+
+Puppet::Parser::Functions.newfunction(:ensure_resources,
+ :type => :statement,
+ :doc => <<-'ENDOFDOC'
+Takes a resource type, title (only hash), and a list of attributes that describe a
+resource.
+
+ user { 'dan':
+ gid => 'mygroup',
+ ensure => present,
+ }
+
+An hash of resources should be passed in and each will be created with
+the type and parameters specified if it doesn't already exist.
+
+ ensure_resources('user', {'dan' => { gid => 'mygroup', uid => '600' } , 'alex' => { gid => 'mygroup' }}, {'ensure' => 'present'})
+
+From Hiera Backend:
+
+userlist:
+ dan:
+ gid: 'mygroup'
+ uid: '600'
+ alex:
+ gid: 'mygroup'
+
+Call:
+ensure_resources('user', hiera_hash('userlist'), {'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 ||= {}
+
+ if title.is_a?(Hash)
+ resource_hash = title.dup
+ resources = resource_hash.keys
+
+ Puppet::Parser::Functions.function(:ensure_resource)
+ resources.each { |resource_name|
+ if resource_hash[resource_name]
+ params_merged = params.merge(resource_hash[resource_name])
+ else
+ params_merged = params
+ end
+ function_ensure_resource([ type, resource_name, params_merged ])
+ }
+ else
+ raise(Puppet::ParseError, 'ensure_resources(): Requires second argument to be a Hash')
+ end
+end
diff --git a/lib/puppet/parser/functions/fqdn_rand_string.rb b/lib/puppet/parser/functions/fqdn_rand_string.rb
new file mode 100644
index 0000000..2bb1287
--- /dev/null
+++ b/lib/puppet/parser/functions/fqdn_rand_string.rb
@@ -0,0 +1,34 @@
+Puppet::Parser::Functions::newfunction(
+ :fqdn_rand_string,
+ :arity => -2,
+ :type => :rvalue,
+ :doc => "Usage: `fqdn_rand_string(LENGTH, [CHARSET], [SEED])`. LENGTH is
+ required and must be a positive integer. CHARSET is optional and may be
+ `undef` or a string. SEED is optional and may be any number or string.
+
+ Generates a random string LENGTH characters long using the character set
+ provided by CHARSET, combining the `$fqdn` fact and the value of SEED for
+ repeatable randomness. (That is, each node will get a different random
+ string from this function, but a given node's result will be the same every
+ time unless its hostname changes.) Adding a SEED can be useful if you need
+ more than one unrelated string. CHARSET will default to alphanumeric if
+ `undef` or an empty string.") do |args|
+ raise(ArgumentError, "fqdn_rand_string(): wrong number of arguments (0 for 1)") if args.size == 0
+ Puppet::Parser::Functions.function('is_integer')
+ raise(ArgumentError, "fqdn_rand_string(): first argument must be a positive integer") unless function_is_integer([args[0]]) and args[0].to_i > 0
+ raise(ArgumentError, "fqdn_rand_string(): second argument must be undef or a string") unless args[1].nil? or args[1].is_a? String
+
+ Puppet::Parser::Functions.function('fqdn_rand')
+
+ length = args.shift.to_i
+ charset = args.shift.to_s.chars.to_a
+
+ charset = (0..9).map { |i| i.to_s } + ('A'..'Z').to_a + ('a'..'z').to_a if charset.empty?
+
+ rand_string = ''
+ for current in 1..length
+ rand_string << charset[function_fqdn_rand([charset.size, (args + [current.to_s]).join(':')]).to_i]
+ end
+
+ rand_string
+end
diff --git a/lib/puppet/parser/functions/fqdn_rotate.rb b/lib/puppet/parser/functions/fqdn_rotate.rb
index 7f4d37d..b66431d 100644
--- a/lib/puppet/parser/functions/fqdn_rotate.rb
+++ b/lib/puppet/parser/functions/fqdn_rotate.rb
@@ -2,16 +2,23 @@
# fqdn_rotate.rb
#
-module Puppet::Parser::Functions
- newfunction(:fqdn_rotate, :type => :rvalue, :doc => <<-EOS
-Rotates an array a random number of times based on a nodes fqdn.
- EOS
- ) do |arguments|
+Puppet::Parser::Functions.newfunction(
+ :fqdn_rotate,
+ :type => :rvalue,
+ :doc => "Usage: `fqdn_rotate(VALUE, [SEED])`. VALUE is required and
+ must be an array or a string. SEED is optional and may be any number
+ or string.
+
+ Rotates VALUE a random number of times, combining the `$fqdn` fact and
+ the value of SEED for repeatable randomness. (That is, each node will
+ get a different random rotation from this function, but a given node's
+ result will be the same every time unless its hostname changes.) Adding
+ a SEED can be useful if you need more than one unrelated rotation.") do |args|
raise(Puppet::ParseError, "fqdn_rotate(): Wrong number of arguments " +
- "given (#{arguments.size} for 1)") if arguments.size < 1
+ "given (#{args.size} for 1)") if args.size < 1
- value = arguments[0]
+ value = args.shift
require 'digest/md5'
unless value.is_a?(Array) || value.is_a?(String)
@@ -31,15 +38,26 @@ Rotates an array a random number of times based on a nodes fqdn.
elements = result.size
- srand(Digest::MD5.hexdigest([lookupvar('::fqdn'),arguments].join(':')).hex)
- rand(elements).times {
+ seed = Digest::MD5.hexdigest([lookupvar('::fqdn'),args].join(':')).hex
+ # deterministic_rand() was added in Puppet 3.2.0; reimplement if necessary
+ if Puppet::Util.respond_to?(:deterministic_rand)
+ offset = Puppet::Util.deterministic_rand(seed, elements).to_i
+ else
+ if defined?(Random) == 'constant' && Random.class == Class
+ offset = Random.new(seed).rand(elements)
+ else
+ old_seed = srand(seed)
+ offset = rand(elements)
+ srand(old_seed)
+ end
+ end
+ offset.times {
result.push result.shift
}
result = string ? result.join : result
return result
- end
end
# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/fqdn_uuid.rb b/lib/puppet/parser/functions/fqdn_uuid.rb
new file mode 100644
index 0000000..30205d0
--- /dev/null
+++ b/lib/puppet/parser/functions/fqdn_uuid.rb
@@ -0,0 +1,92 @@
+require 'digest/sha1'
+
+module Puppet::Parser::Functions
+ newfunction(:fqdn_uuid, :type => :rvalue, :doc => <<-END) do |args|
+
+ Creates a UUID based on a given string, assumed to be the FQDN
+
+ For example, to generate a UUID based on the FQDN of a system:
+
+ Usage:
+
+ $uuid = fqdn_uuid($::fqdn)
+
+ The generated UUID will be the same for the given hostname
+
+ The resulting UUID is returned on the form:
+
+ 1d839dea-5e10-5243-88eb-e66815bd7d5c
+
+ (u.e. without any curly braces.)
+
+ The generated UUID is a version 5 UUID with the V5 DNS namespace:
+
+ 6ba7b810-9dad-11d1-80b4-00c04fd430c8
+
+ This only supports a the V5 SHA-1 hash, using the DNS namespace.
+
+ Please consult http://www.ietf.org/rfc/rfc4122.txt for the details on
+ UUID generation and example implementation.
+
+ No verification is present at the moment as whether the domain name given
+ is in fact a correct fully-qualified domain name. Therefore any arbitrary
+ string and/or alpha-numeric value can subside for a domain name.
+ EOS
+
+ END
+
+ if args.length == 0
+ raise(ArgumentError, "fqdn_uuid: No arguments given")
+ elsif args.length == 1
+ fqdn = args[0]
+ else
+ raise(ArgumentError, "fqdn_uuid: Too many arguments given (#{args.length})")
+ end
+
+ # Code lovingly taken from
+ # https://github.com/puppetlabs/marionette-collective/blob/master/lib/mcollective/ssl.rb
+
+ # This is the UUID version 5 type DNS name space which is as follows:
+ #
+ # 6ba7b810-9dad-11d1-80b4-00c04fd430c8
+ #
+ uuid_name_space_dns = [0x6b,
+ 0xa7,
+ 0xb8,
+ 0x10,
+ 0x9d,
+ 0xad,
+ 0x11,
+ 0xd1,
+ 0x80,
+ 0xb4,
+ 0x00,
+ 0xc0,
+ 0x4f,
+ 0xd4,
+ 0x30,
+ 0xc8
+ ].map {|b| b.chr}.join
+
+ sha1 = Digest::SHA1.new
+ sha1.update(uuid_name_space_dns)
+ sha1.update(fqdn)
+
+ # first 16 bytes..
+ bytes = sha1.digest[0, 16].bytes.to_a
+
+ # version 5 adjustments
+ bytes[6] &= 0x0f
+ bytes[6] |= 0x50
+
+ # variant is DCE 1.1
+ bytes[8] &= 0x3f
+ bytes[8] |= 0x80
+
+ bytes = [4, 2, 2, 2, 6].collect do |i|
+ bytes.slice!(0, i).pack('C*').unpack('H*')
+ end
+
+ bytes.join('-')
+ end
+end
diff --git a/lib/puppet/parser/functions/getparam.rb b/lib/puppet/parser/functions/getparam.rb
index 6d51006..0a5cbe0 100644
--- a/lib/puppet/parser/functions/getparam.rb
+++ b/lib/puppet/parser/functions/getparam.rb
@@ -28,7 +28,7 @@ ENDOFDOC
return '' if param.empty?
if resource = findresource(reference.to_s)
- return resource[param] if resource[param]
+ return resource[param] unless resource[param].nil?
end
return ''
diff --git a/lib/puppet/parser/functions/getvar.rb b/lib/puppet/parser/functions/getvar.rb
index fb336b6..3af8d48 100644
--- a/lib/puppet/parser/functions/getvar.rb
+++ b/lib/puppet/parser/functions/getvar.rb
@@ -20,7 +20,13 @@ module Puppet::Parser::Functions
end
begin
- self.lookupvar("#{args[0]}")
+ result = nil
+ catch(:undefined_variable) do
+ result = self.lookupvar("#{args[0]}")
+ end
+
+ # avoid relying on incosistent behaviour around ruby return values from catch
+ result
rescue Puppet::ParseError # Eat the exception if strict_variables = true is set
end
diff --git a/lib/puppet/parser/functions/has_interface_with.rb b/lib/puppet/parser/functions/has_interface_with.rb
index 3691524..e762798 100644
--- a/lib/puppet/parser/functions/has_interface_with.rb
+++ b/lib/puppet/parser/functions/has_interface_with.rb
@@ -38,8 +38,11 @@ has_interface_with("lo") => true
# Bug with 3.7.1 - 3.7.3 when using future parser throws :undefined_variable
# https://tickets.puppetlabs.com/browse/PUP-3597
factval = nil
- catch :undefined_variable do
- factval = lookupvar(kind)
+ begin
+ catch :undefined_variable do
+ factval = lookupvar(kind)
+ end
+ rescue Puppet::ParseError # Eat the exception if strict_variables = true is set
end
if factval == value
return true
diff --git a/lib/puppet/parser/functions/hash.rb b/lib/puppet/parser/functions/hash.rb
index 8cc4823..89d0e07 100644
--- a/lib/puppet/parser/functions/hash.rb
+++ b/lib/puppet/parser/functions/hash.rb
@@ -29,7 +29,7 @@ Would return: {'a'=>1,'b'=>2,'c'=>3}
# This is to make it compatible with older version of Ruby ...
array = array.flatten
result = Hash[*array]
- rescue Exception
+ rescue StandardError
raise(Puppet::ParseError, 'hash(): Unable to compute ' +
'hash from array given')
end
diff --git a/lib/puppet/parser/functions/intersection.rb b/lib/puppet/parser/functions/intersection.rb
index 48f02e9..bfbb4ba 100644
--- a/lib/puppet/parser/functions/intersection.rb
+++ b/lib/puppet/parser/functions/intersection.rb
@@ -4,13 +4,13 @@
module Puppet::Parser::Functions
newfunction(:intersection, :type => :rvalue, :doc => <<-EOS
-This function returns an array an intersection of two.
+This function returns an array of the intersection of two.
*Examples:*
- intersection(["a","b","c"],["b","c","d"])
+ intersection(["a","b","c"],["b","c","d"]) # returns ["b","c"]
+ intersection(["a","b","c"],[1,2,3,4]) # returns [] (true, when evaluated as a Boolean)
-Would return: ["b","c"]
EOS
) do |arguments|
diff --git a/lib/puppet/parser/functions/is_absolute_path.rb b/lib/puppet/parser/functions/is_absolute_path.rb
new file mode 100644
index 0000000..e64777f
--- /dev/null
+++ b/lib/puppet/parser/functions/is_absolute_path.rb
@@ -0,0 +1,50 @@
+module Puppet::Parser::Functions
+ newfunction(:is_absolute_path, :type => :rvalue, :arity => 1, :doc => <<-'ENDHEREDOC') do |args|
+ Returns boolean true if the string represents an absolute path in the filesystem. This function works
+ for windows and unix style paths.
+
+ The following values will return true:
+
+ $my_path = 'C:/Program Files (x86)/Puppet Labs/Puppet'
+ is_absolute_path($my_path)
+ $my_path2 = '/var/lib/puppet'
+ is_absolute_path($my_path2)
+ $my_path3 = ['C:/Program Files (x86)/Puppet Labs/Puppet']
+ is_absolute_path($my_path3)
+ $my_path4 = ['/var/lib/puppet']
+ is_absolute_path($my_path4)
+
+ The following values will return false:
+
+ is_absolute_path(true)
+ is_absolute_path('../var/lib/puppet')
+ is_absolute_path('var/lib/puppet')
+ $undefined = undef
+ is_absolute_path($undefined)
+
+ ENDHEREDOC
+ function_deprecation([:is_absolute_path, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Absolute_path. There is further documentation for validate_legacy function in the README.'])
+ require 'puppet/util'
+
+ path = args[0]
+ # This logic was borrowed from
+ # [lib/puppet/file_serving/base.rb](https://github.com/puppetlabs/puppet/blob/master/lib/puppet/file_serving/base.rb)
+ # Puppet 2.7 and beyond will have Puppet::Util.absolute_path? Fall back to a back-ported implementation otherwise.
+ if Puppet::Util.respond_to?(:absolute_path?) then
+ value = (Puppet::Util.absolute_path?(path, :posix) or Puppet::Util.absolute_path?(path, :windows))
+ else
+ # This code back-ported from 2.7.x's lib/puppet/util.rb Puppet::Util.absolute_path?
+ # Determine in a platform-specific way whether a path is absolute. This
+ # defaults to the local platform if none is specified.
+ # Escape once for the string literal, and once for the regex.
+ slash = '[\\\\/]'
+ name = '[^\\\\/]+'
+ regexes = {
+ :windows => %r!^(([A-Z]:#{slash})|(#{slash}#{slash}#{name}#{slash}#{name})|(#{slash}#{slash}\?#{slash}#{name}))!i,
+ :posix => %r!^/!
+ }
+ value = (!!(path =~ regexes[:posix])) || (!!(path =~ regexes[:windows]))
+ end
+ value
+ end
+end
diff --git a/lib/puppet/parser/functions/is_array.rb b/lib/puppet/parser/functions/is_array.rb
index b39e184..1d2c0fa 100644
--- a/lib/puppet/parser/functions/is_array.rb
+++ b/lib/puppet/parser/functions/is_array.rb
@@ -8,6 +8,8 @@ Returns true if the variable passed to this function is an array.
EOS
) do |arguments|
+ function_deprecation([:is_array, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Array. There is further documentation for validate_legacy function in the README.'])
+
raise(Puppet::ParseError, "is_array(): Wrong number of arguments " +
"given (#{arguments.size} for 1)") if arguments.size < 1
@@ -18,5 +20,3 @@ Returns true if the variable passed to this function is an array.
return result
end
end
-
-# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/is_bool.rb b/lib/puppet/parser/functions/is_bool.rb
index 8bbdbc8..83d2ebe 100644
--- a/lib/puppet/parser/functions/is_bool.rb
+++ b/lib/puppet/parser/functions/is_bool.rb
@@ -8,6 +8,8 @@ Returns true if the variable passed to this function is a boolean.
EOS
) do |arguments|
+ function_deprecation([:is_bool, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Bool. There is further documentation for validate_legacy function in the README.'])
+
raise(Puppet::ParseError, "is_bool(): Wrong number of arguments " +
"given (#{arguments.size} for 1)") if arguments.size != 1
@@ -18,5 +20,3 @@ Returns true if the variable passed to this function is a boolean.
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
index b3fee96..90ede32 100644
--- a/lib/puppet/parser/functions/is_domain_name.rb
+++ b/lib/puppet/parser/functions/is_domain_name.rb
@@ -13,16 +13,16 @@ Returns true if the string passed to this function is a syntactically correct do
"given #{arguments.size} for 1")
end
- domain = arguments[0]
+ # Only allow string types
+ return false unless arguments[0].is_a?(String)
+
+ domain = arguments[0].dup
# Limits (rfc1035, 3.1)
domain_max_length=255
label_min_length=1
label_max_length=63
- # Only allow string types
- return false unless domain.is_a?(String)
-
# Allow ".", it is the top level domain
return true if domain == '.'
@@ -33,6 +33,10 @@ Returns true if the string passed to this function is a syntactically correct do
return false if domain.empty?
return false if domain.length > domain_max_length
+ # The top level domain must be alphabetic if there are multiple labels.
+ # See rfc1123, 2.1
+ return false if domain.include? '.' and not /\.[A-Za-z]+$/.match(domain)
+
# Check each label in the domain
labels = domain.split('.')
vlabels = labels.each do |label|
diff --git a/lib/puppet/parser/functions/is_email_address.rb b/lib/puppet/parser/functions/is_email_address.rb
new file mode 100644
index 0000000..4fb0229
--- /dev/null
+++ b/lib/puppet/parser/functions/is_email_address.rb
@@ -0,0 +1,21 @@
+#
+# is_email_address.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:is_email_address, :type => :rvalue, :doc => <<-EOS
+Returns true if the string passed to this function is a valid email address.
+ EOS
+ ) do |arguments|
+ if arguments.size != 1
+ raise(Puppet::ParseError, 'is_email_address(): Wrong number of arguments '\
+ "given #{arguments.size} for 1")
+ end
+
+ # Taken from http://emailregex.com/ (simpler regex)
+ valid_email_regex = %r{\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z}
+ return (arguments[0] =~ valid_email_regex) == 0
+ 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 a2da943..1186458 100644
--- a/lib/puppet/parser/functions/is_float.rb
+++ b/lib/puppet/parser/functions/is_float.rb
@@ -8,6 +8,8 @@ Returns true if the variable passed to this function is a float.
EOS
) do |arguments|
+ function_deprecation([:is_float, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Float. There is further documentation for validate_legacy function in the README.'])
+
if (arguments.size != 1) then
raise(Puppet::ParseError, "is_float(): Wrong number of arguments "+
"given #{arguments.size} for 1")
diff --git a/lib/puppet/parser/functions/is_integer.rb b/lib/puppet/parser/functions/is_integer.rb
index c03d28d..e04fd1f 100644
--- a/lib/puppet/parser/functions/is_integer.rb
+++ b/lib/puppet/parser/functions/is_integer.rb
@@ -13,6 +13,8 @@ If given any other argument `false` is returned.
EOS
) do |arguments|
+ function_deprecation([:is_integer, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Integer. There is further documentation for validate_legacy function in the README.'])
+
if (arguments.size != 1) then
raise(Puppet::ParseError, "is_integer(): Wrong number of arguments "+
"given #{arguments.size} for 1")
diff --git a/lib/puppet/parser/functions/is_ip_address.rb b/lib/puppet/parser/functions/is_ip_address.rb
index a90adab..5f1d765 100644
--- a/lib/puppet/parser/functions/is_ip_address.rb
+++ b/lib/puppet/parser/functions/is_ip_address.rb
@@ -10,6 +10,8 @@ Returns true if the string passed to this function is a valid IP address.
require 'ipaddr'
+ function_deprecation([:is_ip_address, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ip_address. There is further documentation for validate_legacy function in the README.'])
+
if (arguments.size != 1) then
raise(Puppet::ParseError, "is_ip_address(): Wrong number of arguments "+
"given #{arguments.size} for 1")
diff --git a/lib/puppet/parser/functions/is_ipv4_address.rb b/lib/puppet/parser/functions/is_ipv4_address.rb
new file mode 100644
index 0000000..1764e61
--- /dev/null
+++ b/lib/puppet/parser/functions/is_ipv4_address.rb
@@ -0,0 +1,30 @@
+#
+# is_ipv4_address.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:is_ipv4_address, :type => :rvalue, :doc => <<-EOS
+Returns true if the string passed to this function is a valid IPv4 address.
+ EOS
+ ) do |arguments|
+
+ require 'ipaddr'
+
+ function_deprecation([:is_ipv4_address, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ipv4. There is further documentation for validate_legacy function in the README.'])
+
+ if (arguments.size != 1) then
+ raise(Puppet::ParseError, "is_ipv4_address(): Wrong number of arguments "+
+ "given #{arguments.size} for 1")
+ end
+
+ begin
+ ip = IPAddr.new(arguments[0])
+ rescue ArgumentError
+ return false
+ end
+
+ return ip.ipv4?
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/is_ipv6_address.rb b/lib/puppet/parser/functions/is_ipv6_address.rb
new file mode 100644
index 0000000..7ca4997
--- /dev/null
+++ b/lib/puppet/parser/functions/is_ipv6_address.rb
@@ -0,0 +1,30 @@
+#
+# is_ipv6_address.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:is_ipv6_address, :type => :rvalue, :doc => <<-EOS
+Returns true if the string passed to this function is a valid IPv6 address.
+ EOS
+ ) do |arguments|
+
+ function_deprecation([:is_ipv6_address, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ipv6. There is further documentation for validate_legacy function in the README.'])
+
+ require 'ipaddr'
+
+ if (arguments.size != 1) then
+ raise(Puppet::ParseError, "is_ipv6_address(): Wrong number of arguments "+
+ "given #{arguments.size} for 1")
+ end
+
+ begin
+ ip = IPAddr.new(arguments[0])
+ rescue ArgumentError
+ return false
+ end
+
+ return ip.ipv6?
+ 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
index 1b3088a..2619d44 100644
--- a/lib/puppet/parser/functions/is_mac_address.rb
+++ b/lib/puppet/parser/functions/is_mac_address.rb
@@ -15,7 +15,7 @@ Returns true if the string passed to this function is a valid mac address.
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
+ if /^[a-f0-9]{1,2}(:[a-f0-9]{1,2}){5}$/i.match(mac) then
return true
else
return false
diff --git a/lib/puppet/parser/functions/is_numeric.rb b/lib/puppet/parser/functions/is_numeric.rb
index e7e1d2a..4a55225 100644
--- a/lib/puppet/parser/functions/is_numeric.rb
+++ b/lib/puppet/parser/functions/is_numeric.rb
@@ -24,6 +24,8 @@ Valid examples:
EOS
) do |arguments|
+ function_deprecation([:is_numeric, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Numeric. There is further documentation for validate_legacy function in the README.'])
+
if (arguments.size != 1) then
raise(Puppet::ParseError, "is_numeric(): Wrong number of arguments "+
"given #{arguments.size} for 1")
@@ -71,5 +73,3 @@ Valid examples:
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
index f5bef04..31ee91e 100644
--- a/lib/puppet/parser/functions/is_string.rb
+++ b/lib/puppet/parser/functions/is_string.rb
@@ -8,12 +8,15 @@ Returns true if the variable passed to this function is a string.
EOS
) do |arguments|
+ function_deprecation([:is_string, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::String. There is further documentation for validate_legacy function in the README.'])
+
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)
+ # when called through the v4 API shim, undef gets translated to nil
+ result = type.is_a?(String) || type.nil?
if result and (type == type.to_f.to_s or type == type.to_i.to_s) then
return false
diff --git a/lib/puppet/parser/functions/join_keys_to_values.rb b/lib/puppet/parser/functions/join_keys_to_values.rb
index e9924fe..e3baf9f 100644
--- a/lib/puppet/parser/functions/join_keys_to_values.rb
+++ b/lib/puppet/parser/functions/join_keys_to_values.rb
@@ -5,7 +5,8 @@
module Puppet::Parser::Functions
newfunction(:join_keys_to_values, :type => :rvalue, :doc => <<-EOS
This function joins each key of a hash to that key's corresponding value with a
-separator. Keys and values are cast to strings. The return value is an array in
+separator. Keys are cast to strings. If values are arrays, multiple keys
+are added for each element. The return value is an array in
which each element is one joined key/value pair.
*Examples:*
@@ -13,6 +14,10 @@ which each element is one joined key/value pair.
join_keys_to_values({'a'=>1,'b'=>2}, " is ")
Would result in: ["a is 1","b is 2"]
+
+ join_keys_to_values({'a'=>1,'b'=>[2,3]}, " is ")
+
+Would result in: ["a is 1","b is 2","b is 3"]
EOS
) do |arguments|
@@ -38,8 +43,12 @@ Would result in: ["a is 1","b is 2"]
# Join the keys to their values.
hash.map do |k,v|
- String(k) + separator + String(v)
- end
+ if v.is_a?(Array)
+ v.map { |va| String(k) + separator + String(va) }
+ else
+ String(k) + separator + String(v)
+ end
+ end.flatten
end
end
diff --git a/lib/puppet/parser/functions/load_module_metadata.rb b/lib/puppet/parser/functions/load_module_metadata.rb
new file mode 100644
index 0000000..c9b8488
--- /dev/null
+++ b/lib/puppet/parser/functions/load_module_metadata.rb
@@ -0,0 +1,24 @@
+module Puppet::Parser::Functions
+ newfunction(:load_module_metadata, :type => :rvalue, :doc => <<-EOT
+ EOT
+ ) do |args|
+ raise(Puppet::ParseError, "load_module_metadata(): Wrong number of arguments, expects one or two") unless [1,2].include?(args.size)
+ mod = args[0]
+ allow_empty_metadata = args[1]
+ module_path = function_get_module_path([mod])
+ metadata_json = File.join(module_path, 'metadata.json')
+
+ metadata_exists = File.exists?(metadata_json)
+ if metadata_exists
+ metadata = PSON.load(File.read(metadata_json))
+ else
+ if allow_empty_metadata
+ metadata = {}
+ else
+ raise(Puppet::ParseError, "load_module_metadata(): No metadata.json file for module #{mod}")
+ end
+ end
+
+ return metadata
+ end
+end
diff --git a/lib/puppet/parser/functions/loadjson.rb b/lib/puppet/parser/functions/loadjson.rb
new file mode 100644
index 0000000..3a3372b
--- /dev/null
+++ b/lib/puppet/parser/functions/loadjson.rb
@@ -0,0 +1,34 @@
+module Puppet::Parser::Functions
+ newfunction(:loadjson, :type => :rvalue, :arity => -2, :doc => <<-'ENDHEREDOC') do |args|
+Load a JSON file containing an array, string, or hash, and return the data
+in the corresponding native data type.
+The second parameter is the default value. It will be returned if the file
+was not found or could not be parsed.
+
+For example:
+
+ $myhash = loadjson('/etc/puppet/data/myhash.json')
+ $myhash = loadjson('no-file.json', {'default' => 'value'})
+ ENDHEREDOC
+
+ raise ArgumentError, 'Wrong number of arguments. 1 or 2 arguments should be provided.' unless args.length >= 1
+
+ if File.exists?(args[0])
+ begin
+ content = File.read(args[0])
+ PSON::load(content) || args[1]
+ rescue Exception => e
+ if args[1]
+ args[1]
+ else
+ raise e
+ end
+ end
+ else
+ warning("Can't load '#{args[0]}' File does not exist!")
+ args[1]
+ end
+
+ end
+
+end
diff --git a/lib/puppet/parser/functions/loadyaml.rb b/lib/puppet/parser/functions/loadyaml.rb
index 10c4005..9696362 100644
--- a/lib/puppet/parser/functions/loadyaml.rb
+++ b/lib/puppet/parser/functions/loadyaml.rb
@@ -1,20 +1,34 @@
module Puppet::Parser::Functions
+ newfunction(:loadyaml, :type => :rvalue, :arity => -2, :doc => <<-'ENDHEREDOC') do |args|
+Load a YAML file containing an array, string, or hash, and return the data
+in the corresponding native data type.
+The second parameter is the default value. It will be returned if the file
+was not found or could not be parsed.
- newfunction(:loadyaml, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
- Load a YAML file containing an array, string, or hash, and return the data
- in the corresponding native data type.
+For example:
- For example:
+ $myhash = loadyaml('/etc/puppet/data/myhash.yaml')
+ $myhash = loadyaml('no-file.yaml', {'default' => 'value'})
+ ENDHEREDOC
- $myhash = loadyaml('/etc/puppet/data/myhash.yaml')
- ENDHEREDOC
+ raise ArgumentError, 'Wrong number of arguments. 1 or 2 arguments should be provided.' unless args.length >= 1
+ require 'yaml'
- unless args.length == 1
- raise Puppet::ParseError, ("loadyaml(): wrong number of arguments (#{args.length}; must be 1)")
+ if File.exists?(args[0])
+ begin
+ YAML::load_file(args[0]) || args[1]
+ rescue Exception => e
+ if args[1]
+ args[1]
+ else
+ raise e
+ end
+ end
+ else
+ warning("Can't load '#{args[0]}' File does not exist!")
+ args[1]
end
- YAML.load_file(args[0])
-
end
end
diff --git a/lib/puppet/parser/functions/member.rb b/lib/puppet/parser/functions/member.rb
index 88609ce..1e5b3de 100644
--- a/lib/puppet/parser/functions/member.rb
+++ b/lib/puppet/parser/functions/member.rb
@@ -44,7 +44,7 @@ would return: false
end
if arguments[1].is_a? String or arguments[1].is_a? Fixnum
- item = Array(arguments[1])
+ item = [arguments[1]]
else
item = arguments[1]
end
diff --git a/lib/puppet/parser/functions/parsejson.rb b/lib/puppet/parser/functions/parsejson.rb
index a9a16a4..f7c2896 100644
--- a/lib/puppet/parser/functions/parsejson.rb
+++ b/lib/puppet/parser/functions/parsejson.rb
@@ -4,20 +4,25 @@
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
+This function accepts JSON as a string and converts it into the correct
+Puppet structure.
+
+The optional second argument can be used to pass a default value that will
+be returned if the parsing of YAML string have failed.
+ EOS
) do |arguments|
+ raise ArgumentError, 'Wrong number of arguments. 1 or 2 arguments should be provided.' unless arguments.length >= 1
- if (arguments.size != 1) then
- raise(Puppet::ParseError, "parsejson(): Wrong number of arguments "+
- "given #{arguments.size} for 1")
+ begin
+ PSON::load(arguments[0]) || arguments[1]
+ rescue StandardError => e
+ if arguments[1]
+ arguments[1]
+ else
+ raise e
+ end
end
- json = arguments[0]
-
- # PSON is natively available in puppet
- PSON.load(json)
end
end
diff --git a/lib/puppet/parser/functions/parseyaml.rb b/lib/puppet/parser/functions/parseyaml.rb
index 53d54fa..ba9d98a 100644
--- a/lib/puppet/parser/functions/parseyaml.rb
+++ b/lib/puppet/parser/functions/parseyaml.rb
@@ -6,17 +6,26 @@ 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
+The optional second argument can be used to pass a default value that will
+be returned if the parsing of YAML string have failed.
+ EOS
+ ) do |arguments|
+ raise ArgumentError, 'Wrong number of arguments. 1 or 2 arguments should be provided.' unless arguments.length >= 1
require 'yaml'
- YAML::load(arguments[0])
+ begin
+ YAML::load(arguments[0]) || arguments[1]
+ # in ruby 1.9.3 Psych::SyntaxError is a RuntimeException
+ # this still needs to catch that and work also on rubies that
+ # do not have Psych available.
+ rescue StandardError, Psych::SyntaxError => e
+ if arguments[1]
+ arguments[1]
+ else
+ raise e
+ end
+ end
end
end
diff --git a/lib/puppet/parser/functions/prefix.rb b/lib/puppet/parser/functions/prefix.rb
index d02286a..ac1c58a 100644
--- a/lib/puppet/parser/functions/prefix.rb
+++ b/lib/puppet/parser/functions/prefix.rb
@@ -4,7 +4,7 @@
module Puppet::Parser::Functions
newfunction(:prefix, :type => :rvalue, :doc => <<-EOS
-This function applies a prefix to all elements in an array.
+This function applies a prefix to all elements in an array or a hash.
*Examples:*
@@ -18,10 +18,10 @@ Will return: ['pa','pb','pc']
raise(Puppet::ParseError, "prefix(): Wrong number of arguments " +
"given (#{arguments.size} for 1)") if arguments.size < 1
- array = arguments[0]
+ enumerable = arguments[0]
- unless array.is_a?(Array)
- raise Puppet::ParseError, "prefix(): expected first argument to be an Array, got #{array.inspect}"
+ unless enumerable.is_a?(Array) or enumerable.is_a?(Hash)
+ raise Puppet::ParseError, "prefix(): expected first argument to be an Array or a Hash, got #{enumerable.inspect}"
end
prefix = arguments[1] if arguments[1]
@@ -32,10 +32,17 @@ Will return: ['pa','pb','pc']
end
end
- # Turn everything into string same as join would do ...
- result = array.collect do |i|
- i = i.to_s
- prefix ? prefix + i : i
+ if enumerable.is_a?(Array)
+ # Turn everything into string same as join would do ...
+ result = enumerable.collect do |i|
+ i = i.to_s
+ prefix ? prefix + i : i
+ end
+ else
+ result = Hash[enumerable.map do |k,v|
+ k = k.to_s
+ [ prefix ? prefix + k : k, v ]
+ end]
end
return result
diff --git a/lib/puppet/parser/functions/private.rb b/lib/puppet/parser/functions/private.rb
index 60210d3..3b00ba1 100644
--- a/lib/puppet/parser/functions/private.rb
+++ b/lib/puppet/parser/functions/private.rb
@@ -4,26 +4,14 @@
module Puppet::Parser::Functions
newfunction(:private, :doc => <<-'EOS'
- Sets the current class or definition as private.
+ DEPRECATED: Sets the current class or definition as private.
Calling the class or definition from outside the current module will fail.
- EOS
+ EOS
) do |args|
-
- raise(Puppet::ParseError, "private(): Wrong number of arguments "+
- "given (#{args.size}}) for 0 or 1)") if args.size > 1
-
- scope = self
- if scope.lookupvar('module_name') != scope.lookupvar('caller_module_name')
- message = nil
- if args[0] and args[0].is_a? String
- message = args[0]
- else
- manifest_name = scope.source.name
- manifest_type = scope.source.type
- message = (manifest_type.to_s == 'hostclass') ? 'Class' : 'Definition'
- message += " #{manifest_name} is private"
- end
- raise(Puppet::ParseError, message)
+ warning("private() DEPRECATED: This function will cease to function on Puppet 4; please use assert_private() before upgrading to puppet 4 for backwards-compatibility, or migrate to the new parser's typing system.")
+ if !Puppet::Parser::Functions.autoloader.loaded?(:assert_private)
+ Puppet::Parser::Functions.autoloader.load(:assert_private)
end
+ function_assert_private([(args[0] unless args.size < 1)])
end
end
diff --git a/lib/puppet/parser/functions/pry.rb b/lib/puppet/parser/functions/pry.rb
new file mode 100644
index 0000000..c18ef7e
--- /dev/null
+++ b/lib/puppet/parser/functions/pry.rb
@@ -0,0 +1,30 @@
+#
+# pry.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:pry, :type => :statement, :doc => <<-EOS
+This function invokes a pry debugging session in the current scope object. This is useful for debugging manifest code at specific points during a compilation.
+
+*Examples:*
+
+ pry()
+ EOS
+ ) do |arguments|
+ begin
+ require 'pry'
+ rescue LoadError
+ raise(Puppet::Error, "pry(): Requires the 'pry' rubygem to use, but it was not found")
+ end
+ #
+ ## Run `catalog` to see the contents currently compiling catalog
+ ## Run `cd catalog` and `ls` to see catalog methods and instance variables
+ ## Run `@resource_table` to see the current catalog resource table
+ #
+ if $stdout.isatty
+ binding.pry # rubocop:disable Lint/Debugger
+ else
+ Puppet.warning 'pry(): cowardly refusing to start the debugger on a daemonized master'
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/pw_hash.rb b/lib/puppet/parser/functions/pw_hash.rb
new file mode 100644
index 0000000..41d4223
--- /dev/null
+++ b/lib/puppet/parser/functions/pw_hash.rb
@@ -0,0 +1,56 @@
+Puppet::Parser::Functions::newfunction(
+ :pw_hash,
+ :type => :rvalue,
+ :arity => 3,
+ :doc => "Hashes a password using the crypt function. Provides a hash
+ usable on most POSIX systems.
+
+ The first argument to this function is the password to hash. If it is
+ undef or an empty string, this function returns undef.
+
+ The second argument to this function is which type of hash to use. It
+ will be converted into the appropriate crypt(3) hash specifier. Valid
+ hash types are:
+
+ |Hash type |Specifier|
+ |---------------------|---------|
+ |MD5 |1 |
+ |SHA-256 |5 |
+ |SHA-512 (recommended)|6 |
+
+ The third argument to this function is the salt to use.
+
+ Note: this uses the Puppet Master's implementation of crypt(3). If your
+ environment contains several different operating systems, ensure that they
+ are compatible before using this function.") do |args|
+ raise ArgumentError, "pw_hash(): wrong number of arguments (#{args.size} for 3)" if args.size != 3
+ raise ArgumentError, "pw_hash(): first argument must be a string" unless args[0].is_a? String or args[0].nil?
+ raise ArgumentError, "pw_hash(): second argument must be a string" unless args[1].is_a? String
+ hashes = { 'md5' => '1',
+ 'sha-256' => '5',
+ 'sha-512' => '6' }
+ hash_type = hashes[args[1].downcase]
+ raise ArgumentError, "pw_hash(): #{args[1]} is not a valid hash type" if hash_type.nil?
+ raise ArgumentError, "pw_hash(): third argument must be a string" unless args[2].is_a? String
+ raise ArgumentError, "pw_hash(): third argument must not be empty" if args[2].empty?
+ raise ArgumentError, "pw_hash(): characters in salt must be in the set [a-zA-Z0-9./]" unless args[2].match(/\A[a-zA-Z0-9.\/]+\z/)
+
+ password = args[0]
+ return nil if password.nil? or password.empty?
+
+ salt = "$#{hash_type}$#{args[2]}"
+
+ # handle weak implementations of String#crypt
+ if 'test'.crypt('$1$1') != '$1$1$Bp8CU9Oujr9SSEw53WV6G.'
+ # JRuby < 1.7.17
+ if RUBY_PLATFORM == 'java'
+ # puppetserver bundles Apache Commons Codec
+ org.apache.commons.codec.digest.Crypt.crypt(password.to_java_bytes, salt)
+ else
+ # MS Windows and other systems that don't support enhanced salts
+ raise Puppet::ParseError, 'system does not support enhanced salts'
+ end
+ else
+ password.crypt(salt)
+ end
+end
diff --git a/lib/puppet/parser/functions/range.rb b/lib/puppet/parser/functions/range.rb
index 49fba21..d690df7 100644
--- a/lib/puppet/parser/functions/range.rb
+++ b/lib/puppet/parser/functions/range.rb
@@ -25,8 +25,8 @@ integers automatically)
Will return: ["a","b","c"]
range("host01", "host10")
-
Will return: ["host01", "host02", ..., "host09", "host10"]
+NB Be explicit in including trailing zeros. Otherwise the underlying ruby function will fail.
Passing a third argument will cause the generated range to step by that
interval, e.g.
@@ -37,18 +37,17 @@ Will return: [0,2,4,6,8]
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
+ raise(Puppet::ParseError, 'range(): Wrong number of ' +
+ 'arguments given (0 for 1)') if arguments.size == 0
if arguments.size > 1
start = arguments[0]
stop = arguments[1]
step = arguments[2].nil? ? 1 : arguments[2].to_i.abs
- type = '..' # We select simplest type for Range available in Ruby ...
+ type = '..' # Use the simplest type of Range available in Ruby
- elsif arguments.size > 0
+ else # arguments.size == 1
value = arguments[0]
if m = value.match(/^(\w+)(\.\.\.?|\-)(\w+)$/)
@@ -56,16 +55,16 @@ Will return: [0,2,4,6,8]
stop = m[3]
type = m[2]
-
+ step = 1
elsif value.match(/^.+$/)
- raise(Puppet::ParseError, 'range(): Unable to compute range ' +
- 'from the value given')
+ raise(Puppet::ParseError, "range(): Unable to compute range " +
+ "from the value: #{value}")
else
- raise(Puppet::ParseError, 'range(): Unknown format of range given')
+ raise(Puppet::ParseError, "range(): Unknown range format: #{value}")
end
end
- # Check whether we have integer value if so then make it so ...
+ # If we were given an integer, ensure we work with one
if start.to_s.match(/^\d+$/)
start = start.to_i
stop = stop.to_i
@@ -76,10 +75,10 @@ Will return: [0,2,4,6,8]
range = case type
when /^(\.\.|\-)$/ then (start .. stop)
- when /^(\.\.\.)$/ then (start ... stop) # Exclusive of last element ...
+ when '...' then (start ... stop) # Exclusive of last element
end
- result = range.step(step).collect { |i| i } # Get them all ... Pokemon ...
+ result = range.step(step).to_a
return result
end
diff --git a/lib/puppet/parser/functions/regexpescape.rb b/lib/puppet/parser/functions/regexpescape.rb
new file mode 100644
index 0000000..477ee87
--- /dev/null
+++ b/lib/puppet/parser/functions/regexpescape.rb
@@ -0,0 +1,31 @@
+#
+# regexpescape.rb
+#
+module Puppet::Parser::Functions
+ newfunction(:regexpescape, :type => :rvalue, :doc => <<-EOS
+ Regexp escape a string or array of strings.
+ Requires either a single string or an array as an input.
+ EOS
+ ) do |arguments| # rubocop:disable Style/ClosingParenthesisIndentation
+ raise(Puppet::ParseError, 'regexpescape(): Wrong number of arguments ' \
+ "given (#{arguments.size} for 1)") if arguments.empty?
+
+ value = arguments[0]
+
+ unless value.is_a?(Array) || value.is_a?(String)
+ raise(Puppet::ParseError, 'regexpescape(): Requires either ' \
+ 'array or string to work with')
+ end
+
+ result = if value.is_a?(Array)
+ # Numbers in Puppet are often string-encoded which is troublesome ...
+ value.collect { |i| i.is_a?(String) ? Regexp.escape(i) : i }
+ else
+ Regexp.escape(value)
+ end
+
+ return result
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/seeded_rand.rb b/lib/puppet/parser/functions/seeded_rand.rb
new file mode 100644
index 0000000..44e27b8
--- /dev/null
+++ b/lib/puppet/parser/functions/seeded_rand.rb
@@ -0,0 +1,22 @@
+Puppet::Parser::Functions::newfunction(
+ :seeded_rand,
+ :arity => 2,
+ :type => :rvalue,
+ :doc => <<-EOS
+Usage: `seeded_rand(MAX, SEED)`. MAX must be a positive integer; SEED is any string.
+
+Generates a random whole number greater than or equal to 0 and less
+than MAX, using the value of SEED for repeatable randomness. If SEED
+starts with "$fqdn:", this is behaves the same as `fqdn_rand`.
+
+EOS
+) do |args|
+ require 'digest/md5'
+
+ raise(ArgumentError, "seeded_rand(): first argument must be a positive integer") unless function_is_integer([args[0]]) and args[0].to_i > 0
+ raise(ArgumentError, "seeded_rand(): second argument must be a string") unless args[1].is_a? String
+
+ max = args[0].to_i
+ seed = Digest::MD5.hexdigest(args[1]).hex
+ Puppet::Util.deterministic_rand(seed,max)
+end
diff --git a/lib/puppet/parser/functions/shell_escape.rb b/lib/puppet/parser/functions/shell_escape.rb
new file mode 100644
index 0000000..447fe35
--- /dev/null
+++ b/lib/puppet/parser/functions/shell_escape.rb
@@ -0,0 +1,30 @@
+#
+# shell_escape.rb
+#
+
+require 'shellwords'
+
+module Puppet::Parser::Functions
+ newfunction(:shell_escape, :type => :rvalue, :doc => <<-EOS
+Escapes a string so that it can be safely used in a Bourne shell command line.
+
+Note that the resulting string should be used unquoted and is not intended for use in double quotes nor in single
+quotes.
+
+This function behaves the same as ruby's Shellwords.shellescape() function.
+ EOS
+ ) do |arguments|
+
+ raise(Puppet::ParseError, "shell_escape(): Wrong number of arguments " +
+ "given (#{arguments.size} for 1)") if arguments.size != 1
+
+ # explicit conversion to string is required for ruby 1.9
+ string = arguments[0].to_s
+
+ result = Shellwords.shellescape(string)
+
+ return result
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/shell_join.rb b/lib/puppet/parser/functions/shell_join.rb
new file mode 100644
index 0000000..05aeb95
--- /dev/null
+++ b/lib/puppet/parser/functions/shell_join.rb
@@ -0,0 +1,31 @@
+#
+# shell_join.rb
+#
+
+require 'shellwords'
+
+module Puppet::Parser::Functions
+ newfunction(:shell_join, :type => :rvalue, :doc => <<-EOS
+Builds a command line string from the given array of strings. Each array item is escaped for Bourne shell. All items are
+then joined together, with a single space in between.
+
+This function behaves the same as ruby's Shellwords.shelljoin() function
+ EOS
+ ) do |arguments|
+
+ raise(Puppet::ParseError, "shell_join(): Wrong number of arguments " +
+ "given (#{arguments.size} for 1)") if arguments.size != 1
+
+ array = arguments[0]
+
+ raise Puppet::ParseError, ("First argument is not an Array: #{array.inspect}") unless array.is_a?(Array)
+
+ # explicit conversion to string is required for ruby 1.9
+ array = array.map { |item| item.to_s }
+ result = Shellwords.shelljoin(array)
+
+ return result
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/shell_split.rb b/lib/puppet/parser/functions/shell_split.rb
new file mode 100644
index 0000000..0446448
--- /dev/null
+++ b/lib/puppet/parser/functions/shell_split.rb
@@ -0,0 +1,26 @@
+#
+# shell_split.rb
+#
+
+require 'shellwords'
+
+module Puppet::Parser::Functions
+ newfunction(:shell_split, :type => :rvalue, :doc => <<-EOS
+Splits a string into an array of tokens in the same way the Bourne shell does.
+
+This function behaves the same as ruby's Shellwords.shellsplit() function
+ EOS
+ ) do |arguments|
+
+ raise(Puppet::ParseError, "shell_split(): Wrong number of arguments " +
+ "given (#{arguments.size} for 1)") if arguments.size != 1
+
+ string = arguments[0].to_s
+
+ result = Shellwords.shellsplit(string)
+
+ 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
index cc207e3..0d6cc96 100644
--- a/lib/puppet/parser/functions/size.rb
+++ b/lib/puppet/parser/functions/size.rb
@@ -2,11 +2,9 @@
# 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.
+Returns the number of elements in a string, an array or a hash
EOS
) do |arguments|
@@ -29,13 +27,13 @@ Returns the number of elements in a string or array.
Float(item)
raise(Puppet::ParseError, 'size(): Requires either ' +
- 'string or array to work with')
+ 'string, array or hash to work with')
rescue ArgumentError
result = item.size
end
- elsif item.is_a?(Array)
+ elsif item.is_a?(Array) || item.is_a?(Hash)
result = item.size
else
raise(Puppet::ParseError, 'size(): Unknown type given')
diff --git a/lib/puppet/parser/functions/str2bool.rb b/lib/puppet/parser/functions/str2bool.rb
index 446732e..472506d 100644
--- a/lib/puppet/parser/functions/str2bool.rb
+++ b/lib/puppet/parser/functions/str2bool.rb
@@ -5,8 +5,8 @@
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'.
+contain things like: Y,y, 1, T,t, TRUE,true to 'true' and strings that contain things
+like: 0, F,f, N,n, false, FALSE, no to 'false'.
EOS
) do |arguments|
@@ -21,7 +21,7 @@ like: 0, f, n, false, no to 'false'.
end
unless string.is_a?(String)
- raise(Puppet::ParseError, 'str2bool(): Requires either ' +
+ raise(Puppet::ParseError, 'str2bool(): Requires ' +
'string to work with')
end
@@ -32,8 +32,8 @@ like: 0, f, n, false, no to 'false'.
# 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 /^(1|t|y|true|yes)$/i then true
+ when /^(0|f|n|false|no)$/i then false
when /^(undef|undefined)$/ then false # This is not likely to happen ...
else
raise(Puppet::ParseError, 'str2bool(): Unknown type of boolean given')
diff --git a/lib/puppet/parser/functions/suffix.rb b/lib/puppet/parser/functions/suffix.rb
index f7792d6..2908434 100644
--- a/lib/puppet/parser/functions/suffix.rb
+++ b/lib/puppet/parser/functions/suffix.rb
@@ -4,7 +4,8 @@
module Puppet::Parser::Functions
newfunction(:suffix, :type => :rvalue, :doc => <<-EOS
-This function applies a suffix to all elements in an array.
+This function applies a suffix to all elements in an array, or to the keys
+in a hash.
*Examples:*
@@ -18,10 +19,10 @@ Will return: ['ap','bp','cp']
raise(Puppet::ParseError, "suffix(): Wrong number of arguments " +
"given (#{arguments.size} for 1)") if arguments.size < 1
- array = arguments[0]
+ enumerable = arguments[0]
- unless array.is_a?(Array)
- raise Puppet::ParseError, "suffix(): expected first argument to be an Array, got #{array.inspect}"
+ unless enumerable.is_a?(Array) or enumerable.is_a?(Hash)
+ raise Puppet::ParseError, "suffix(): expected first argument to be an Array or a Hash, got #{enumerable.inspect}"
end
suffix = arguments[1] if arguments[1]
@@ -32,10 +33,17 @@ Will return: ['ap','bp','cp']
end
end
- # Turn everything into string same as join would do ...
- result = array.collect do |i|
- i = i.to_s
- suffix ? i + suffix : i
+ if enumerable.is_a?(Array)
+ # Turn everything into string same as join would do ...
+ result = enumerable.collect do |i|
+ i = i.to_s
+ suffix ? i + suffix : i
+ end
+ else
+ result = Hash[enumerable.map do |k,v|
+ k = k.to_s
+ [ suffix ? k + suffix : k, v ]
+ end]
end
return result
diff --git a/lib/puppet/parser/functions/time.rb b/lib/puppet/parser/functions/time.rb
index 0cddaf8..c574747 100644
--- a/lib/puppet/parser/functions/time.rb
+++ b/lib/puppet/parser/functions/time.rb
@@ -33,13 +33,14 @@ Will return something like: 1311972653
ENV['TZ'] = time_zone
- time = local_time.localtime
+ result = local_time.localtime.strftime('%s')
ENV['TZ'] = original_zone
+ else
+ result = time.localtime.strftime('%s')
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
diff --git a/lib/puppet/parser/functions/try_get_value.rb b/lib/puppet/parser/functions/try_get_value.rb
new file mode 100644
index 0000000..fc19a23
--- /dev/null
+++ b/lib/puppet/parser/functions/try_get_value.rb
@@ -0,0 +1,53 @@
+module Puppet::Parser::Functions
+ newfunction(
+ :try_get_value,
+ :type => :rvalue,
+ :arity => -2,
+ :doc => <<-eos
+DEPRECATED: this function is deprecated, please use dig() instead.
+
+Looks up into a complex structure of arrays and hashes and returns a value
+or the default value if nothing was found.
+
+Key can contain slashes to describe path components. The function will go down
+the structure and try to extract the required value.
+
+$data = {
+ 'a' => {
+ 'b' => [
+ 'b1',
+ 'b2',
+ 'b3',
+ ]
+ }
+}
+
+$value = try_get_value($data, 'a/b/2', 'not_found', '/')
+=> $value = 'b3'
+
+a -> first hash key
+b -> second hash key
+2 -> array index starting with 0
+
+not_found -> (optional) will be returned if there is no value or the path did not match. Defaults to nil.
+/ -> (optional) path delimiter. Defaults to '/'.
+
+In addition to the required "key" argument, "try_get_value" accepts default
+argument. It will be returned if no value was found or a path component is
+missing. And the fourth argument can set a variable path separator.
+ eos
+ ) do |args|
+ warning("try_get_value() DEPRECATED: this function is deprecated, please use dig() instead.")
+ data = args[0]
+ path = args[1] || ''
+ default = args[2]
+
+ if !(data.is_a?(Hash) || data.is_a?(Array)) || path == ''
+ return default || data
+ end
+
+ separator = args[3] || '/'
+ path = path.split(separator).map{ |key| key =~ /^\d+$/ ? key.to_i : key }
+ function_dig([data, path, default])
+ end
+end
diff --git a/lib/puppet/parser/functions/union.rb b/lib/puppet/parser/functions/union.rb
index c91bb80..6c5bb83 100644
--- a/lib/puppet/parser/functions/union.rb
+++ b/lib/puppet/parser/functions/union.rb
@@ -4,7 +4,7 @@
module Puppet::Parser::Functions
newfunction(:union, :type => :rvalue, :doc => <<-EOS
-This function returns a union of two arrays.
+This function returns a union of two or more arrays.
*Examples:*
@@ -14,20 +14,15 @@ Would return: ["a","b","c","d"]
EOS
) do |arguments|
- # Two arguments are required
+ # Check that 2 or more arguments have been given ...
raise(Puppet::ParseError, "union(): Wrong number of arguments " +
- "given (#{arguments.size} for 2)") if arguments.size != 2
+ "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')
+ arguments.each do |argument|
+ raise(Puppet::ParseError, 'union(): Every parameter must be an array') unless argument.is_a?(Array)
end
- result = first | second
-
- return result
+ arguments.reduce(:|)
end
end
diff --git a/lib/puppet/parser/functions/unix2dos.rb b/lib/puppet/parser/functions/unix2dos.rb
new file mode 100644
index 0000000..0bd9cd1
--- /dev/null
+++ b/lib/puppet/parser/functions/unix2dos.rb
@@ -0,0 +1,15 @@
+# Custom Puppet function to convert unix to dos format
+module Puppet::Parser::Functions
+ newfunction(:unix2dos, :type => :rvalue, :arity => 1, :doc => <<-EOS
+ Returns the DOS version of the given string.
+ Takes a single string argument.
+ EOS
+ ) do |arguments|
+
+ unless arguments[0].is_a?(String)
+ raise(Puppet::ParseError, 'unix2dos(): Requires string as argument')
+ end
+
+ arguments[0].gsub(/\r*\n/, "\r\n")
+ end
+end
diff --git a/lib/puppet/parser/functions/upcase.rb b/lib/puppet/parser/functions/upcase.rb
index 4302b29..44b3bcd 100644
--- a/lib/puppet/parser/functions/upcase.rb
+++ b/lib/puppet/parser/functions/upcase.rb
@@ -12,23 +12,28 @@ Converts a string or an array of strings to uppercase.
Will return:
- ASDF
- EOS
+ ABCD
+ EOS
) do |arguments|
raise(Puppet::ParseError, "upcase(): Wrong number of arguments " +
- "given (#{arguments.size} for 1)") if arguments.size < 1
+ "given (#{arguments.size} for 1)") if arguments.size != 1
value = arguments[0]
- unless value.is_a?(Array) || value.is_a?(String)
- raise(Puppet::ParseError, 'upcase(): Requires either ' +
- 'array or string to work with')
+ unless value.is_a?(Array) || value.is_a?(Hash) || value.respond_to?(:upcase)
+ raise(Puppet::ParseError, 'upcase(): Requires an ' +
+ 'array, hash or object that responds to upcase in order to work')
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 }
+ result = value.collect { |i| function_upcase([i]) }
+ elsif value.is_a?(Hash)
+ result = {}
+ value.each_pair do |k, v|
+ result[function_upcase([k])] = function_upcase([v])
+ end
else
result = value.upcase
end
diff --git a/lib/puppet/parser/functions/uriescape.rb b/lib/puppet/parser/functions/uriescape.rb
index a486eee..45bbed2 100644
--- a/lib/puppet/parser/functions/uriescape.rb
+++ b/lib/puppet/parser/functions/uriescape.rb
@@ -22,7 +22,7 @@ module Puppet::Parser::Functions
if value.is_a?(Array)
# Numbers in Puppet are often string-encoded which is troublesome ...
- result = value.collect { |i| i.is_a?(String) ? URI.escape(i,unsafe) : i }
+ result = value.collect { |i| i.is_a?(String) ? URI.escape(i) : i }
else
result = URI.escape(value)
end
diff --git a/lib/puppet/parser/functions/validate_absolute_path.rb b/lib/puppet/parser/functions/validate_absolute_path.rb
index b696680..c73f3df 100644
--- a/lib/puppet/parser/functions/validate_absolute_path.rb
+++ b/lib/puppet/parser/functions/validate_absolute_path.rb
@@ -26,6 +26,9 @@ module Puppet::Parser::Functions
ENDHEREDOC
+ # The deprecation function was being called twice, as validate_absolute_path calls is_absolute_path. I have removed it from here so it only calls deprecation once within is_absolute_path.
+ # function_deprecation([:validate_absolute_path, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Absolute_path. There is further documentation for validate_legacy function in the README.'])
+
require 'puppet/util'
unless args.length > 0 then
@@ -40,28 +43,10 @@ module Puppet::Parser::Functions
unless arg.is_a?(Array) then
candidates = Array.new(1,arg)
end
- # iterate over all pathes within the candidates array
+ # iterate over all paths within the candidates array
candidates.each do |path|
- # This logic was borrowed from
- # [lib/puppet/file_serving/base.rb](https://github.com/puppetlabs/puppet/blob/master/lib/puppet/file_serving/base.rb)
- # Puppet 2.7 and beyond will have Puppet::Util.absolute_path? Fall back to a back-ported implementation otherwise.
- if Puppet::Util.respond_to?(:absolute_path?) then
- unless Puppet::Util.absolute_path?(path, :posix) or Puppet::Util.absolute_path?(path, :windows)
- raise Puppet::ParseError, ("#{path.inspect} is not an absolute path.")
- end
- else
- # This code back-ported from 2.7.x's lib/puppet/util.rb Puppet::Util.absolute_path?
- # Determine in a platform-specific way whether a path is absolute. This
- # defaults to the local platform if none is specified.
- # Escape once for the string literal, and once for the regex.
- slash = '[\\\\/]'
- name = '[^\\\\/]+'
- regexes = {
- :windows => %r!^(([A-Z]:#{slash})|(#{slash}#{slash}#{name}#{slash}#{name})|(#{slash}#{slash}\?#{slash}#{name}))!i,
- :posix => %r!^/!,
- }
- rval = (!!(path =~ regexes[:posix])) || (!!(path =~ regexes[:windows]))
- rval or raise Puppet::ParseError, ("#{path.inspect} is not an absolute path.")
+ unless function_is_absolute_path([path])
+ raise Puppet::ParseError, ("#{path.inspect} is not an absolute path.")
end
end
end
diff --git a/lib/puppet/parser/functions/validate_array.rb b/lib/puppet/parser/functions/validate_array.rb
index 34b5118..3bf3983 100644
--- a/lib/puppet/parser/functions/validate_array.rb
+++ b/lib/puppet/parser/functions/validate_array.rb
@@ -18,6 +18,8 @@ module Puppet::Parser::Functions
ENDHEREDOC
+ function_deprecation([:validate_array, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Array. There is further documentation for validate_legacy function in the README.'])
+
unless args.length > 0 then
raise Puppet::ParseError, ("validate_array(): wrong number of arguments (#{args.length}; must be > 0)")
end
diff --git a/lib/puppet/parser/functions/validate_augeas.rb b/lib/puppet/parser/functions/validate_augeas.rb
index 4ea4fe0..2196c3e 100644
--- a/lib/puppet/parser/functions/validate_augeas.rb
+++ b/lib/puppet/parser/functions/validate_augeas.rb
@@ -31,7 +31,7 @@ module Puppet::Parser::Functions
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.")
+ raise Puppet::ParseError, ("validate_augeas(): this function requires the augeas feature. See http://docs.puppetlabs.com/guides/augeas.html#pre-requisites for how to activate it.")
end
if (args.length < 2) or (args.length > 4) then
diff --git a/lib/puppet/parser/functions/validate_bool.rb b/lib/puppet/parser/functions/validate_bool.rb
index 59a0805..49075b8 100644
--- a/lib/puppet/parser/functions/validate_bool.rb
+++ b/lib/puppet/parser/functions/validate_bool.rb
@@ -19,6 +19,9 @@ module Puppet::Parser::Functions
ENDHEREDOC
+ # The deprecation function was being called twice, as validate_bool calls is_bool. I have removed it from here so it only calls deprecation once within is_bool.
+ # function_deprecation([:validate_bool, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Bool. There is further documentation for validate_legacy function in the README.'])
+
unless args.length > 0 then
raise Puppet::ParseError, ("validate_bool(): wrong number of arguments (#{args.length}; must be > 0)")
end
diff --git a/lib/puppet/parser/functions/validate_cmd.rb b/lib/puppet/parser/functions/validate_cmd.rb
index 5df3c60..685162b 100644
--- a/lib/puppet/parser/functions/validate_cmd.rb
+++ b/lib/puppet/parser/functions/validate_cmd.rb
@@ -53,7 +53,7 @@ module Puppet::Parser::Functions
rescue Puppet::ExecutionFailure => detail
msg += "\n#{detail}"
raise Puppet::ParseError, msg
- rescue Exception => detail
+ rescue StandardError => detail
msg += "\n#{detail.class.name} #{detail}"
raise Puppet::ParseError, msg
ensure
diff --git a/lib/puppet/parser/functions/validate_email_address.rb b/lib/puppet/parser/functions/validate_email_address.rb
new file mode 100644
index 0000000..ddd0d25
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_email_address.rb
@@ -0,0 +1,31 @@
+module Puppet::Parser::Functions
+ newfunction(:validate_email_address, :doc => <<-ENDHEREDOC
+ Validate that all values passed are valid email addresses.
+ Fail compilation if any value fails this check.
+ The following values will pass:
+ $my_email = "waldo@gmail.com"
+ validate_email_address($my_email)
+ validate_email_address("bob@gmail.com", "alice@gmail.com", $my_email)
+
+ The following values will fail, causing compilation to abort:
+ $some_array = [ 'bad_email@/d/efdf.com' ]
+ validate_email_address($some_array)
+ ENDHEREDOC
+ ) do |args|
+ rescuable_exceptions = [ArgumentError]
+
+ if args.empty?
+ raise Puppet::ParseError, "validate_email_address(): wrong number of arguments (#{args.length}; must be > 0)"
+ end
+
+ args.each do |arg|
+ raise Puppet::ParseError, "#{arg.inspect} is not a string." unless arg.is_a?(String)
+
+ begin
+ raise Puppet::ParseError, "#{arg.inspect} is not a valid email address" unless function_is_email_address([arg])
+ rescue *rescuable_exceptions
+ raise Puppet::ParseError, "#{arg.inspect} is not a valid email address"
+ end
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/validate_hash.rb b/lib/puppet/parser/functions/validate_hash.rb
index 9bdd543..fcdc7e1 100644
--- a/lib/puppet/parser/functions/validate_hash.rb
+++ b/lib/puppet/parser/functions/validate_hash.rb
@@ -18,6 +18,8 @@ module Puppet::Parser::Functions
ENDHEREDOC
+ function_deprecation([:validate_hash, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Hash. There is further documentation for validate_legacy function in the README.'])
+
unless args.length > 0 then
raise Puppet::ParseError, ("validate_hash(): wrong number of arguments (#{args.length}; must be > 0)")
end
diff --git a/lib/puppet/parser/functions/validate_integer.rb b/lib/puppet/parser/functions/validate_integer.rb
new file mode 100644
index 0000000..2ae0293
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_integer.rb
@@ -0,0 +1,134 @@
+module Puppet::Parser::Functions
+
+ newfunction(:validate_integer, :doc => <<-'ENDHEREDOC') do |args|
+ Validate that the first argument is an integer (or an array of integers). Abort catalog compilation if any of the checks fail.
+
+ The second argument is optional and passes a maximum. (All elements of) the first argument has to be less or equal to this max.
+
+ The third argument is optional and passes a minimum. (All elements of) the first argument has to be greater or equal to this min.
+ If, and only if, a minimum is given, the second argument may be an empty string or undef, which will be handled to just check
+ if (all elements of) the first argument are greater or equal to the given minimum.
+
+ It will fail if the first argument is not an integer or array of integers, and if arg 2 and arg 3 are not convertable to an integer.
+
+ The following values will pass:
+
+ validate_integer(1)
+ validate_integer(1, 2)
+ validate_integer(1, 1)
+ validate_integer(1, 2, 0)
+ validate_integer(2, 2, 2)
+ validate_integer(2, '', 0)
+ validate_integer(2, undef, 0)
+ $foo = undef
+ validate_integer(2, $foo, 0)
+ validate_integer([1,2,3,4,5], 6)
+ validate_integer([1,2,3,4,5], 6, 0)
+
+ Plus all of the above, but any combination of values passed as strings ('1' or "1").
+ Plus all of the above, but with (correct) combinations of negative integer values.
+
+ The following values will not:
+
+ validate_integer(true)
+ validate_integer(false)
+ validate_integer(7.0)
+ validate_integer({ 1 => 2 })
+ $foo = undef
+ validate_integer($foo)
+ validate_integer($foobaridontexist)
+
+ validate_integer(1, 0)
+ validate_integer(1, true)
+ validate_integer(1, '')
+ validate_integer(1, undef)
+ validate_integer(1, , 0)
+ validate_integer(1, 2, 3)
+ validate_integer(1, 3, 2)
+ validate_integer(1, 3, true)
+
+ Plus all of the above, but any combination of values passed as strings ('false' or "false").
+ Plus all of the above, but with incorrect combinations of negative integer values.
+ Plus all of the above, but with non-integer items in arrays or maximum / minimum argument.
+
+ ENDHEREDOC
+
+ function_deprecation([:validate_integer, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Integer. There is further documentation for validate_legacy function in the README.'])
+
+ # tell the user we need at least one, and optionally up to two other parameters
+ raise Puppet::ParseError, "validate_integer(): Wrong number of arguments; must be 1, 2 or 3, got #{args.length}" unless args.length > 0 and args.length < 4
+
+ input, max, min = *args
+
+ # check maximum parameter
+ if args.length > 1
+ max = max.to_s
+ # allow max to be empty (or undefined) if we have a minimum set
+ if args.length > 2 and max == ''
+ max = nil
+ else
+ begin
+ max = Integer(max)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_integer(): Expected second argument to be unset or an Integer, got #{max}:#{max.class}"
+ end
+ end
+ else
+ max = nil
+ end
+
+ # check minimum parameter
+ if args.length > 2
+ begin
+ min = Integer(min.to_s)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_integer(): Expected third argument to be unset or an Integer, got #{min}:#{min.class}"
+ end
+ else
+ min = nil
+ end
+
+ # ensure that min < max
+ if min and max and min > max
+ raise Puppet::ParseError, "validate_integer(): Expected second argument to be larger than third argument, got #{max} < #{min}"
+ end
+
+ # create lamba validator function
+ validator = lambda do |num|
+ # check input < max
+ if max and num > max
+ raise Puppet::ParseError, "validate_integer(): Expected #{input.inspect} to be smaller or equal to #{max}, got #{input.inspect}."
+ end
+ # check input > min (this will only be checked if no exception has been raised before)
+ if min and num < min
+ raise Puppet::ParseError, "validate_integer(): Expected #{input.inspect} to be greater or equal to #{min}, got #{input.inspect}."
+ end
+ end
+
+ # if this is an array, handle it.
+ case input
+ when Array
+ # check every element of the array
+ input.each_with_index do |arg, pos|
+ begin
+ raise TypeError if arg.is_a?(Hash)
+ arg = Integer(arg.to_s)
+ validator.call(arg)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_integer(): Expected element at array position #{pos} to be an Integer, got #{arg.class}"
+ end
+ end
+ # for the sake of compatibility with ruby 1.8, we need extra handling of hashes
+ when Hash
+ raise Puppet::ParseError, "validate_integer(): Expected first argument to be an Integer or Array, got #{input.class}"
+ # check the input. this will also fail any stuff other than pure, shiny integers
+ else
+ begin
+ input = Integer(input.to_s)
+ validator.call(input)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_integer(): Expected first argument to be an Integer or Array, got #{input.class}"
+ end
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/validate_ip_address.rb b/lib/puppet/parser/functions/validate_ip_address.rb
new file mode 100644
index 0000000..5d80cfb
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_ip_address.rb
@@ -0,0 +1,52 @@
+module Puppet::Parser::Functions
+
+ newfunction(:validate_ip_address, :doc => <<-ENDHEREDOC
+ Validate that all values passed are valid IP addresses,
+ regardless they are IPv4 or IPv6
+ Fail compilation if any value fails this check.
+ The following values will pass:
+ $my_ip = "1.2.3.4"
+ validate_ip_address($my_ip)
+ validate_ip_address("8.8.8.8", "172.16.0.1", $my_ip)
+
+ $my_ip = "3ffe:505:2"
+ validate_ip_address(1)
+ validate_ip_address($my_ip)
+ validate_ip_address("fe80::baf6:b1ff:fe19:7507", $my_ip)
+
+ The following values will fail, causing compilation to abort:
+ $some_array = [ 1, true, false, "garbage string", "3ffe:505:2" ]
+ validate_ip_address($some_array)
+ ENDHEREDOC
+ ) do |args|
+
+ require "ipaddr"
+ rescuable_exceptions = [ ArgumentError ]
+
+ function_deprecation([:validate_ip_address, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ip_address. There is further documentation for validate_legacy function in the README.'])
+
+ if defined?(IPAddr::InvalidAddressError)
+ rescuable_exceptions << IPAddr::InvalidAddressError
+ end
+
+ unless args.length > 0 then
+ raise Puppet::ParseError, ("validate_ip_address(): wrong number of arguments (#{args.length}; must be > 0)")
+ end
+
+ args.each do |arg|
+ unless arg.is_a?(String)
+ raise Puppet::ParseError, "#{arg.inspect} is not a string."
+ end
+
+ begin
+ unless IPAddr.new(arg).ipv4? or IPAddr.new(arg).ipv6?
+ raise Puppet::ParseError, "#{arg.inspect} is not a valid IP address."
+ end
+ rescue *rescuable_exceptions
+ raise Puppet::ParseError, "#{arg.inspect} is not a valid IP address."
+ end
+ end
+
+ end
+
+end
diff --git a/lib/puppet/parser/functions/validate_ipv4_address.rb b/lib/puppet/parser/functions/validate_ipv4_address.rb
index fc02748..0660abd 100644
--- a/lib/puppet/parser/functions/validate_ipv4_address.rb
+++ b/lib/puppet/parser/functions/validate_ipv4_address.rb
@@ -8,7 +8,7 @@ module Puppet::Parser::Functions
$my_ip = "1.2.3.4"
validate_ipv4_address($my_ip)
- validate_bool("8.8.8.8", "172.16.0.1", $my_ip)
+ validate_ipv4_address("8.8.8.8", "172.16.0.1", $my_ip)
The following values will fail, causing compilation to abort:
@@ -18,6 +18,8 @@ module Puppet::Parser::Functions
ENDHEREDOC
) do |args|
+ function_deprecation([:validate_ipv4_address, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ipv4. There is further documentation for validate_legacy function in the README.'])
+
require "ipaddr"
rescuable_exceptions = [ ArgumentError ]
diff --git a/lib/puppet/parser/functions/validate_ipv6_address.rb b/lib/puppet/parser/functions/validate_ipv6_address.rb
index b0f2558..f5dd9e5 100644
--- a/lib/puppet/parser/functions/validate_ipv6_address.rb
+++ b/lib/puppet/parser/functions/validate_ipv6_address.rb
@@ -19,6 +19,8 @@ module Puppet::Parser::Functions
ENDHEREDOC
) do |args|
+ function_deprecation([:validate_ipv6_address, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ipv6. There is further documentation for validate_legacy function in the README.'])
+
require "ipaddr"
rescuable_exceptions = [ ArgumentError ]
diff --git a/lib/puppet/parser/functions/validate_numeric.rb b/lib/puppet/parser/functions/validate_numeric.rb
new file mode 100644
index 0000000..4205b30
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_numeric.rb
@@ -0,0 +1,96 @@
+module Puppet::Parser::Functions
+
+ newfunction(:validate_numeric, :doc => <<-'ENDHEREDOC') do |args|
+ Validate that the first argument is a numeric value (or an array of numeric values). Abort catalog compilation if any of the checks fail.
+
+ The second argument is optional and passes a maximum. (All elements of) the first argument has to be less or equal to this max.
+
+ The third argument is optional and passes a minimum. (All elements of) the first argument has to be greater or equal to this min.
+ If, and only if, a minimum is given, the second argument may be an empty string or undef, which will be handled to just check
+ if (all elements of) the first argument are greater or equal to the given minimum.
+
+ It will fail if the first argument is not a numeric (Integer or Float) or array of numerics, and if arg 2 and arg 3 are not convertable to a numeric.
+
+ For passing and failing usage, see `validate_integer()`. It is all the same for validate_numeric, yet now floating point values are allowed, too.
+
+ ENDHEREDOC
+
+ function_deprecation([:validate_numeric, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Numeric. There is further documentation for validate_legacy function in the README.'])
+
+ # tell the user we need at least one, and optionally up to two other parameters
+ raise Puppet::ParseError, "validate_numeric(): Wrong number of arguments; must be 1, 2 or 3, got #{args.length}" unless args.length > 0 and args.length < 4
+
+ input, max, min = *args
+
+ # check maximum parameter
+ if args.length > 1
+ max = max.to_s
+ # allow max to be empty (or undefined) if we have a minimum set
+ if args.length > 2 and max == ''
+ max = nil
+ else
+ begin
+ max = Float(max)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_numeric(): Expected second argument to be unset or a Numeric, got #{max}:#{max.class}"
+ end
+ end
+ else
+ max = nil
+ end
+
+ # check minimum parameter
+ if args.length > 2
+ begin
+ min = Float(min.to_s)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_numeric(): Expected third argument to be unset or a Numeric, got #{min}:#{min.class}"
+ end
+ else
+ min = nil
+ end
+
+ # ensure that min < max
+ if min and max and min > max
+ raise Puppet::ParseError, "validate_numeric(): Expected second argument to be larger than third argument, got #{max} < #{min}"
+ end
+
+ # create lamba validator function
+ validator = lambda do |num|
+ # check input < max
+ if max and num > max
+ raise Puppet::ParseError, "validate_numeric(): Expected #{input.inspect} to be smaller or equal to #{max}, got #{input.inspect}."
+ end
+ # check input > min (this will only be checked if no exception has been raised before)
+ if min and num < min
+ raise Puppet::ParseError, "validate_numeric(): Expected #{input.inspect} to be greater or equal to #{min}, got #{input.inspect}."
+ end
+ end
+
+ # if this is an array, handle it.
+ case input
+ when Array
+ # check every element of the array
+ input.each_with_index do |arg, pos|
+ begin
+ raise TypeError if arg.is_a?(Hash)
+ arg = Float(arg.to_s)
+ validator.call(arg)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_numeric(): Expected element at array position #{pos} to be a Numeric, got #{arg.class}"
+ end
+ end
+ # for the sake of compatibility with ruby 1.8, we need extra handling of hashes
+ when Hash
+ raise Puppet::ParseError, "validate_integer(): Expected first argument to be a Numeric or Array, got #{input.class}"
+ # check the input. this will also fail any stuff other than pure, shiny integers
+ else
+ begin
+ input = Float(input.to_s)
+ validator.call(input)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_numeric(): Expected first argument to be a Numeric or Array, got #{input.class}"
+ end
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/validate_re.rb b/lib/puppet/parser/functions/validate_re.rb
index ca25a70..0ac83dd 100644
--- a/lib/puppet/parser/functions/validate_re.rb
+++ b/lib/puppet/parser/functions/validate_re.rb
@@ -23,16 +23,26 @@ module Puppet::Parser::Functions
validate_re($::puppetversion, '^2.7', 'The $puppetversion fact value does not match 2.7')
+ Note: Compilation will also abort, if the first argument is not a String. Always use
+ quotes to force stringification:
+
+ validate_re("${::operatingsystemmajrelease}", '^[57]$')
+
ENDHEREDOC
+
+ function_deprecation([:validate_re, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Re. There is further documentation for validate_legacy function in the README.'])
+
if (args.length < 2) or (args.length > 3) then
- raise Puppet::ParseError, ("validate_re(): wrong number of arguments (#{args.length}; must be 2 or 3)")
+ raise Puppet::ParseError, "validate_re(): wrong number of arguments (#{args.length}; must be 2 or 3)"
end
+ raise Puppet::ParseError, "validate_re(): input needs to be a String, not a #{args[0].class}" unless args[0].is_a? String
+
msg = args[2] || "validate_re(): #{args[0].inspect} does not match #{args[1].inspect}"
# We're using a flattened array here because we can't call String#any? in
# Ruby 1.9 like we can in Ruby 1.8
- raise Puppet::ParseError, (msg) unless [args[1]].flatten.any? do |re_str|
+ raise Puppet::ParseError, msg unless [args[1]].flatten.any? do |re_str|
args[0] =~ Regexp.compile(re_str)
end
diff --git a/lib/puppet/parser/functions/validate_slength.rb b/lib/puppet/parser/functions/validate_slength.rb
index 7d534f3..383855c 100644
--- a/lib/puppet/parser/functions/validate_slength.rb
+++ b/lib/puppet/parser/functions/validate_slength.rb
@@ -3,7 +3,7 @@ module Puppet::Parser::Functions
newfunction(:validate_slength, :doc => <<-'ENDHEREDOC') do |args|
Validate that the first argument is a string (or an array of strings), and
less/equal to than the length of the second argument. An optional third
- parameter can be given a the minimum length. It fails if the first
+ parameter can be given the minimum length. It fails if the first
argument is not a string or array of strings, and if arg 2 and arg 3 are
not convertable to a number.
@@ -21,6 +21,8 @@ module Puppet::Parser::Functions
ENDHEREDOC
+ function_deprecation([:validate_slength, 'This method is deprecated, please use the stdlib validate_legacy function, with String[]. There is further documentation for validate_legacy function in the README.'])
+
raise Puppet::ParseError, "validate_slength(): Wrong number of arguments (#{args.length}; must be 2 or 3)" unless args.length == 2 or args.length == 3
input, max_length, min_length = *args
@@ -43,9 +45,7 @@ module Puppet::Parser::Functions
min_length = 0
end
- if min_length > max_length
- raise Puppet::ParseError, "validate_slength(): Expected second argument to be larger than third argument"
- end
+ raise Puppet::ParseError, "validate_slength(): Expected second argument to be equal to or larger than third argument" unless max_length >= min_length
validator = lambda do |str|
unless str.length <= max_length and str.length >= min_length
diff --git a/lib/puppet/parser/functions/validate_string.rb b/lib/puppet/parser/functions/validate_string.rb
index c841f6a..6675d86 100644
--- a/lib/puppet/parser/functions/validate_string.rb
+++ b/lib/puppet/parser/functions/validate_string.rb
@@ -13,22 +13,25 @@ module Puppet::Parser::Functions
validate_string(true)
validate_string([ 'some', 'array' ])
-
+
Note: validate_string(undef) will not fail in this version of the
functions API (incl. current and future parser). Instead, use:
-
+
if $var == undef {
fail('...')
}
-
+
ENDHEREDOC
+ function_deprecation([:validate_string, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::String. There is further documentation for validate_legacy function in the README.'])
+
unless args.length > 0 then
raise Puppet::ParseError, ("validate_string(): wrong number of arguments (#{args.length}; must be > 0)")
end
args.each do |arg|
- unless arg.is_a?(String)
+ # when called through the v4 API shim, undef gets translated to nil
+ unless arg.is_a?(String) || arg.nil?
raise Puppet::ParseError, ("#{arg.inspect} is not a string. It looks to be a #{arg.class}")
end
end
diff --git a/lib/puppet/parser/functions/validate_x509_rsa_key_pair.rb b/lib/puppet/parser/functions/validate_x509_rsa_key_pair.rb
new file mode 100644
index 0000000..fc9f23f
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_x509_rsa_key_pair.rb
@@ -0,0 +1,47 @@
+module Puppet::Parser::Functions
+
+ newfunction(:validate_x509_rsa_key_pair, :doc => <<-ENDHEREDOC
+ Validates a PEM-formatted X.509 certificate and RSA private key using
+ OpenSSL. Verifies that the certficate's signature was created from the
+ supplied key.
+
+ Fail compilation if any value fails this check.
+
+ validate_x509_rsa_key_pair($cert, $key)
+
+ ENDHEREDOC
+ ) do |args|
+
+ require 'openssl'
+
+ NUM_ARGS = 2 unless defined? NUM_ARGS
+
+ unless args.length == NUM_ARGS then
+ raise Puppet::ParseError,
+ ("validate_x509_rsa_key_pair(): wrong number of arguments (#{args.length}; must be #{NUM_ARGS})")
+ end
+
+ args.each do |arg|
+ unless arg.is_a?(String)
+ raise Puppet::ParseError, "#{arg.inspect} is not a string."
+ end
+ end
+
+ begin
+ cert = OpenSSL::X509::Certificate.new(args[0])
+ rescue OpenSSL::X509::CertificateError => e
+ raise Puppet::ParseError, "Not a valid x509 certificate: #{e}"
+ end
+
+ begin
+ key = OpenSSL::PKey::RSA.new(args[1])
+ rescue OpenSSL::PKey::RSAError => e
+ raise Puppet::ParseError, "Not a valid RSA key: #{e}"
+ end
+
+ unless cert.verify(key)
+ raise Puppet::ParseError, "Certificate signature does not match supplied key"
+ end
+ end
+
+end
diff --git a/lib/puppet/provider/file_line/ruby.rb b/lib/puppet/provider/file_line/ruby.rb
index ae1a8b3..beeb430 100644
--- a/lib/puppet/provider/file_line/ruby.rb
+++ b/lib/puppet/provider/file_line/ruby.rb
@@ -1,24 +1,35 @@
Puppet::Type.type(:file_line).provide(:ruby) do
def exists?
- lines.find do |line|
- line.chomp == resource[:line].chomp
+ if resource[:replace].to_s != 'true' and count_matches(match_regex) > 0
+ true
+ else
+ lines.find do |line|
+ if resource[:ensure].to_s == 'absent' and resource[:match_for_absence].to_s == 'true'
+ line.chomp =~ Regexp.new(resource[:match])
+ else
+ line.chomp == resource[:line].chomp
+ end
+ end
end
end
def create
- if resource[:match]
- handle_create_with_match
- elsif resource[:after]
- handle_create_with_after
- else
- append_line
+ unless resource[:replace].to_s != 'true' and count_matches(match_regex) > 0
+ if resource[:match]
+ handle_create_with_match
+ elsif resource[:after]
+ handle_create_with_after
+ else
+ append_line
+ end
end
end
def destroy
- local_lines = lines
- File.open(resource[:path],'w') do |fh|
- fh.write(local_lines.reject{|l| l.chomp == resource[:line] }.join(''))
+ if resource[:match_for_absence].to_s == 'true' and resource[:match]
+ handle_destroy_with_match
+ else
+ handle_destroy_line
end
end
@@ -32,15 +43,27 @@ Puppet::Type.type(:file_line).provide(:ruby) do
@lines ||= File.readlines(resource[:path])
end
+ def match_regex
+ resource[:match] ? Regexp.new(resource[:match]) : nil
+ end
+
def handle_create_with_match()
- regex = resource[:match] ? Regexp.new(resource[:match]) : nil
- match_count = count_matches(regex)
+ regex_after = resource[:after] ? Regexp.new(resource[:after]) : nil
+ match_count = count_matches(match_regex)
+
if match_count > 1 && resource[:multiple].to_s != 'true'
raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'"
end
+
File.open(resource[:path], 'w') do |fh|
lines.each do |l|
- fh.puts(regex.match(l) ? resource[:line] : l)
+ fh.puts(match_regex.match(l) ? resource[:line] : l)
+ if (match_count == 0 and regex_after)
+ if regex_after.match(l)
+ fh.puts(resource[:line])
+ match_count += 1 #Increment match_count to indicate that the new line has been inserted.
+ end
+ end
end
if (match_count == 0)
@@ -52,20 +75,22 @@ Puppet::Type.type(:file_line).provide(:ruby) do
def handle_create_with_after
regex = Regexp.new(resource[:after])
count = count_matches(regex)
- case count
- when 1 # find the line to put our line after
- File.open(resource[:path], 'w') do |fh|
- lines.each do |l|
- fh.puts(l)
- if regex.match(l) then
- fh.puts(resource[:line])
- end
+
+ if count > 1 && resource[:multiple].to_s != 'true'
+ raise Puppet::Error, "#{count} lines match pattern '#{resource[:after]}' in file '#{resource[:path]}'. One or no line must match the pattern."
+ end
+
+ File.open(resource[:path], 'w') do |fh|
+ lines.each do |l|
+ fh.puts(l)
+ if regex.match(l) then
+ fh.puts(resource[:line])
end
end
- when 0 # append the line to the end of the file
+ end
+
+ if (count == 0) # append the line to the end of the file
append_line
- else
- raise Puppet::Error, "#{count} lines match pattern '#{resource[:after]}' in file '#{resource[:path]}'. One or no line must match the pattern."
end
end
@@ -73,12 +98,34 @@ Puppet::Type.type(:file_line).provide(:ruby) do
lines.select{|l| l.match(regex)}.size
end
+ def handle_destroy_with_match
+ match_count = count_matches(match_regex)
+ if match_count > 1 && resource[:multiple].to_s != 'true'
+ raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'"
+ end
+
+ local_lines = lines
+ File.open(resource[:path],'w') do |fh|
+ fh.write(local_lines.reject{|l| match_regex.match(l) }.join(''))
+ end
+ end
+
+ def handle_destroy_line
+ local_lines = lines
+ File.open(resource[:path],'w') do |fh|
+ fh.write(local_lines.reject{|l| l.chomp == resource[:line] }.join(''))
+ end
+ end
+
##
# append the line to the file.
#
# @api private
def append_line
- File.open(resource[:path], 'a') do |fh|
+ File.open(resource[:path], 'w') do |fh|
+ lines.each do |l|
+ fh.puts(l)
+ end
fh.puts resource[:line]
end
end
diff --git a/lib/puppet/type/file_line.rb b/lib/puppet/type/file_line.rb
index df263e6..7b7d44e 100644
--- a/lib/puppet/type/file_line.rb
+++ b/lib/puppet/type/file_line.rb
@@ -3,9 +3,9 @@ Puppet::Type.newtype(:file_line) do
desc <<-EOT
Ensures that a given line is contained within a file. The implementation
matches the full line, including whitespace at the beginning and end. If
- the line is not contained in the given file, Puppet will add the line to
- ensure the desired state. Multiple resources may be declared to manage
- multiple lines in the same file.
+ the line is not contained in the given file, Puppet will append the line to
+ the end of the file to ensure the desired state. Multiple resources may
+ be declared to manage multiple lines in the same file.
Example:
@@ -13,6 +13,7 @@ Puppet::Type.newtype(:file_line) do
path => '/etc/sudoers',
line => '%sudo ALL=(ALL) ALL',
}
+
file_line { 'sudo_rule_nopw':
path => '/etc/sudoers',
line => '%sudonopw ALL=(ALL) NOPASSWD: ALL',
@@ -21,9 +22,34 @@ Puppet::Type.newtype(:file_line) do
In this example, Puppet will ensure both of the specified lines are
contained in the file /etc/sudoers.
+ Match Example:
+
+ file_line { 'bashrc_proxy':
+ ensure => present,
+ path => '/etc/bashrc',
+ line => 'export HTTP_PROXY=http://squid.puppetlabs.vm:3128',
+ match => '^export\ HTTP_PROXY\=',
+ }
+
+ In this code example match will look for a line beginning with export
+ followed by HTTP_PROXY and replace it with the value in line.
+
+ Match Example With `ensure => absent`:
+
+ file_line { 'bashrc_proxy':
+ ensure => absent,
+ path => '/etc/bashrc',
+ line => 'export HTTP_PROXY=http://squid.puppetlabs.vm:3128',
+ match => '^export\ HTTP_PROXY\=',
+ match_for_absence => true,
+ }
+
+ In this code example match will look for a line beginning with export
+ followed by HTTP_PROXY and delete it. If multiple lines match, an
+ error will be raised unless the `multiple => true` parameter is set.
+
**Autorequires:** If Puppet is managing the file that will contain the line
being managed, the file_line resource will autorequire that file.
-
EOT
ensurable do
@@ -36,40 +62,64 @@ Puppet::Type.newtype(:file_line) do
end
newparam(:match) do
- desc 'An optional regular expression to run against existing lines in the file;\n' +
- 'if a match is found, we replace that line rather than adding a new line.'
+ desc 'An optional ruby regular expression to run against existing lines in the file.' +
+ ' If a match is found, we replace that line rather than adding a new line.' +
+ ' A regex comparison is performed against the line value and if it does not' +
+ ' match an exception will be raised.'
+ end
+
+ newparam(:match_for_absence) do
+ desc 'An optional value to determine if match should be applied when ensure => absent.' +
+ ' If set to true and match is set, the line that matches match will be deleted.' +
+ ' If set to false (the default), match is ignored when ensure => absent.' +
+ ' When `ensure => present`, match_for_absence is ignored.'
+ newvalues(true, false)
+ defaultto false
end
newparam(:multiple) do
- desc 'An optional value to determine if match can change multiple lines.'
+ desc 'An optional value to determine if match can change multiple lines.' +
+ ' If set to false, an exception will be raised if more than one line matches'
newvalues(true, false)
end
newparam(:after) do
- desc 'An optional value used to specify the line after which we will add any new lines. (Existing lines are added in place)'
+ desc 'An optional value used to specify the line after which we will add any new lines. (Existing lines are added in place)' +
+ ' This is also takes a regex.'
end
newparam(:line) do
- desc 'The line to be appended to the file located by the path parameter.'
+ desc 'The line to be appended to the file or used to replace matches found by the match attribute.'
end
newparam(:path) do
desc 'The file Puppet will ensure contains the line specified by the line parameter.'
validate do |value|
- unless (Puppet.features.posix? and value =~ /^\//) or (Puppet.features.microsoft_windows? and (value =~ /^.:\// or value =~ /^\/\/[^\/]+\/[^\/]+/))
- raise(Puppet::Error, "File paths must be fully qualified, not '#{value}'")
+ unless Puppet::Util.absolute_path?(value)
+ raise Puppet::Error, "File paths must be fully qualified, not '#{value}'"
end
end
end
+ newparam(:replace) do
+ desc 'If true, replace line that matches. If false, do not write line if a match is found'
+ newvalues(true, false)
+ defaultto true
+ end
+
# Autorequire the file resource if it's being managed
autorequire(:file) do
self[:path]
end
validate do
- unless self[:line] and self[:path]
- raise(Puppet::Error, "Both line and path are required attributes")
+ unless self[:line]
+ unless (self[:ensure].to_s == 'absent') and (self[:match_for_absence].to_s == 'true') and self[:match]
+ raise(Puppet::Error, "line is a required attribute")
+ end
+ end
+ unless self[:path]
+ raise(Puppet::Error, "path is a required attribute")
end
end
end