From 0bd97be465516fa607f5aa0db6f5450513dc292a Mon Sep 17 00:00:00 2001 From: Sagi Shnaidman Date: Wed, 7 Nov 2018 10:17:37 +0000 Subject: [PATCH] Revert "Use puppet4 functions-api" This reverts commit fd3156bc60ec537ffc53aea1d0e0035c9fe17638. Closes-Bug: #1802083 Change-Id: I7705744cab62f432e2e09bf1ee88bba809609cda --- lib/puppet/functions/normalize_ip_for_uri.rb | 36 ---- .../functions/os_database_connection.rb | 75 ------- lib/puppet/functions/os_transport_url.rb | 189 ------------------ .../functions/is_service_default.rb | 15 +- .../parser/functions/normalize_ip_for_uri.rb | 37 ++++ .../functions/os_database_connection.rb | 81 ++++++++ .../parser/functions/os_transport_url.rb | 157 +++++++++++++++ 7 files changed, 286 insertions(+), 304 deletions(-) delete mode 100644 lib/puppet/functions/normalize_ip_for_uri.rb delete mode 100644 lib/puppet/functions/os_database_connection.rb delete mode 100644 lib/puppet/functions/os_transport_url.rb rename lib/puppet/{ => parser}/functions/is_service_default.rb (60%) create mode 100644 lib/puppet/parser/functions/normalize_ip_for_uri.rb create mode 100644 lib/puppet/parser/functions/os_database_connection.rb create mode 100644 lib/puppet/parser/functions/os_transport_url.rb diff --git a/lib/puppet/functions/normalize_ip_for_uri.rb b/lib/puppet/functions/normalize_ip_for_uri.rb deleted file mode 100644 index 3713b078..00000000 --- a/lib/puppet/functions/normalize_ip_for_uri.rb +++ /dev/null @@ -1,36 +0,0 @@ -# Add brackets if the argument is an IPv6 address. -# Returns the argument untouched otherwise. -# -# CAUTION: this code "fails" when the user is passing -# an IPv6 address with the port in it without the -# brackets: 2001::1:8080, to specify address 2001::1 -# and port 8080. This code will change it to -# [2001::1:8080] as it's a valid ip address. This -# shouldn't be an issue in most cases. -# -# If an array is given, each member will be normalized to -# a valid IPv6 address with brackets when needed. -Puppet::Functions.create_function(:normalize_ip_for_uri) do - def normalize_ip_for_uri(*args) - require 'ipaddr' - - result = [] - args = args[0] if args[0].kind_of?(Array) - args = [args] unless args.kind_of?(Array) - args.each do |ip| - begin - if IPAddr.new(ip).ipv6? - unless ip.match(/\[.+\]/) - Puppet.debug("IP #{ip} is changed to [#{ip}]") - ip = "[#{ip}]" - end - end - rescue ArgumentError - # ignore it - end - result << ip - end - return result[0] if args.size == 1 - result - end -end diff --git a/lib/puppet/functions/os_database_connection.rb b/lib/puppet/functions/os_database_connection.rb deleted file mode 100644 index f63c70b1..00000000 --- a/lib/puppet/functions/os_database_connection.rb +++ /dev/null @@ -1,75 +0,0 @@ -Puppet::Functions.create_function(:os_database_connection) do - def os_database_connection(*args) - require 'uri' - - if (args.size != 1) then - raise(Puppet::ParseError, "os_database_connection(): Wrong number of arguments " + - "given (#{args.size} for 1)") - end - - v = args[0] - klass = v.class - - unless klass == Hash - raise(Puppet::ParseError, "os_database_connection(): Requires an hash, got #{klass}") - end - - v.keys.each do |key| - klass = (key == 'extra') ? Hash : String - unless (v[key].class == klass) or (v[key] == :undef) - raise(Puppet::ParseError, "os_database_connection(): #{key} should be a #{klass}") - end - end - - parts = {} - - unless v.include?('dialect') - raise(Puppet::ParseError, 'os_database_connection(): dialect is required') - end - - if v.include?('host') - parts[:host] = v['host'] - end - - unless v.include?('database') - raise(Puppet::ParseError, 'os_database_connection(): database is required') - end - - if v.include?('port') - if v.include?('host') - parts[:port] = v['port'].to_i - else - raise(Puppet::ParseError, 'os_database_connection(): host is required with port') - end - end - - if v.include?('username') and (v['username'] != :undef) and (v['username'].to_s != '') - parts[:userinfo] = URI.escape(v['username']) - if v.include?('password') and (v['password'] != :undef) and (v['password'].to_s != '') - parts[:userinfo] += ":#{URI.escape(v['password'])}" - end - end - - # support previous charset option on the function. Setting charset will - # override charset if passed in via the extra parameters - if v.include?('charset') - if v.include?('extra') - v['extra'].merge!({ 'charset' => v['charset'] }) - else - v['extra'] = { 'charset' => v['charset'] } - end - end - - parts[:query] = v['extra'].map{ |k,v| "#{k}=#{v}" }.join('&') if v.include?('extra') - - parts[:scheme] = v['dialect'] - - if v.include?('host') - parts[:path] = "/#{v['database']}" - else - parts[:path] = "///#{v['database']}" - end - - URI::Generic.build(parts).to_s - end -end diff --git a/lib/puppet/functions/os_transport_url.rb b/lib/puppet/functions/os_transport_url.rb deleted file mode 100644 index b8f90b03..00000000 --- a/lib/puppet/functions/os_transport_url.rb +++ /dev/null @@ -1,189 +0,0 @@ -# This function builds a os_transport_url string from a hash of parameters. -# -# Valid hash parameteres: -# * transport - (string) type of transport, 'rabbit' or 'amqp' -# * host - (string) single host -# * hosts - (array) array of hosts to use -# * port - (string | integer) port to connect to -# * username - (string) connection username -# * password - (string) connection password -# * virtual_host - (string) virtual host to connect to -# * ssl - (string) is the connection ssl or not ('1' or '0'). overrides the ssl -# key in the query parameter -# * query - (hash) hash of key,value pairs used to create a query string for -# the transport_url. -# -# Only 'transport' and either 'host' or 'hosts' are required keys for the -# parameters hash. -# -# The url format that will be generated: -# transport://user:pass@host:port[,userN:passN@hostN:portN]/virtual_host?query -# -# NOTE: ipv6 addresses will automatically be bracketed for the URI using the -# normalize_ip_for_uri function. -# -# Single Host Example: -# os_transport_url({ -# 'transport' => 'rabbit', -# 'host' => '1.1.1.1', -# 'port' => '5672', -# 'username' => 'username', -# 'password' => 'password', -# 'virtual_host' => 'virtual_host', -# 'ssl' => '1', -# 'query' => { 'key' => 'value' }, -# }) -# -# Generates: -# rabbit://username:password@1.1.1.1:5672/virtual_host?key=value&ssl=1 -# -# Multiple Hosts Example: -# os_transport_url({ -# 'transport' => 'rabbit', -# 'hosts' => [ '1.1.1.1', '2.2.2.2' ], -# 'port' => '5672', -# 'username' => 'username', -# 'password' => 'password', -# 'virtual_host' => 'virtual_host', -# 'query' => { 'key' => 'value' }, -# }) -# -# Generates: -# rabbit://username:password@1.1.1.1:5672,username:password@2.2.2.2:5672/virtual_host?key=value -Puppet::Functions.create_function(:os_transport_url) do - # TODO(tobias-urdin): Rework and remove this. - # Taken straight from stdlib v5.1.0 module. - def _str2bool(string) - if !!string == string - return string - end - unless string.is_a?(String) - raise(Puppet::ParseError, 'str2bool(): Requires string to work with') - end - result = case string - when %r{^$}, '' then false # Empty string will be false ... - when %r{^(1|t|y|true|yes)$}i then true - when %r{^(0|f|n|false|no)$}i then false - when %r{^(undef|undefined)$} then false # This is not likely to happen ... - else - raise(Puppet::ParseError, 'os_transport_url _str2bool(): Unknown type of boolean given') - end - return result - end - - # TODO(tobias-urdin): Rework and remove this. - # Taken straight from stdlib v5.1.0 module. - def _bool2num(val) - value = _str2bool(val) - result = value ? 1 : 0 - return result - end - - def os_transport_url(*args) - require 'uri' - - unless args.size == 1 - raise(ArgumentError, 'os_transport_url(): Wrong number of arguments') - end - - v = args[0] - klass = v.class - - unless klass == Hash - raise(Puppet::ParseError, "os_transport_url(): Requires an hash, got #{klass}") - end - - # type checking for the parameter hash - v.keys.each do |key| - v[key] = v[key].to_s if key == 'port' - klass = (key == 'hosts') ? Array : String - klass = (key == 'query') ? Hash : klass - unless (v[key].class == klass) or (v[key] == :undef) - raise(Puppet::ParseError, "os_transport_url(): #{key} should be a #{klass}") - end - end - - # defaults - parts = { - :transport => 'rabbit', - :hostinfo => 'localhost', - :path => '/', - } - - unless v.include?('transport') - raise(Puppet::ParseError, 'os_transport_url(): transport is required') - end - - unless v.include?('host') or v.include?('hosts') - raise(Puppet::ParseError, 'os_transport_url(): host or hosts is required') - end - - if v.include?('host') and v.include?('hosts') - raise(Puppet::ParseError, 'os_transport_url(): cannot use both host and hosts.') - end - - parts[:transport] = v['transport'] - - if v.include?('username') and (v['username'] != :undef) and (v['username'].to_s != '') - parts[:userinfo] = URI.escape(v['username']) - if v.include?('password') and (v['password'] != :undef) and (v['password'].to_s != '') - parts[:userinfo] += ":#{URI.escape(v['password'])}" - end - end - - if v.include?('host') - host = call_function('normalize_ip_for_uri', v['host']) - host += ":#{v['port'].to_s}" if v.include?('port') - if parts.include?(:userinfo) - parts[:hostinfo] = "#{parts[:userinfo]}@#{host}" - else - parts[:hostinfo] = "#{host}" - end - end - - if v.include?('hosts') - hosts = call_function('normalize_ip_for_uri', v['hosts']) - # normalize_ip_for_uri may return a string, so check that we still have an - # array - hosts = [hosts] if hosts.kind_of?(String) - hosts = hosts.map{ |h| "#{h}:#{v['port'].to_s}" } if v.include?('port') - if parts.include?(:userinfo) - parts[:hostinfo] = hosts.map { |h| "#{parts[:userinfo]}@#{h}" }.join(',') - else - parts[:hostinfo] = hosts.join(',') - end - end - - parts[:path] = "/#{v['virtual_host']}" if v.include?('virtual_host') - - # support previous ssl option on the function. Setting ssl will - # override ssl if passed in via the query parameters - if v.include?('ssl') - # ssl can be passed in as a query paramter but should be 0/1. See - # http://docs.celeryproject.org/projects/kombu/en/latest/userguide/connections.html#urls - # so we rely on _str2bool and _bool2num to ensure it's in the - # format - # TODO(tobias-urdin): Rework this to using proper data types and not the - # legacy puppet functions that is copied into this function statement. - # We need to do this right now because it fails testing if we call the - # str2bool or bool2num legacy functions using call_function. - ssl_str = _str2bool(v['ssl']) - ssl_val = _bool2num(v['ssl']) - if v.include?('query') - v['query'].merge!({ 'ssl' => ssl_val }) - else - v['query'] = { 'ssl' => ssl_val } - end - end - - parts[:query] = v['query'].map{ |k,val| "#{k}=#{val}" }.join('&') if v.include?('query') - - url_parts = [] - url_parts << parts[:transport] - url_parts << '://' - url_parts << parts[:hostinfo] - url_parts << parts[:path] - url_parts << '?' << parts[:query] if parts.include?(:query) - url_parts.join() - end -end diff --git a/lib/puppet/functions/is_service_default.rb b/lib/puppet/parser/functions/is_service_default.rb similarity index 60% rename from lib/puppet/functions/is_service_default.rb rename to lib/puppet/parser/functions/is_service_default.rb index a016a603..9af9148b 100644 --- a/lib/puppet/functions/is_service_default.rb +++ b/lib/puppet/parser/functions/is_service_default.rb @@ -1,15 +1,22 @@ +# +# is_service_default.rb +# # This function can be used to check if a variable is set to the default value # of '' # # For reference: # http://lists.openstack.org/pipermail/openstack-dev/2015-July/069823.html # https://github.com/openstack/puppet-openstacklib/commit/3b85306d042292713d0fd89fa508e0a0fbf99671 -Puppet::Functions.create_function(:is_service_default) do - def is_service_default(*args) +# +module Puppet::Parser::Functions + newfunction(:is_service_default, :type => :rvalue, :doc => <<-EOS +Returns true if the variable passed to this function is '' + EOS + ) do |arguments| raise(Puppet::ParseError, "is_service_default(): Wrong number of arguments" + - "given (#{args.size} for 1)") if args.size != 1 + "given (#{arguments.size} for 1)") if arguments.size != 1 - value = args[0] + value = arguments[0] unless value.is_a?(String) return false diff --git a/lib/puppet/parser/functions/normalize_ip_for_uri.rb b/lib/puppet/parser/functions/normalize_ip_for_uri.rb new file mode 100644 index 00000000..92dead9a --- /dev/null +++ b/lib/puppet/parser/functions/normalize_ip_for_uri.rb @@ -0,0 +1,37 @@ +require 'ipaddr' + +module Puppet::Parser::Functions + newfunction(:normalize_ip_for_uri, + :type => :rvalue, + :doc => <<-EOD + Add brackets if the argument is an IPv6 address. + Returns the argument untouched otherwise. + CAUTION: this code "fails" when the user is passing + an IPv6 address with the port in it without the + brackets: 2001::1:8080, to specify address 2001::1 + and port 8080. This code will change it to + [2001::1:8080] as it's a valid ip address. This + shouldn't be an issue in most cases. + If an array is given, each member will be normalized to + a valid IPv6 address with brackets when needed. + EOD + ) do |args| + result = [] + args = args[0] if args[0].kind_of?(Array) + args.each do |ip| + begin + if IPAddr.new(ip).ipv6? + unless ip.match(/\[.+\]/) + Puppet.debug("IP #{ip} is changed to [#{ip}]") + ip = "[#{ip}]" + end + end + rescue ArgumentError + # ignore it + end + result << ip + end + return result[0] if args.size == 1 + result + end +end diff --git a/lib/puppet/parser/functions/os_database_connection.rb b/lib/puppet/parser/functions/os_database_connection.rb new file mode 100644 index 00000000..4cc428d9 --- /dev/null +++ b/lib/puppet/parser/functions/os_database_connection.rb @@ -0,0 +1,81 @@ +require 'puppet/parser/functions' + +Puppet::Parser::Functions.newfunction(:os_database_connection, + :type => :rvalue, + :doc => <<-EOS +This function builds a os_database_connection string from various parameters. +EOS +) do |arguments| + + require 'uri' + + if (arguments.size != 1) then + raise(Puppet::ParseError, "os_database_connection(): Wrong number of arguments " + + "given (#{arguments.size} for 1)") + end + + v = arguments[0] + klass = v.class + + unless klass == Hash + raise(Puppet::ParseError, "os_database_connection(): Requires an hash, got #{klass}") + end + + v.keys.each do |key| + klass = (key == 'extra') ? Hash : String + unless (v[key].class == klass) or (v[key] == :undef) + raise(Puppet::ParseError, "os_database_connection(): #{key} should be a #{klass}") + end + end + + parts = {} + + unless v.include?('dialect') + raise(Puppet::ParseError, 'os_database_connection(): dialect is required') + end + + if v.include?('host') + parts[:host] = v['host'] + end + + unless v.include?('database') + raise(Puppet::ParseError, 'os_database_connection(): database is required') + end + + if v.include?('port') + if v.include?('host') + parts[:port] = v['port'].to_i + else + raise(Puppet::ParseError, 'os_database_connection(): host is required with port') + end + end + + if v.include?('username') and (v['username'] != :undef) and (v['username'].to_s != '') + parts[:userinfo] = URI.escape(v['username']) + if v.include?('password') and (v['password'] != :undef) and (v['password'].to_s != '') + parts[:userinfo] += ":#{URI.escape(v['password'])}" + end + end + + # support previous charset option on the function. Setting charset will + # override charset if passed in via the extra parameters + if v.include?('charset') + if v.include?('extra') + v['extra'].merge!({ 'charset' => v['charset'] }) + else + v['extra'] = { 'charset' => v['charset'] } + end + end + + parts[:query] = v['extra'].map{ |k,v| "#{k}=#{v}" }.join('&') if v.include?('extra') + + parts[:scheme] = v['dialect'] + + if v.include?('host') + parts[:path] = "/#{v['database']}" + else + parts[:path] = "///#{v['database']}" + end + + URI::Generic.build(parts).to_s +end diff --git a/lib/puppet/parser/functions/os_transport_url.rb b/lib/puppet/parser/functions/os_transport_url.rb new file mode 100644 index 00000000..7c611a91 --- /dev/null +++ b/lib/puppet/parser/functions/os_transport_url.rb @@ -0,0 +1,157 @@ +require 'puppet/parser/functions' + +Puppet::Parser::Functions.newfunction(:os_transport_url, + :type => :rvalue, + :arity => 1, + :doc => <<-EOS +This function builds a os_transport_url string from a hash of parameters. + +Valid hash parameteres: + * transport - (string) type of transport, 'rabbit' or 'amqp' + * host - (string) single host + * hosts - (array) array of hosts to use + * port - (string | integer) port to connect to + * username - (string) connection username + * password - (string) connection password + * virtual_host - (string) virtual host to connect to + * ssl - (string) is the connection ssl or not ('1' or '0'). overrides the ssl + key in the query parameter + * query - (hash) hash of key,value pairs used to create a query string for + the transport_url. + +Only 'transport' and either 'host' or 'hosts' are required keys for the +parameters hash. + +The url format that will be generated: +transport://user:pass@host:port[,userN:passN@hostN:portN]/virtual_host?query + +NOTE: ipv6 addresses will automatically be bracketed for the URI using the +normalize_ip_for_uri function. + +Single Host Example: +os_transport_url({ + 'transport' => 'rabbit', + 'host' => '1.1.1.1', + 'port' => '5672', + 'username' => 'username', + 'password' => 'password', + 'virtual_host' => 'virtual_host', + 'ssl' => '1', + 'query' => { 'key' => 'value' }, +}) +Generates: +rabbit://username:password@1.1.1.1:5672/virtual_host?key=value&ssl=1 + +Multiple Hosts Example: +os_transport_url({ + 'transport' => 'rabbit', + 'hosts' => [ '1.1.1.1', '2.2.2.2' ], + 'port' => '5672', + 'username' => 'username', + 'password' => 'password', + 'virtual_host' => 'virtual_host', + 'query' => { 'key' => 'value' }, +}) +Generates: +rabbit://username:password@1.1.1.1:5672,username:password@2.2.2.2:5672/virtual_host?key=value +EOS +) do |arguments| + + require 'uri' + + v = arguments[0] + klass = v.class + + unless klass == Hash + raise(Puppet::ParseError, "os_transport_url(): Requires an hash, got #{klass}") + end + + # type checking for the parameter hash + v.keys.each do |key| + v[key] = v[key].to_s if key == 'port' + klass = (key == 'hosts') ? Array : String + klass = (key == 'query') ? Hash : klass + unless (v[key].class == klass) or (v[key] == :undef) + raise(Puppet::ParseError, "os_transport_url(): #{key} should be a #{klass}") + end + end + + # defaults + parts = { + :transport => 'rabbit', + :hostinfo => 'localhost', + :path => '/', + } + + unless v.include?('transport') + raise(Puppet::ParseError, 'os_transport_url(): transport is required') + end + + unless v.include?('host') or v.include?('hosts') + raise(Puppet::ParseError, 'os_transport_url(): host or hosts is required') + end + + if v.include?('host') and v.include?('hosts') + raise(Puppet::ParseError, 'os_transport_url(): cannot use both host and hosts.') + end + + parts[:transport] = v['transport'] + + if v.include?('username') and (v['username'] != :undef) and (v['username'].to_s != '') + parts[:userinfo] = URI.escape(v['username']) + if v.include?('password') and (v['password'] != :undef) and (v['password'].to_s != '') + parts[:userinfo] += ":#{URI.escape(v['password'])}" + end + end + + if v.include?('host') + host = function_normalize_ip_for_uri([v['host']]) + host += ":#{v['port'].to_s}" if v.include?('port') + if parts.include?(:userinfo) + parts[:hostinfo] = "#{parts[:userinfo]}@#{host}" + else + parts[:hostinfo] = "#{host}" + end + end + + if v.include?('hosts') + hosts = function_normalize_ip_for_uri([v['hosts']]) + # normalize_ip_for_uri may return a string, so check that we still have an + # array + hosts = [hosts] if hosts.kind_of?(String) + hosts = hosts.map{ |h| "#{h}:#{v['port'].to_s}" } if v.include?('port') + if parts.include?(:userinfo) + parts[:hostinfo] = hosts.map { |h| "#{parts[:userinfo]}@#{h}" }.join(',') + else + parts[:hostinfo] = hosts.join(',') + end + end + + parts[:path] = "/#{v['virtual_host']}" if v.include?('virtual_host') + + # support previous ssl option on the function. Setting ssl will + # override ssl if passed in via the query parameters + if v.include?('ssl') + # ssl can be passed in as a query paramter but should be 0/1. See + # http://docs.celeryproject.org/projects/kombu/en/latest/userguide/connections.html#urls + # so we rely on the stdlib str2bool and bool2num to ensure it's in the + # format + ssl_val = function_bool2num([function_str2bool([v['ssl']])]) + if v.include?('query') + v['query'].merge!({ 'ssl' => ssl_val }) + else + v['query'] = { 'ssl' => ssl_val } + end + end + + parts[:query] = v['query'].map{ |k,val| "#{k}=#{val}" }.join('&') if v.include?('query') + + + url_parts = [] + url_parts << parts[:transport] + url_parts << '://' + url_parts << parts[:hostinfo] + url_parts << parts[:path] + url_parts << '?' << parts[:query] if parts.include?(:query) + url_parts.join() +end