| 
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
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 | # File 'lib/puppet/functions/foreman/foreman.rb', line 47
Puppet::Functions.create_function(:'foreman::foreman') do
  dispatch :foreman do
    required_param 'Enum["environments", "fact_values", "hosts", "hostgroups", "puppetclasses", "smart_proxies", "subnets"]', :item
    required_param 'String', :search
    optional_param 'Variant[Integer[0], Pattern[/\d+/]]', :per_page
    optional_param 'Stdlib::HTTPUrl', :foreman_url
    optional_param 'String', :foreman_user
    optional_param 'String', :foreman_pass
    optional_param 'Integer[0]', :timeout
    optional_param 'Variant[String, Array, Hash, Boolean]', :filter_result
    optional_param 'Variant[Boolean, String]', :use_tfmproxy
  end
  def foreman(item, search, per_page = "20", foreman_url = "https://localhost", foreman_user = "admin", foreman_pass = "changeme", timeout = 5, filter_result = false, use_tfmproxy = false)
        raise Puppet::ParseError, "Foreman: Invalid filter_result: #{filter_result}, must not be boolean true" if filter_result == true
    begin
      path = "/api/#{CGI.escape(item)}?search=#{CGI.escape(search)}&per_page=#{CGI.escape(per_page.to_s)}"
      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
        if filter_result != false and results.has_key?('results')
      filtered_results = Array.new
      if filter_result.is_a? String
                results['results'].each do |result|
          if result.has_key?(filter_result)
            filtered_results << result[filter_result]
          end
        end
      elsif filter_result.is_a? Array
                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
                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 results
  end
end |