Puppet Function: foreman

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

Overview

foreman()Any

Returns:

  • (Any)


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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/puppet/parser/functions/foreman.rb', line 49

newfunction(:foreman, :type => :rvalue) do |args|
  # parse an args hash
  raise Puppet::ParseError, "Foreman: Must supply a Hash to foreman(), not a #{args[0].class}" unless args[0].is_a? Hash
  args_hash     = args[0]
  item          = args_hash["item"]
  search        = args_hash["search"]
  per_page      = args_hash["per_page"]     || "20"
  use_tfmproxy  = args_hash["use_tfmproxy"] || false
  foreman_url   = args_hash["foreman_url"]  || "https://localhost" # defaults: all-in-one
  foreman_user  = args_hash["foreman_user"] || "admin"             # has foreman/puppet
  foreman_pass  = args_hash["foreman_pass"] || "changeme"          # on the same box
  filter_result = args_hash['filter_result'] || false
  timeout       = (args_hash['timeout']      || 5).to_i

  # extend this as required
  searchable_items = %w{ environments fact_values hosts hostgroups puppetclasses smart_proxies subnets }
  raise Puppet::ParseError, "Foreman: Invalid item to search on: #{item}, must be one of #{searchable_items.join(", ")}." unless searchable_items.include?(item)
  raise Puppet::ParseError, "Foreman: Invalid filter_result: #{filter_result}, must be a String or an Array" unless filter_result.is_a? String or filter_result.is_a? Array or filter_result.is_a? Hash or filter_result == false

  begin
    path = "/api/#{CGI.escape(item)}?search=#{CGI.escape(search)}&per_page=#{CGI.escape(per_page)}"

    req = Net::HTTP::Get.new(path)
    req['Content-Type'] = 'application/json'
    req['Accept'] = 'application/json'

    if use_tfmproxy
      configfile = '/etc/foreman-proxy/settings.yml'
      configfile = use_tfmproxy if use_tfmproxy.is_a? String
      raise Puppet::ParseError, "File #{configfile} not found while use_tfmproxy is enabled" unless File.exists?(configfile)
      tfmproxy = YAML.load(File.read(configfile))
      uri = URI.parse(tfmproxy[:foreman_url])
      http = Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = true
      http.ca_file = tfmproxy[:foreman_ssl_ca]
      http.cert = OpenSSL::X509::Certificate.new(File.read(tfmproxy[:foreman_ssl_cert]))
      http.key = OpenSSL::PKey::RSA.new(File.read(tfmproxy[:foreman_ssl_key]), nil)
      http.verify_mode = OpenSSL::SSL::VERIFY_PEER
    else
      uri = URI.parse(foreman_url)
      http = Net::HTTP.new(uri.host, uri.port)
      req.basic_auth(foreman_user, foreman_pass)
      http.use_ssl = true if uri.scheme == 'https'
      http.verify_mode = OpenSSL::SSL::VERIFY_NONE if http.use_ssl?
    end
    results = Timeout::timeout(timeout) { PSON.parse http.request(req).body }
  rescue Exception => e
    raise Puppet::ParseError, "Failed to contact Foreman at #{foreman_url}: #{e}"
  end

  # Filter results
  if filter_result != false and results.has_key?('results')
    filtered_results = Array.new

    if filter_result.is_a? String
      # filter into an array
      results['results'].each do |result|
        if result.has_key?(filter_result)
          filtered_results << result[filter_result]
        end
      end
    elsif filter_result.is_a? Array
      # filter into an array of hashes by given key
      results['results'].each do |result|
        resulthash = Hash.new
        result.each do |key,value|
          if filter_result.include? key
            resulthash[key] = result[key]
          end
        end
        if resulthash != {}
          filtered_results << resulthash
        end
      end
    else
      # filter into an array of hashes while rename keys
      results['results'].each do |result|
        resulthash = Hash.new
        result.each do |key,value|
          if filter_result.include? key
            resulthash[filter_result[key]] = result[key]
          end
        end
        if resulthash != {}
          filtered_results << resulthash
        end
      end
    end
   return filtered_results
  end

  # return unfiltered
  return results
end