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 fail 'Nodes are not provided!' unless nodes forms = %w(list array hash) fail "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| fail "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 fail "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