puppet-pacemaker/lib/puppet/parser/functions/pacemaker_cluster_nodes.rb

192 lines
5.2 KiB
Ruby

module Puppet::Parser::Functions
newfunction(
:pacemaker_cluster_nodes,
type: :rvalue,
arity: -2,
doc: <<-eof
Convert different forms of node list to the required form.
Input data can be:
* String 'n1 n2a,n2b n3'
* Array ['n1', ['n2a','n2b'], 'n3']
* Hash { 'name' => 'n1', 'ring0' => '192.168.0.1' }
Hash can have optional keys: name, id, ip, votes,
Node id will be autogenerated unless id key is provided.
Internal nodes structure example:
```
[
{
name: 'node1',
id: '1',
votes: '2',
ring0: '192.168.0.1',
ring1: '172.16.0.1',
},
{
name: 'node2',
id: '2',
votes: '1',
ring0: '192.168.0.2',
ring1: '172.16.0.2',
},
{
name: 'node3',
id: '3',
votes: '1',
ring0: '192.168.0.3',
ring1: '172.16.0.3',
}
]
# All fields except at least one ring address are optional
```
If neither 'ring0' nor 'ring1' are found fields 'ip' and 'name' will be used.
Output forms:
* hash - output the hash of the node ids and their data (used for corosync config template)
* list - output the space ad comma separated nodes and interfaces (used for "pcs cluster setup")
* array - output the plain array of nodes (used for pacemaker_auth or "pcs cluster auth")
eof
) do |args|
nodes = args[0]
form = args[1] || 'hash'
form = form.to_s.downcase
raise(Puppet::Error, 'Nodes are not provided!') if [String, Hash, Array].include? nodes.class and nodes.empty?
forms = %w(list array hash)
raise(Puppet::Error, "Unknown form: '#{form}'") unless forms.include? form
array_formatter = lambda do |structure|
list = []
structure.each do |node|
next unless node.is_a? Hash
list << node['ring0'] if node['ring0']
list << node['ring1'] if node['ring1']
end
list.flatten.compact.uniq
end
list_formatter = lambda do |structure|
list = []
structure.each do |node|
node_rings = []
node_rings[0] = node['ring0'] if node['ring0']
node_rings[1] = node['ring1'] if node['ring1']
list << node_rings.join(',')
end
list.join ' '
end
hash_formatter = lambda do |structure|
hash = {}
structure.each do |node|
id = node['id']
next unless id
hash[id] = node
end
hash
end
node_split_to_rings = lambda do |node|
node = node.to_s.chomp.strip
rings = node.split ','
node_hash = {}
node_hash['ring0'] = rings[0].to_s if rings[0] and rings[0] != ''
node_hash['ring1'] = rings[1].to_s if rings[1] and rings[1] != ''
node_hash
end
node_hash_process = lambda do |node|
ring0 = node['ring0']
ring1 = node['ring1']
ring0 = node['ip'] if node['ip'] and not ring0
ring0 = node['name'] if node['name'] and not ring0
node_hash = {}
node_hash['ring0'] = ring0.to_s if ring0
node_hash['ring1'] = ring1.to_s if ring1
node_hash['name'] = node['name'].to_s if node['name']
node_hash['id'] = node['id'].to_s if node['id']
node_hash['vote'] = node['vote'].to_s if node['vote']
node_hash
end
string_parser = lambda do |string|
string = string.to_s.chomp.strip
node_list = []
string.split.each do |node|
node_hash = node_split_to_rings.call node
next unless node_hash['ring0'] or node_hash['ring1']
node_list << node_hash
end
node_list
end
array_parser = lambda do |array|
array = [array] unless array.is_a? Array
node_list = []
array.each do |node|
if node.is_a? Array
node_hash = {}
node_hash['ring0'] = node[0].to_s if node[0]
node_hash['ring1'] = node[1].to_s if node[1]
elsif node.is_a? Hash
node_hash = node_hash_process.call node
else
node_hash = node_split_to_rings.call node.to_s
end
next unless node_hash['ring0'] or node_hash['ring1']
node_list << node_hash
end
node_list
end
hash_parser = lambda do |hash|
raise(Puppet::Error, "Data is not a hash: #{hash.inspect}") unless hash.is_a? Hash
node_list = []
hash.each do |node_name, node|
node = node.dup
node['name'] = node_name if node_name and not node['name']
node_hash = node_hash_process.call node
next unless node_hash['ring0'] or node_hash['ring1']
node_list << node_hash
end
node_list
end
set_node_ids = lambda do |structure|
next_id = 1
structure.each do |node|
unless node['id']
node['id'] = next_id.to_s
next_id += 1
end
end
end
structure = []
if nodes.is_a? String
structure = string_parser.call nodes
elsif nodes.is_a? Array
structure = array_parser.call nodes
elsif nodes.is_a? Hash
structure = hash_parser.call nodes
else
raise(Puppet::Error, "Got unsupported nodes input data: #{nodes.inspect}")
end
set_node_ids.call structure
if form == 'hash'
hash_formatter.call structure
elsif form == 'list'
list_formatter.call structure
elsif form == 'array'
array_formatter.call structure
end
end
end