md-puppetdb-terminus 2.0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +202 -0
- data/README.md +29 -0
- data/Rakefile +16 -0
- data/lib/md-puppetdb-terminus.rb +1 -0
- data/lib/puppet/application/storeconfigs.rb +4 -0
- data/lib/puppet/face/node/deactivate.rb +38 -0
- data/lib/puppet/face/node/status.rb +83 -0
- data/lib/puppet/face/storeconfigs.rb +179 -0
- data/lib/puppet/indirector/catalog/puppetdb.rb +350 -0
- data/lib/puppet/indirector/facts/puppetdb.rb +134 -0
- data/lib/puppet/indirector/facts/puppetdb_apply.rb +25 -0
- data/lib/puppet/indirector/node/puppetdb.rb +22 -0
- data/lib/puppet/indirector/resource/puppetdb.rb +107 -0
- data/lib/puppet/reports/puppetdb.rb +186 -0
- data/lib/puppet/util/puppetdb.rb +108 -0
- data/lib/puppet/util/puppetdb/blacklist.rb +35 -0
- data/lib/puppet/util/puppetdb/char_encoding.rb +212 -0
- data/lib/puppet/util/puppetdb/command.rb +113 -0
- data/lib/puppet/util/puppetdb/command_names.rb +8 -0
- data/lib/puppet/util/puppetdb/config.rb +112 -0
- data/lib/puppet/util/puppetdb/global_check.rb +31 -0
- data/lib/puppetdb-terminus.rb +1 -0
- data/lib/puppetdb/terminus.rb +6 -0
- data/lib/puppetdb/terminus/version.rb +5 -0
- data/puppetdb-terminus.gemspec +23 -0
- metadata +99 -0
@@ -0,0 +1,350 @@
|
|
1
|
+
require 'puppet/resource/catalog'
|
2
|
+
require 'puppet/indirector/rest'
|
3
|
+
require 'puppet/util/puppetdb'
|
4
|
+
|
5
|
+
class Puppet::Resource::Catalog::Puppetdb < Puppet::Indirector::REST
|
6
|
+
include Puppet::Util::Puppetdb
|
7
|
+
include Puppet::Util::Puppetdb::CommandNames
|
8
|
+
|
9
|
+
# Run initial checks
|
10
|
+
def initialize
|
11
|
+
Puppet::Util::Puppetdb::GlobalCheck.run
|
12
|
+
end
|
13
|
+
|
14
|
+
def save(request)
|
15
|
+
profile "catalog#save" do
|
16
|
+
catalog = munge_catalog(request.instance, extract_extra_request_data(request))
|
17
|
+
|
18
|
+
submit_command(request.key, catalog, CommandReplaceCatalog, 4)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def find(request)
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
26
|
+
# @api private
|
27
|
+
def extract_extra_request_data(request)
|
28
|
+
{
|
29
|
+
:transaction_uuid => request.options[:transaction_uuid],
|
30
|
+
:environment => request.environment,
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def munge_catalog(catalog, extra_request_data = {})
|
35
|
+
profile "Munge catalog" do
|
36
|
+
hash = profile "Convert catalog to PSON data hash" do
|
37
|
+
catalog.to_pson_data_hash
|
38
|
+
end
|
39
|
+
|
40
|
+
data = hash['data']
|
41
|
+
|
42
|
+
add_parameters_if_missing(data)
|
43
|
+
add_namevar_aliases(data, catalog)
|
44
|
+
stringify_titles(data)
|
45
|
+
stringify_version(data)
|
46
|
+
sort_unordered_metaparams(data)
|
47
|
+
munge_edges(data)
|
48
|
+
synthesize_edges(data, catalog)
|
49
|
+
filter_keys(data)
|
50
|
+
add_transaction_uuid(data, extra_request_data[:transaction_uuid])
|
51
|
+
add_environment(data, extra_request_data[:environment])
|
52
|
+
|
53
|
+
data
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
Relationships = {
|
58
|
+
:before => {:direction => :forward, :relationship => 'before'},
|
59
|
+
:require => {:direction => :reverse, :relationship => 'required-by'},
|
60
|
+
:notify => {:direction => :forward, :relationship => 'notifies'},
|
61
|
+
:subscribe => {:direction => :reverse, :relationship => 'subscription-of'},
|
62
|
+
}
|
63
|
+
|
64
|
+
# Metaparams that may contain arrays, but whose semantics are
|
65
|
+
# fundamentally unordered
|
66
|
+
UnorderedMetaparams = [:alias, :audit, :before, :check, :notify, :require, :subscribe, :tag]
|
67
|
+
|
68
|
+
# Include environment in hash, returning the complete hash.
|
69
|
+
#
|
70
|
+
# @param hash [Hash] original data hash
|
71
|
+
# @param environment [String] environment
|
72
|
+
# @return [Hash] returns original hash augmented with environment
|
73
|
+
# @api private
|
74
|
+
def add_environment(hash, environment)
|
75
|
+
hash['environment'] = environment
|
76
|
+
|
77
|
+
hash
|
78
|
+
end
|
79
|
+
|
80
|
+
# Include transaction_uuid in hash, returning the complete hash.
|
81
|
+
#
|
82
|
+
# @param hash [Hash] original data hash
|
83
|
+
# @param transaction_uuid [String] transaction_uuid
|
84
|
+
# @return [Hash] returns original hash augmented with transaction_uuid
|
85
|
+
# @api private
|
86
|
+
def add_transaction_uuid(hash, transaction_uuid)
|
87
|
+
hash['transaction-uuid'] = transaction_uuid
|
88
|
+
|
89
|
+
hash
|
90
|
+
end
|
91
|
+
|
92
|
+
# Version is an integer (time since epoch in millis). The wire
|
93
|
+
# format specifies version should be a string
|
94
|
+
#
|
95
|
+
# @param hash [Hash] original data hash
|
96
|
+
# @return [Hash] returns a modified original hash
|
97
|
+
def stringify_version(hash)
|
98
|
+
hash['version'] = hash['version'].to_s
|
99
|
+
|
100
|
+
hash
|
101
|
+
end
|
102
|
+
|
103
|
+
def stringify_titles(hash)
|
104
|
+
resources = hash['resources']
|
105
|
+
profile "Stringify titles (resource count: #{resources.count})" do
|
106
|
+
resources.each do |resource|
|
107
|
+
resource['title'] = resource['title'].to_s
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
hash
|
112
|
+
end
|
113
|
+
|
114
|
+
def add_parameters_if_missing(hash)
|
115
|
+
resources = hash['resources']
|
116
|
+
profile "Add parameters if missing (resource count: #{resources.count})" do
|
117
|
+
resources.each do |resource|
|
118
|
+
resource['parameters'] ||= {}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
hash
|
123
|
+
end
|
124
|
+
|
125
|
+
def add_namevar_aliases(hash, catalog)
|
126
|
+
resources = hash['resources']
|
127
|
+
profile "Add namevar aliases (resource count: #{resources.count})" do
|
128
|
+
resources.each do |resource|
|
129
|
+
real_resource = catalog.resource(resource['type'], resource['title'])
|
130
|
+
|
131
|
+
# Resources with composite namevars can't be referred to by
|
132
|
+
# anything other than their title when declaring
|
133
|
+
# relationships. Trying to snag the :alias for these resources
|
134
|
+
# will only return _part_ of the name (a problem with Puppet
|
135
|
+
# proper), so skipping the adding of aliases for these resources
|
136
|
+
# is both an optimization and a safeguard.
|
137
|
+
next if real_resource.key_attributes.count > 1
|
138
|
+
|
139
|
+
aliases = [real_resource[:alias]].flatten.compact
|
140
|
+
|
141
|
+
# Non-isomorphic resources aren't unique based on namevar, so we can't
|
142
|
+
# use it as an alias
|
143
|
+
type = real_resource.resource_type
|
144
|
+
if !type.respond_to?(:isomorphic?) or type.isomorphic?
|
145
|
+
# This makes me a little sad. It turns out that the "to_hash" method
|
146
|
+
# of Puppet::Resource can have side effects. In particular, if the
|
147
|
+
# resource type specifies a title_pattern, calling "to_hash" will trigger
|
148
|
+
# the title_pattern processing, which can have the side effect of
|
149
|
+
# populating the namevar (potentially with a munged value). Thus,
|
150
|
+
# it is important that we search for namevar aliases in that hash
|
151
|
+
# rather than in the resource itself.
|
152
|
+
real_resource_hash = real_resource.to_hash
|
153
|
+
|
154
|
+
name = real_resource_hash[real_resource.send(:namevar)]
|
155
|
+
unless name.nil? or real_resource.title == name or aliases.include?(name)
|
156
|
+
aliases << name
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
resource['parameters']['alias'] = aliases unless aliases.empty?
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
hash
|
165
|
+
end
|
166
|
+
|
167
|
+
def sort_unordered_metaparams(hash)
|
168
|
+
resources = hash['resources']
|
169
|
+
profile "Sort unordered metaparams (resource count: #{resources.count})" do
|
170
|
+
resources.each do |resource|
|
171
|
+
params = resource['parameters']
|
172
|
+
UnorderedMetaparams.each do |metaparam|
|
173
|
+
if params[metaparam].kind_of? Array then
|
174
|
+
values = params[metaparam].sort
|
175
|
+
params[metaparam] = values unless values.empty?
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
hash
|
182
|
+
end
|
183
|
+
|
184
|
+
def munge_edges(hash)
|
185
|
+
edges = hash['edges']
|
186
|
+
profile "Munge edges (edge count: #{edges.count})" do
|
187
|
+
edges.each do |edge|
|
188
|
+
%w[source target].each do |vertex|
|
189
|
+
edge[vertex] = resource_ref_to_hash(edge[vertex]) if edge[vertex].is_a?(String)
|
190
|
+
end
|
191
|
+
edge['relationship'] ||= 'contains'
|
192
|
+
end
|
193
|
+
|
194
|
+
hash
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def map_aliases_to_title(hash)
|
199
|
+
resources = hash['resources']
|
200
|
+
aliases = {}
|
201
|
+
|
202
|
+
profile "Map aliases to title (resource count: #{resources.count})" do
|
203
|
+
resources.each do |resource|
|
204
|
+
names = resource['parameters']['alias'] || []
|
205
|
+
resource_hash = {'type' => resource['type'], 'title' => resource['title']}
|
206
|
+
names.each do |name|
|
207
|
+
alias_array = [resource['type'], name]
|
208
|
+
aliases[alias_array] = resource_hash
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
aliases
|
214
|
+
end
|
215
|
+
|
216
|
+
def synthesize_edges(hash, catalog)
|
217
|
+
profile "Synthesize edges" do
|
218
|
+
aliases = map_aliases_to_title(hash)
|
219
|
+
|
220
|
+
resource_table = {}
|
221
|
+
profile "Build up resource_table" do
|
222
|
+
hash['resources'].each do |resource|
|
223
|
+
resource_table[ [resource['type'], resource['title']] ] = resource
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
profile "Primary synthesis" do
|
228
|
+
hash['resources'].each do |resource|
|
229
|
+
# Standard virtual resources don't appear in the catalog. However,
|
230
|
+
# exported resources which haven't been also collected will appears as
|
231
|
+
# exported and virtual (collected ones will only be exported). They will
|
232
|
+
# eventually be removed from the catalog, so we can't add edges involving
|
233
|
+
# them. Puppet::Resource#to_pson_data_hash omits 'virtual', so we have to
|
234
|
+
# look it up in the catalog to find that information. This isn't done in
|
235
|
+
# a separate step because we don't actually want to send the field (it
|
236
|
+
# will always be false). See ticket #16472.
|
237
|
+
#
|
238
|
+
# The outer conditional is here because Class[main] can't properly be
|
239
|
+
# looked up using catalog.resource and will return nil. See ticket
|
240
|
+
# #16473. Yay.
|
241
|
+
if real_resource = catalog.resource(resource['type'], resource['title'])
|
242
|
+
next if real_resource.virtual?
|
243
|
+
end
|
244
|
+
|
245
|
+
Relationships.each do |param,relation|
|
246
|
+
if value = resource['parameters'][param]
|
247
|
+
[value].flatten.each do |other_ref|
|
248
|
+
edge = {'relationship' => relation[:relationship]}
|
249
|
+
|
250
|
+
resource_hash = {'type' => resource['type'], 'title' => resource['title']}
|
251
|
+
other_hash = resource_ref_to_hash(other_ref)
|
252
|
+
|
253
|
+
# Puppet doesn't always seem to check this correctly. If we don't
|
254
|
+
# users will later get an invalid relationship error instead.
|
255
|
+
#
|
256
|
+
# Primarily we are trying to catch the non-capitalized resourceref
|
257
|
+
# case problem here: http://projects.puppetlabs.com/issues/19474
|
258
|
+
# Once that problem is solved and older versions of Puppet that have
|
259
|
+
# the bug are no longer supported we can probably remove this code.
|
260
|
+
unless other_ref =~ /^[A-Z][a-z0-9_]*(::[A-Z][a-z0-9_]*)*\[.*\]/
|
261
|
+
rel = edge_to_s(resource_hash_to_ref(resource_hash), other_ref, param)
|
262
|
+
raise Puppet::Error, "Invalid relationship: #{rel}, because " +
|
263
|
+
"#{other_ref} doesn't seem to be in the correct format. " +
|
264
|
+
"Resource references should be formatted as: " +
|
265
|
+
"Classname['title'] or Modulename::Classname['title'] (take " +
|
266
|
+
"careful note of the capitalization)."
|
267
|
+
end
|
268
|
+
|
269
|
+
# This is an unfortunate hack. Puppet does some weird things w/rt
|
270
|
+
# munging off trailing slashes from file resources, and users may
|
271
|
+
# legally specify relationships using a different number of trailing
|
272
|
+
# slashes than the resource was originally declared with.
|
273
|
+
# We do know that for any file resource in the catalog, there should
|
274
|
+
# be a canonical entry for it that contains no trailing slashes. So,
|
275
|
+
# here, in case someone has specified a relationship to a file resource
|
276
|
+
# and has used one or more trailing slashes when specifying the
|
277
|
+
# relationship, we will munge off the trailing slashes before
|
278
|
+
# we look up the resource in the catalog to create the edge.
|
279
|
+
if other_hash['type'] == 'File' and other_hash['title'] =~ /\/$/
|
280
|
+
other_hash['title'] = other_hash['title'].sub(/\/+$/, '')
|
281
|
+
end
|
282
|
+
|
283
|
+
other_array = [other_hash['type'], other_hash['title']]
|
284
|
+
|
285
|
+
# Try to find the resource by type/title or look it up as an alias
|
286
|
+
# and try that
|
287
|
+
other_resource = resource_table[other_array]
|
288
|
+
if other_resource.nil? and alias_hash = aliases[other_array]
|
289
|
+
other_resource = resource_table[ alias_hash.values_at('type', 'title') ]
|
290
|
+
end
|
291
|
+
|
292
|
+
raise Puppet::Error, "Invalid relationship: #{edge_to_s(resource_hash_to_ref(resource_hash), other_ref, param)}, because #{other_ref} doesn't seem to be in the catalog" unless other_resource
|
293
|
+
|
294
|
+
# As above, virtual exported resources will eventually be removed,
|
295
|
+
# so if a real resource refers to one, it's wrong. Non-virtual
|
296
|
+
# exported resources are exported resources that were also
|
297
|
+
# collected in this catalog, so they're okay. Virtual non-exported
|
298
|
+
# resources can't appear in the catalog in the first place, so it
|
299
|
+
# suffices to check for virtual.
|
300
|
+
if other_real_resource = catalog.resource(other_resource['type'], other_resource['title'])
|
301
|
+
if other_real_resource.virtual?
|
302
|
+
raise Puppet::Error, "Invalid relationship: #{edge_to_s(resource_hash_to_ref(resource_hash), other_ref, param)}, because #{other_ref} is exported but not collected"
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
# If the ref was an alias, it will have a different title, so use
|
307
|
+
# that
|
308
|
+
other_hash['title'] = other_resource['title']
|
309
|
+
|
310
|
+
if relation[:direction] == :forward
|
311
|
+
edge.merge!('source' => resource_hash, 'target' => other_hash)
|
312
|
+
else
|
313
|
+
edge.merge!('source' => other_hash, 'target' => resource_hash)
|
314
|
+
end
|
315
|
+
hash['edges'] << edge
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
profile "Make edges unique" do
|
323
|
+
hash['edges'].uniq!
|
324
|
+
end
|
325
|
+
|
326
|
+
hash
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def filter_keys(hash)
|
331
|
+
profile "Filter extraneous keys from the catalog" do
|
332
|
+
hash.delete_if do |k,v|
|
333
|
+
! ['name', 'version', 'edges', 'resources'].include?(k)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def resource_ref_to_hash(ref)
|
339
|
+
ref =~ /^([^\[\]]+)\[(.+)\]$/m
|
340
|
+
{'type' => $1, 'title' => $2}
|
341
|
+
end
|
342
|
+
|
343
|
+
def resource_hash_to_ref(hash)
|
344
|
+
"#{hash['type']}[#{hash['title']}]"
|
345
|
+
end
|
346
|
+
|
347
|
+
def edge_to_s(specifier_resource, referred_resource, param)
|
348
|
+
"#{specifier_resource} { #{param} => #{referred_resource} }"
|
349
|
+
end
|
350
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'puppet/node/facts'
|
3
|
+
require 'puppet/indirector/rest'
|
4
|
+
require 'puppet/util/puppetdb'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
class Puppet::Node::Facts::Puppetdb < Puppet::Indirector::REST
|
8
|
+
include Puppet::Util::Puppetdb
|
9
|
+
include Puppet::Util::Puppetdb::CommandNames
|
10
|
+
|
11
|
+
# Run initial checks
|
12
|
+
def initialize
|
13
|
+
Puppet::Util::Puppetdb::GlobalCheck.run
|
14
|
+
end
|
15
|
+
|
16
|
+
def save(request)
|
17
|
+
profile "facts#save" do
|
18
|
+
payload = profile "Encode facts command submission payload" do
|
19
|
+
facts = request.instance.dup
|
20
|
+
facts.values = facts.values.dup
|
21
|
+
facts.stringify
|
22
|
+
{
|
23
|
+
"name" => facts.name,
|
24
|
+
"values" => facts.values,
|
25
|
+
# PDB-453: we call to_s to avoid a 'stack level too deep' error
|
26
|
+
# when we attempt to use ActiveSupport 2.3.16 on RHEL 5 with
|
27
|
+
# legacy storeconfigs.
|
28
|
+
"environment" => request.environment.to_s,
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
submit_command(request.key, payload, CommandReplaceFacts, 2)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def find(request)
|
37
|
+
profile "facts#find" do
|
38
|
+
begin
|
39
|
+
url = "/v3/nodes/#{CGI.escape(request.key)}/facts"
|
40
|
+
response = profile "Query for nodes facts: #{url}" do
|
41
|
+
http_get(request, url, headers)
|
42
|
+
end
|
43
|
+
log_x_deprecation_header(response)
|
44
|
+
|
45
|
+
if response.is_a? Net::HTTPSuccess
|
46
|
+
profile "Parse fact query response (size: #{response.body.size})" do
|
47
|
+
result = JSON.parse(response.body)
|
48
|
+
# Note: the Inventory Service API appears to expect us to return nil here
|
49
|
+
# if the node isn't found. However, PuppetDB returns an empty array in
|
50
|
+
# this case; for now we will just look for that condition and assume that
|
51
|
+
# it means that the node wasn't found, so we will return nil. In the
|
52
|
+
# future we may want to improve the logic such that we can distinguish
|
53
|
+
# between the "node not found" and the "no facts for this node" cases.
|
54
|
+
if result.empty?
|
55
|
+
return nil
|
56
|
+
end
|
57
|
+
facts = result.inject({}) do |a,h|
|
58
|
+
a.merge(h['name'] => h['value'])
|
59
|
+
end
|
60
|
+
Puppet::Node::Facts.new(request.key, facts)
|
61
|
+
end
|
62
|
+
else
|
63
|
+
# Newline characters cause an HTTP error, so strip them
|
64
|
+
raise "[#{response.code} #{response.message}] #{response.body.gsub(/[\r\n]/, '')}"
|
65
|
+
end
|
66
|
+
rescue => e
|
67
|
+
raise Puppet::Error, "Failed to find facts from PuppetDB at #{self.class.server}:#{self.class.port}: #{e}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Search for nodes matching a set of fact constraints. The constraints are
|
73
|
+
# specified as a hash of the form:
|
74
|
+
#
|
75
|
+
# `{type.name.operator => value`
|
76
|
+
#
|
77
|
+
# The only accepted `type` is 'facts'.
|
78
|
+
#
|
79
|
+
# `name` must be the fact name to query against.
|
80
|
+
#
|
81
|
+
# `operator` may be one of {eq, ne, lt, gt, le, ge}, and will default to 'eq'
|
82
|
+
# if unspecified.
|
83
|
+
def search(request)
|
84
|
+
profile "facts#search" do
|
85
|
+
return [] unless request.options
|
86
|
+
operator_map = {
|
87
|
+
'eq' => '=',
|
88
|
+
'gt' => '>',
|
89
|
+
'lt' => '<',
|
90
|
+
'ge' => '>=',
|
91
|
+
'le' => '<=',
|
92
|
+
}
|
93
|
+
filters = request.options.sort.map do |key,value|
|
94
|
+
type, name, operator = key.to_s.split('.')
|
95
|
+
operator ||= 'eq'
|
96
|
+
raise Puppet::Error, "Fact search against keys of type '#{type}' is unsupported" unless type == 'facts'
|
97
|
+
if operator == 'ne'
|
98
|
+
['not', ['=', ['fact', name], value]]
|
99
|
+
else
|
100
|
+
[operator_map[operator], ['fact', name], value]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
query = ["and"] + filters
|
105
|
+
query_param = CGI.escape(query.to_json)
|
106
|
+
|
107
|
+
begin
|
108
|
+
url = "/v3/nodes?query=#{query_param}"
|
109
|
+
response = profile "Fact query request: #{URI.unescape(url)}" do
|
110
|
+
http_get(request, url, headers)
|
111
|
+
end
|
112
|
+
log_x_deprecation_header(response)
|
113
|
+
|
114
|
+
if response.is_a? Net::HTTPSuccess
|
115
|
+
profile "Parse fact query response (size: #{response.body.size})" do
|
116
|
+
JSON.parse(response.body).collect {|s| s["name"]}
|
117
|
+
end
|
118
|
+
else
|
119
|
+
# Newline characters cause an HTTP error, so strip them
|
120
|
+
raise "[#{response.code} #{response.message}] #{response.body.gsub(/[\r\n]/, '')}"
|
121
|
+
end
|
122
|
+
rescue => e
|
123
|
+
raise Puppet::Error, "Could not perform inventory search from PuppetDB at #{self.class.server}:#{self.class.port}: #{e}"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def headers
|
129
|
+
{
|
130
|
+
"Accept" => "application/json",
|
131
|
+
"Content-Type" => "application/x-www-form-urlencoded; charset=UTF-8",
|
132
|
+
}
|
133
|
+
end
|
134
|
+
end
|