Files
puppet-openstacklib/lib/puppet/functions/os_transport_url.rb
Takashi Kajinami 4ce49e9f74 Import functions from stdlib
... instead of copying the implementations into our modules. The issue
with unit tests, which is described in the comment, is no longer seen.

Change-Id: If5dd1a7d8987010f35e164861c807869128f690c
2023-10-31 22:13:42 +09:00

168 lines
5.4 KiB
Ruby

# 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
def os_transport_url(*args)
require 'erb'
unless args.size == 1
raise(ArgumentError, 'os_transport_url(): Wrong number of arguments')
end
v_raw = args[0]
klass = v_raw.class
unless klass == Hash
raise(Puppet::ParseError, "os_transport_url(): Requires an hash, got #{klass}")
end
v = {}
# type checking for the parameter hash
v_raw.keys.each do |key|
if key == 'port'
v[key] = v_raw[key].to_s
else
v[key] = v_raw[key]
end
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] = ERB::Util.url_encode(v['username'])
if v.include?('password') and (v['password'] != :undef) and (v['password'].to_s != '')
parts[:userinfo] += ":#{ERB::Util.url_encode(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')
query = {}
if v.include?('query')
query.merge!(v['query'])
end
# 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.
ssl_str = call_function('str2bool', v['ssl'])
ssl_val = call_function('bool2num', v['ssl'])
query.merge!({ 'ssl' => ssl_val })
end
parts[:query] = query.map{ |k,val| "#{k}=#{val}" }.join('&') if ! query.empty?
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