Files
puppet-openstacklib/lib/puppet/parser/functions/os_transport_url.rb
Carlos Camacho b3d0590022 Allow integer port in os_transport_url
Currently we only allow to use strings
as the data type for ports.

Due to this we need to cast the data type
in the puppet modules because from THT
this is configured as a Number.

This submission allow to use either string
or numbers for the port parameter in the
os_transport_url function.

Change-Id: I9e56f8e2de542b20fe9e6995506cff5bb435e220
Closes-Bug: #1664561
2017-02-22 10:40:31 +01:00

158 lines
5.0 KiB
Ruby

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