Commit 1042df79 authored by James T. Lee's avatar James T. Lee
Browse files

Move puppet libraries into module for Puppet 7 compat

parent d8c34007
# frozen_string_literal: true
# @summary
# Wrapper that calls the Puppet 3.x function of the same name.
Puppet::Functions.create_function(:is_array) do
# @param scope
# The main value that will be passed to the wrapped method
#
# @param args
# Any additional values that are to be passed to the wrapped method
#
# @return [Boolea]
# A boolean value returned from the called 3.x function.
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
# frozen_string_literal: true
# @summary
# Wrapper that calls the Puppet 3.x function of the same name.
Puppet::Functions.create_function(:is_bool) do
# @param scope
# The main value that will be passed to the wrapped method
#
# @param args
# Any additional values that are to be passed to the wrapped method
#
# @return [Boolea]
# A boolean value returned from the called 3.x function.
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
# frozen_string_literal: true
# @summary
# Wrapper that calls the Puppet 3.x function of the same name.
Puppet::Functions.create_function(:is_float) do
# @param scope
# The main value that will be passed to the wrapped method
#
# @param args
# Any additional values that are to be passed to the wrapped method
#
# @return [Boolea]
# A boolean value returned from the called 3.x function.
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
# frozen_string_literal: true
# @summary
# Wrapper that calls the Puppet 3.x function of the same name.
Puppet::Functions.create_function(:is_ip_address) do
# @param scope
# The main value that will be passed to the wrapped method
#
# @param args
# Any additional values that are to be passed to the wrapped method
#
# @return [Boolea]
# A boolean value returned from the called 3.x function.
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
# frozen_string_literal: true
# @summary
# Wrapper that calls the Puppet 3.x function of the same name.
Puppet::Functions.create_function(:is_ipv4_address) do
# @param scope
# The main value that will be passed to the wrapped method
#
# @param args
# Any additional values that are to be passed to the wrapped method
#
# @return [Boolea]
# A boolean value returned from the called 3.x function.
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
# frozen_string_literal: true
# @summary
# Wrapper that calls the Puppet 3.x function of the same name.
Puppet::Functions.create_function(:is_ipv6_address) do
# @param scope
# The main value that will be passed to the wrapped method
#
# @param args
# Any additional values that are to be passed to the wrapped method
#
# @return [Boolea]
# A boolean value returned from the called 3.x function.
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
# frozen_string_literal: true
# @summary
# Wrapper that calls the Puppet 3.x function of the same name.
Puppet::Functions.create_function(:is_numeric) do
# @param scope
# The main value that will be passed to the wrapped method
#
# @param args
# Any additional values that are to be passed to the wrapped method
#
# @return [Boolea]
# A boolean value returned from the called 3.x function.
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
# frozen_string_literal: true
# @summary
# Wrapper that calls the Puppet 3.x function of the same name.
Puppet::Functions.create_function(:is_string) do
# @param scope
# The main value that will be passed to the wrapped method
#
# @param args
# Any additional values that are to be passed to the wrapped method
#
# @return [Boolean]
# A boolean value returned from the called 3.x function.
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
# frozen_string_literal: true
# @summary
# **Deprecated:** A function to eventually replace the old size() function for stdlib
#
# The original size() function did not handle Puppets new type capabilities, so this function
# is a Puppet 4 compatible solution.
#
# > **Note:** **Deprecated** from Puppet 6.0.0, this function has been replaced with a
# built-in [`length`](https://puppet.com/docs/puppet/latest/function.html#length) function.
#
Puppet::Functions.create_function(:length) do
# @param value
# The value whose length is to be found
#
# @return [Integer]
# The length of the given object
dispatch :length do
param 'Variant[String,Array,Hash]', :value
end
def length(value)
if value.is_a?(String)
result = value.length
elsif value.is_a?(Array) || value.is_a?(Hash)
result = value.size
end
result
end
end
# frozen_string_literal: true
# @summary
# Merges two or more hashes together or hashes resulting from iteration, and returns
# the resulting hash.
#
# @example Using merge()
# $hash1 = {'one' => 1, 'two', => 2}
# $hash2 = {'two' => 'dos', 'three', => 'tres'}
# $merged_hash = merge($hash1, $hash2) # $merged_hash = {'one' => 1, 'two' => 'dos', 'three' => 'tres'}
#
# When there is a duplicate key, the key in the rightmost hash will "win."
#
# Note that since Puppet 4.0.0 the same merge can be achieved with the + operator.
# `$merged_hash = $hash1 + $hash2`
#
# If merge is given a single Iterable (Array, Hash, etc.) it will call a given block with
# up to three parameters, and merge each resulting Hash into the accumulated result. All other types
# of values returned from the block (typically undef) are skipped (not merged).
#
# The codeblock can take 2 or three parameters:
# * with two, it gets the current hash (as built to this point), and each value (for hash the value is a [key, value] tuple)
# * with three, it gets the current hash (as built to this point), the key/index of each value, and then the value
#
# If the iterable is empty, or no hash was returned from the given block, an empty hash is returned. In the given block, a call to `next()`
# will skip that entry, and a call to `break()` will end the iteration.
#
# @example counting occurrences of strings in an array
# ['a', 'b', 'c', 'c', 'd', 'b'].merge | $hsh, $v | { { $v => $hsh[$v].lest || { 0 } + 1 } } # results in { a => 1, b => 2, c => 2, d => 1 }
#
# @example skipping values for entries that are longer than 1 char
# ['a', 'b', 'c', 'c', 'd', 'b', 'blah', 'blah'].merge | $hsh, $v | { if $v =~ String[1,1] { { $v => $hsh[$v].lest || { 0 } + 1 } } } # results in { a => 1, b => 2, c => 2, d => 1 }
#
# The iterative `merge()` has an advantage over doing the same with a general `reduce()` in that the constructed hash
# does not have to be copied in each iteration and thus will perform much better with large inputs.
Puppet::Functions.create_function(:merge) do
# @param args
# Repeated Param - The hashes that are to be merged
#
# @return
# The merged hash
dispatch :merge2hashes do
repeated_param 'Variant[Hash, Undef, String[0,0]]', :args # this strange type is backwards compatible
return_type 'Hash'
end
# @param args
# Repeated Param - The hashes that are to be merged
#
# @param block
# A block placed on the repeatable param `args`
#
# @return
# The merged hash
dispatch :merge_iterable3 do
repeated_param 'Iterable', :args
block_param 'Callable[3,3]', :block
return_type 'Hash'
end
# @param args
# Repeated Param - The hashes that are to be merged
#
# @param block
# A block placed on the repeatable param `args`
#
# @return
# The merged hash
dispatch :merge_iterable2 do
repeated_param 'Iterable', :args
block_param 'Callable[2,2]', :block
return_type 'Hash'
end
def merge2hashes(*hashes)
accumulator = {}
hashes.each { |h| accumulator.merge!(h) if h.is_a?(Hash) }
accumulator
end
def merge_iterable2(iterable)
accumulator = {}
enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable)
enum.each do |v|
r = yield(accumulator, v)
accumulator.merge!(r) if r.is_a?(Hash)
end
accumulator
end
def merge_iterable3(iterable)
accumulator = {}
enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable)
if enum.hash_style?
enum.each do |entry|
r = yield(accumulator, *entry)
accumulator.merge!(r) if r.is_a?(Hash)
end
else
begin
index = 0
loop do
r = yield(accumulator, index, enum.next)
accumulator.merge!(r) if r.is_a?(Hash)
index += 1
end
rescue StopIteration
end
end
accumulator
end
end
# frozen_string_literal: true
# @summary
# Checks if the OS version is at least a certain version.
# > *Note:*
# Only the major version is taken into account.
#
# @example Example usage:#
# if os_version_gte('Debian', '9') { }
# if os_version_gte('Ubuntu', '18.04') { }
Puppet::Functions.create_function(:os_version_gte) do
# @param os operating system
# @param version
#
# @return [Boolean] `true` or `false
dispatch :os_version_gte do
param 'String[1]', :os
param 'String[1]', :version
return_type 'Boolean'
end
def os_version_gte(os, version)
facts = closure_scope['facts']
(facts['operatingsystem'] == os &&
Puppet::Util::Package.versioncmp(version, facts['operatingsystemmajrelease']) >= 0)
end
end
# frozen_string_literal: true
# @summary
# This function accepts HOCON as a string and converts it into the correct
# Puppet structure
#
# @return
# Data
#
# @example How to parse hocon
# $data = parsehocon("{any valid hocon: string}")
#
Puppet::Functions.create_function(:parsehocon) do
# @param hocon_string A valid HOCON string
# @param default An optional default to return if parsing hocon_string fails
dispatch :parsehocon do
param 'String', :hocon_string
optional_param 'Any', :default
end
def parsehocon(hocon_string, default = :no_default_provided)
require 'hocon/config_factory'
begin
data = Hocon::ConfigFactory.parse_string(hocon_string)
data.resolve.root.unwrapped
rescue Hocon::ConfigError::ConfigParseError => err
Puppet.debug("Parsing hocon failed with error: #{err.message}")
raise err if default == :no_default_provided
default
end
end
end
# frozen_string_literal: true
# @summary
# Generates a consistent random string of specific length based on provided seed.
#
# @example Generate a consistently random string of length 8 with a seed:
# seeded_rand_string(8, "${module_name}::redis_password")
#
# @example Generate a random string from a specific set of characters:
# seeded_rand_string(5, '', 'abcdef')
Puppet::Functions.create_function(:seeded_rand_string) do
# @param length Length of string to be generated.
# @param seed Seed string.
# @param charset String that contains characters to use for the random string.
#
# @return [String] Random string.
dispatch :rand_string do
param 'Integer[1]', :length
param 'String', :seed
optional_param 'String[2]', :charset
end
def rand_string(length, seed, charset = nil)
require 'digest/sha2'
charset ||= '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
random_generator = Random.new(Digest::SHA256.hexdigest(seed).to_i(16))
Array.new(length) { charset[random_generator.rand(charset.size)] }.join
end
end
# frozen_string_literal: true
# @summary
# Uses sprintf with named references.
#
# The first parameter is format string describing how the rest of the parameters in the hash
# should be formatted. See the documentation for the `Kernel::sprintf` function in Ruby for
# all the details.
#
# In the given argument hash with parameters, all keys are converted to symbols so they work
# with the `sprintf` function.
#
# @example Format a string and number
# $output = sprintf_hash('String: %<foo>s / number converted to binary: %<number>b',
# { 'foo' => 'a string', 'number' => 5 })
# # $output = 'String: a string / number converted to binary: 101'
#
# Note that since Puppet 4.10.10, and 5.3.4 this functionality is supported by the
# `sprintf` function in puppet core.
#
Puppet::Functions.create_function(:sprintf_hash) do
# @param format The format to use.
# @param arguments Hash with parameters.
# @return The formatted string.
dispatch :sprintf_hash do
param 'String', :format
param 'Hash', :arguments
# Disabled for now. This gives issues on puppet 4.7.1.
# return_type 'String'
end
def sprintf_hash(format, arguments)
call_function('deprecation', 'sprintf_hash', 'This method is deprecated. From Puppet 4.10.10/5.3.4 please use the built-in sprintf instead')
Kernel.sprintf(format, Hash[arguments.map { |(k, v)| [k.to_sym, v] }])
end
end
# frozen_string_literal: true
# @summary
# Returns true if str ends with one of the prefixes given. Each of the prefixes should be a String.
#
Puppet::Functions.create_function(:'stdlib::end_with') do
# @param test_string The string to check
# @param suffixes The suffixes to check
# @example
# 'foobar'.stdlib::end_with('bar') => true
# 'foobar'.stdlib::end_with('foo') => false
# 'foobar'.stdlib::end_with(['foo', 'baz']) => false
# @return [Boolean] True or False
dispatch :end_with do
param 'String', :test_string
param 'Variant[String[1],Array[String[1], 1]]', :suffixes
return_type 'Boolean'
end
def end_with(test_string, suffixes)
test_string.end_with?(*suffixes)
end
end
# frozen_string_literal: true
# @summary
# Returns the Extension (the Portion of Filename in Path starting from the
# last Period).
#
# If Path is a Dotfile, or starts with a Period, then the starting Dot is not
# dealt with the Start of the Extension.
#
# An empty String will also be returned, when the Period is the last Character
# in Path.
Puppet::Functions.create_function(:'stdlib::extname') do
# @param filename The Filename
# @return [String] The Extension starting from the last Period
# @example Determining the Extension of a Filename
# stdlib::extname('test.rb') => '.rb'
# stdlib::extname('a/b/d/test.rb') => '.rb'
# stdlib::extname('test') => ''
# stdlib::extname('.profile') => ''
dispatch :extname do
param 'String', :filename
return_type 'String'
end
def extname(filename)
File.extname(filename)
end
end
# frozen_string_literal: true
# @summary
# Returns true if the ipaddress is within the given CIDRs
#
# @example ip_in_range(<IPv4 Address>, <IPv4 CIDR>)
# stdlib::ip_in_range('10.10.10.53', '10.10.10.0/24') => true
Puppet::Functions.create_function(:'stdlib::ip_in_range') do
# @param ipaddress The IP address to check
# @param range One CIDR or an array of CIDRs
# defining the range(s) to check against
#
# @return [Boolean] True or False
dispatch :ip_in_range do
param 'String', :ipaddress
param 'Variant[String, Array]', :range
return_type 'Boolean'
end
require 'ipaddr'
def ip_in_range(ipaddress, range)
ip = IPAddr.new(ipaddress)
if range.is_a? Array
ranges = range.map { |r| IPAddr.new(r) }
ranges.any? { |rng| rng.include?(ip) }
elsif range.is_a? String
ranges = IPAddr.new(range)
ranges.include?(ip)
end
end
end
# frozen_string_literal: true
# @summary
# Returns true if str starts with one of the prefixes given. Each of the prefixes should be a String.
#
Puppet::Functions.create_function(:'stdlib::start_with') do
# @param test_string The string to check
# @param prefixes The prefixes to check.
# @example
# 'foobar'.stdlib::start_with('foo') => true
# 'foobar'.stdlib::start_with('bar') => false
# 'foObar'.stdlib::start_with(['bar', 'baz']) => false
# @return [Boolean] True or False
dispatch :start_with do
param 'String', :test_string
param 'Variant[String[1],Array[String[1], 1]]', :prefixes
return_type 'Boolean'
end
def start_with(test_string, prefixes)
test_string.start_with?(*prefixes)
end
end
# frozen_string_literal: true
require 'json'
# @summary
# Convert a data structure and output to JSON
#
# @example how to output JSON
# # output json to a file
# file { '/tmp/my.json':
# ensure => file,
# content => to_json($myhash),
# }
#
Puppet::Functions.create_function(:to_json) do
# @param data
# data structure which needs to be converted into JSON
# @return converted data to json
dispatch :to_json do
param 'Any', :data
end
def to_json(data)
data.to_json
end
end
# frozen_string_literal: true
require 'json'
# @summary
# Convert data structure and output to pretty JSON
#
# @example **Usage**
# * how to output pretty JSON to file
# file { '/tmp/my.json':
# ensure => file,
# content => to_json_pretty($myhash),
# }
#
# * how to output pretty JSON skipping over keys with undef values
# file { '/tmp/my.json':
# ensure => file,
# content => to_json_pretty({
# param_one => 'value',
# param_two => undef,
# }, true),
# }
#
# * how to output pretty JSON using tabs for indentation
# file { '/tmp/my.json':
# ensure => file,
# content => to_json_pretty({
# param_one => 'value',
# param_two => {
# param_more => 42,
# },
# }, nil, {indent => ' '}),
# }
Puppet::Functions.create_function(:to_json_pretty) do
# @param data
# data structure which needs to be converted to pretty json
# @param skip_undef
# value `true` or `false`
# @param opts
# hash-map of settings passed to JSON.pretty_generate, see
# https://ruby-doc.org/stdlib-2.0.0/libdoc/json/rdoc/JSON.html#method-i-generate.
# Note that `max_nesting` doesn't take the value `false`; use `-1` instead.
# @return
# converted data to pretty json
dispatch :to_json_pretty do
param 'Variant[Hash, Array]', :data
optional_param 'Optional[Boolean]', :skip_undef
optional_param 'Struct[{
indent => Optional[String],
space => Optional[String],
space_before => Optional[String],
object_nl => Optional[String],
array_nl => Optional[String],
allow_nan => Optional[Boolean],
max_nesting => Optional[Integer[-1,default]],
}]', :opts
end
def to_json_pretty(data, skip_undef = false, opts = nil)
# It's not possible to make an abstract type that can be either a boolean
# false or an integer, so we use -1 as the falsey value
if opts
opts = Hash[opts.map { |k, v| [k.to_sym, v] }]
if opts[:max_nesting] == -1
opts[:max_nesting] = false
end
end
if skip_undef
if data.is_a? Array
data = data.reject { |value| value.nil? }
elsif data.is_a? Hash
data = data.reject { |_, value| value.nil? }
end
end
# Call ::JSON to ensure it references the JSON library from Ruby's standard library
# instead of a random JSON namespace that might be in scope due to user code.
::JSON.pretty_generate(data, opts) << "\n"
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment