Puppet Function: parse_hosts

Defined in:
lib/puppet/parser/functions/parse_hosts.rb
Function type:
Ruby 3.x API

Overview

parse_hosts()Array[Strin

Take an Array of items that may contain port numbers or protocols and return the host information, ports, and protocols.

Works with Hostnames as well as IPv4 and IPv6 addresses.

NOTE: IPv6 addresses will be returned normalized with square brackets around them for clarity.

Examples:


parse_hosts([
  '1.2.3.4',
  'http://1.2.3.4',
  'https://1.2.3.4:443'
])

# Returns

{
  '1.2.3.4' => {
    :ports     => ['443'],
    :protocols => {
      'http'  => [],
      'https' => ['443']
    }
  }
}

Returns:

  • (Array[Strin)

    Array[Strin



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/puppet/parser/functions/parse_hosts.rb', line 2

newfunction(:parse_hosts, :type => :rvalue, :doc  => <<-EOM) do |args|

  # Defaults
  Take an `Array` of items that may contain port numbers or protocols and
  return the host information, ports, and protocols.

  Works with Hostnames as well as IPv4 and IPv6 addresses.

  **NOTE:** IPv6 addresses will be returned normalized with square brackets
  around them for clarity.

  @example

    parse_hosts([
      '1.2.3.4',
      'http://1.2.3.4',
      'https://1.2.3.4:443'
    ])

    # Returns

    {
      '1.2.3.4' => {
        :ports     => ['443'],
        :protocols => {
          'http'  => [],
          'https' => ['443']
        }
      }
    }

  @return [Array[String]]
  EOM
  hosts = args.flatten

  # Validation
  raise Puppet::ParseError, "You must pass a list of hosts." if hosts.empty?

  # Needed to use other functions inside of this one
  Puppet::Parser::Functions.autoloader.loadall

  # Parse!
  parsed_hosts = {}
  hosts.each do |host|

    host = host.strip

    next if host.nil? || host.empty?
    tmp_host = host

    # Initialize.
    protocol = nil
    port = nil
    hostname = nil

    # Get the protocol.
    tmp_host = host.split('://')
    if tmp_host.size == 1
      hostname = tmp_host.first
    else
      protocol = tmp_host.first
      hostname = tmp_host.last
    end

    # Validate with the protocol stripped off
    function_validate_net_list(Array(hostname))

    hostname,port = PuppetX::SIMP::Simplib.split_port(hostname)
    function_validate_port(Array(port)) if (port && !port.empty?)

    # Build a unique list of parsed hosts.
    unless parsed_hosts.key?(hostname)
      parsed_hosts[hostname] = {
        :ports     => [],
        :protocols => {}
      }
    end

    if port
      parsed_hosts[hostname][:ports] << port
    end

    if protocol
      parsed_hosts[hostname][:protocols] = {} unless parsed_hosts[hostname][:protocols]
      parsed_hosts[hostname][:protocols][protocol] = [] unless parsed_hosts[hostname][:protocols][protocol]

      parsed_hosts[hostname][:protocols][protocol] << port if port
    end
  end

  parsed_hosts.keys.each do |host|
    unless parsed_hosts[host][:ports].empty?
      parsed_hosts[host][:ports].uniq!
      parsed_hosts[host][:ports].sort!
    end

    parsed_hosts[host][:protocols].each_key do |protocol|
      unless parsed_hosts[host][:protocols][protocol].empty?
        parsed_hosts[host][:protocols][protocol].uniq!
        parsed_hosts[host][:protocols][protocol].sort!
      end
    end
  end

  parsed_hosts
end