ml-puppetdb-terminus 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +202 -0
- data/NOTICE.txt +17 -0
- data/README.md +22 -0
- data/puppet/lib/puppet/application/storeconfigs.rb +4 -0
- data/puppet/lib/puppet/face/node/deactivate.rb +37 -0
- data/puppet/lib/puppet/face/node/status.rb +80 -0
- data/puppet/lib/puppet/face/storeconfigs.rb +193 -0
- data/puppet/lib/puppet/indirector/catalog/puppetdb.rb +400 -0
- data/puppet/lib/puppet/indirector/facts/puppetdb.rb +152 -0
- data/puppet/lib/puppet/indirector/facts/puppetdb_apply.rb +25 -0
- data/puppet/lib/puppet/indirector/node/puppetdb.rb +19 -0
- data/puppet/lib/puppet/indirector/resource/puppetdb.rb +108 -0
- data/puppet/lib/puppet/reports/puppetdb.rb +188 -0
- data/puppet/lib/puppet/util/puppetdb.rb +108 -0
- data/puppet/lib/puppet/util/puppetdb/char_encoding.rb +316 -0
- data/puppet/lib/puppet/util/puppetdb/command.rb +116 -0
- data/puppet/lib/puppet/util/puppetdb/command_names.rb +8 -0
- data/puppet/lib/puppet/util/puppetdb/config.rb +148 -0
- data/puppet/lib/puppet/util/puppetdb/http.rb +121 -0
- data/puppet/spec/README.markdown +8 -0
- data/puppet/spec/spec.opts +6 -0
- data/puppet/spec/spec_helper.rb +38 -0
- data/puppet/spec/unit/face/node/deactivate_spec.rb +28 -0
- data/puppet/spec/unit/face/node/status_spec.rb +43 -0
- data/puppet/spec/unit/face/storeconfigs_spec.rb +199 -0
- data/puppet/spec/unit/indirector/catalog/puppetdb_spec.rb +703 -0
- data/puppet/spec/unit/indirector/facts/puppetdb_apply_spec.rb +27 -0
- data/puppet/spec/unit/indirector/facts/puppetdb_spec.rb +347 -0
- data/puppet/spec/unit/indirector/node/puppetdb_spec.rb +61 -0
- data/puppet/spec/unit/indirector/resource/puppetdb_spec.rb +199 -0
- data/puppet/spec/unit/reports/puppetdb_spec.rb +249 -0
- data/puppet/spec/unit/util/puppetdb/char_encoding_spec.rb +212 -0
- data/puppet/spec/unit/util/puppetdb/command_spec.rb +98 -0
- data/puppet/spec/unit/util/puppetdb/config_spec.rb +227 -0
- data/puppet/spec/unit/util/puppetdb/http_spec.rb +138 -0
- data/puppet/spec/unit/util/puppetdb_spec.rb +33 -0
- metadata +115 -0
@@ -0,0 +1,703 @@
|
|
1
|
+
#!/usr/bin/env rspec
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
require 'puppet/indirector/catalog/puppetdb'
|
6
|
+
require 'puppet/util/puppetdb'
|
7
|
+
require 'puppet/util/puppetdb/command_names'
|
8
|
+
require 'json'
|
9
|
+
|
10
|
+
describe Puppet::Resource::Catalog::Puppetdb do
|
11
|
+
before :each do
|
12
|
+
Puppet::Util::Puppetdb.stubs(:server).returns 'localhost'
|
13
|
+
Puppet::Util::Puppetdb.stubs(:port).returns 0
|
14
|
+
create_environmentdir("my_environment")
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#save" do
|
18
|
+
let(:response) { Net::HTTPOK.new('1.1', 200, 'OK') }
|
19
|
+
let(:http) { mock 'http' }
|
20
|
+
let(:catalog) do
|
21
|
+
cat = Puppet::Resource::Catalog.new('foo')
|
22
|
+
cat.add_resource(Puppet::Resource.new(:file, 'my_file'))
|
23
|
+
cat
|
24
|
+
end
|
25
|
+
let(:options) {{
|
26
|
+
:code_id => 'my_git_sha1',
|
27
|
+
:transaction_uuid => 'abcdefg',
|
28
|
+
:environment => 'my_environment',
|
29
|
+
:producer_timestamp => "a test",
|
30
|
+
}}
|
31
|
+
|
32
|
+
before :each do
|
33
|
+
response.stubs(:body).returns '{"uuid": "a UUID"}'
|
34
|
+
Puppet::Network::HttpPool.expects(:http_instance).returns http
|
35
|
+
end
|
36
|
+
|
37
|
+
def save
|
38
|
+
subject.save(Puppet::Resource::Catalog.indirection.request(:save, catalog.name, catalog, options))
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should POST the catalog command as a JSON string" do
|
42
|
+
command_payload = subject.munge_catalog(catalog, options)
|
43
|
+
payload = {
|
44
|
+
:command => Puppet::Util::Puppetdb::CommandNames::CommandReplaceCatalog,
|
45
|
+
:version => 7,
|
46
|
+
:payload => command_payload,
|
47
|
+
}.to_json
|
48
|
+
|
49
|
+
http.expects(:post).with do |uri, body, headers|
|
50
|
+
expect(body).to eq(payload)
|
51
|
+
end.returns response
|
52
|
+
|
53
|
+
save
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should log a deprecation warning if one is returned from PuppetDB" do
|
57
|
+
response['x-deprecation'] = 'A horrible deprecation warning!'
|
58
|
+
|
59
|
+
Puppet.expects(:deprecation_warning).with do |msg|
|
60
|
+
msg =~ /A horrible deprecation warning!/
|
61
|
+
end
|
62
|
+
|
63
|
+
http.stubs(:post).returns response
|
64
|
+
|
65
|
+
save
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "catalog transformation methods" do
|
70
|
+
let(:catalog) { Puppet::Parser::Compiler.compile(Puppet::Node.new('node')) }
|
71
|
+
let(:resource) { Puppet::Resource.new(:notify, 'anyone') }
|
72
|
+
|
73
|
+
# This is a little abuse of the laziness of let. Set Puppet[:code], then
|
74
|
+
# create the catalog based on that manifest simply by asking for it.
|
75
|
+
def catalog_data_hash
|
76
|
+
Puppet[:code] = resource.to_manifest
|
77
|
+
catalog.to_data_hash
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#add_transaction_uuid" do
|
81
|
+
it "should add the given transaction uuid" do
|
82
|
+
result = subject.add_transaction_uuid(catalog_data_hash, 'abc123')
|
83
|
+
result['transaction_uuid'].should == 'abc123'
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should add nil transaction uuid if none was given" do
|
87
|
+
result = subject.add_transaction_uuid(catalog_data_hash, nil)
|
88
|
+
result.has_key?('transaction_uuid').should be_true
|
89
|
+
result['transaction_uuid'].should be_nil
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "#add_parameters_if_missing" do
|
94
|
+
it "should create an empty parameters hash if none exists" do
|
95
|
+
result = subject.add_parameters_if_missing(catalog_data_hash)
|
96
|
+
|
97
|
+
result['resources'].each do |res|
|
98
|
+
res['parameters'].should be_a(Hash)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should leave an existing parameters hash alone" do
|
103
|
+
msg = "with up so floating many bells down"
|
104
|
+
resource[:message] = msg
|
105
|
+
|
106
|
+
result = subject.add_parameters_if_missing(catalog_data_hash)
|
107
|
+
resource = result['resources'].find do |res|
|
108
|
+
res['type'] == 'Notify' and res['title'] == 'anyone'
|
109
|
+
end
|
110
|
+
|
111
|
+
resource.should_not be_nil
|
112
|
+
resource['parameters'].should == {:message => msg}
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "#stringify_titles" do
|
117
|
+
if Puppet::Util::Puppetdb.puppet3compat?
|
118
|
+
it "should make all resource titles strings if they aren't" do
|
119
|
+
Puppet[:code] = <<-MANIFEST
|
120
|
+
$foo = true
|
121
|
+
notify { $foo: }
|
122
|
+
MANIFEST
|
123
|
+
|
124
|
+
hash = catalog.to_data_hash
|
125
|
+
result = subject.stringify_titles(hash)
|
126
|
+
|
127
|
+
result['resources'].should be_any { |res|
|
128
|
+
res['type'] == 'Notify' and res['title'] == 'true'
|
129
|
+
}
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe "#add_namevar_aliases" do
|
135
|
+
it "should add namevar to aliases if it's not already present" do
|
136
|
+
name = 'with a different name'
|
137
|
+
resource[:name] = name
|
138
|
+
|
139
|
+
hash = subject.add_parameters_if_missing(catalog_data_hash)
|
140
|
+
result = subject.add_namevar_aliases(hash, catalog)
|
141
|
+
|
142
|
+
resource = result['resources'].find do |res|
|
143
|
+
res['type'] == 'Notify' and res['title'] == 'anyone'
|
144
|
+
end
|
145
|
+
|
146
|
+
resource.should_not be_nil
|
147
|
+
resource['parameters'][:alias].should include(name)
|
148
|
+
end
|
149
|
+
|
150
|
+
context "with resource types that provide #title_patterns" do
|
151
|
+
context "if #title_patterns munges the title to set the namevar" do
|
152
|
+
it "should add namevar to aliases if it's not already present" do
|
153
|
+
# So, what we are testing here is the case where the resource type
|
154
|
+
# defines one or more title_patterns, which, when used to set
|
155
|
+
# the value of the namevar, may munge the value via regex
|
156
|
+
# awesomeness. 'File' is an example of such a resource, as
|
157
|
+
# it will strip trailing slashes from the title to set the
|
158
|
+
# :path parameter, if :path is not specified.
|
159
|
+
#
|
160
|
+
# In a case like this it is important that the munged value of
|
161
|
+
# the namevar be set as an alias, so that catalog dependencies
|
162
|
+
# can be resolved properly.
|
163
|
+
|
164
|
+
# To test this, first we create a File resource whose title contains
|
165
|
+
# a trailing slash.
|
166
|
+
file_resource = Puppet::Resource.new(:file, '/tmp/foo/')
|
167
|
+
|
168
|
+
# I find it fairly well revolting that we can hack stuff into
|
169
|
+
# the compiler via this global :code variable. It doesn't seem
|
170
|
+
# like it should be hard to provide a more explicit and sensible
|
171
|
+
# way to accomplish this...
|
172
|
+
Puppet[:code] = file_resource.to_manifest
|
173
|
+
|
174
|
+
hash = subject.add_parameters_if_missing(catalog.to_data_hash)
|
175
|
+
result = subject.add_namevar_aliases(hash, catalog)
|
176
|
+
|
177
|
+
resource = result['resources'].find do |res|
|
178
|
+
res['type'] == 'File' and res['title'] == '/tmp/foo/'
|
179
|
+
end
|
180
|
+
|
181
|
+
# Now we need to check to make sure that there is an alias without
|
182
|
+
# the trailing slash. This test relies on the secret knowledge
|
183
|
+
# that the File resource has a title_pattern that munges the
|
184
|
+
# namevar (in this case, removes trailing slashes), but hopefully
|
185
|
+
# this test should cover other resource types that fall into
|
186
|
+
# this category as well.
|
187
|
+
resource.should_not be_nil
|
188
|
+
resource['parameters'][:alias].should_not be_nil
|
189
|
+
resource['parameters'][:alias].should include('/tmp/foo')
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should not create an alias parameter if the list would be empty" do
|
195
|
+
hash = subject.add_parameters_if_missing(catalog_data_hash)
|
196
|
+
result = subject.add_namevar_aliases(hash, catalog)
|
197
|
+
|
198
|
+
resource = result['resources'].find do |res|
|
199
|
+
res['type'] == 'Notify' and res['title'] == 'anyone'
|
200
|
+
end
|
201
|
+
|
202
|
+
resource.should_not be_nil
|
203
|
+
resource['parameters'][:alias].should be_nil
|
204
|
+
end
|
205
|
+
|
206
|
+
describe "for resources with composite namevars" do
|
207
|
+
let(:resource) do
|
208
|
+
r = Puppet::Resource.new(:notify, 'yo matey')
|
209
|
+
r.stubs(:key_attributes).returns [:name, :message]
|
210
|
+
r
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should not create aliases" do
|
214
|
+
hash = subject.add_parameters_if_missing(catalog_data_hash)
|
215
|
+
result = subject.add_namevar_aliases(hash, catalog)
|
216
|
+
|
217
|
+
resource = result['resources'].find do |res|
|
218
|
+
res['type'] == 'Notify' and res['title'] == 'yo matey'
|
219
|
+
end
|
220
|
+
|
221
|
+
resource.should_not be_nil
|
222
|
+
resource['parameters'][:alias].should be_nil
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
describe "for non-isomorphic resources" do
|
227
|
+
let(:resource) do
|
228
|
+
Puppet::Resource.new(:exec, 'an_exec', :parameters => {:command => '/bin/true', :alias => 'something awesome'})
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should not add a namevar alias" do
|
232
|
+
hash = subject.add_parameters_if_missing(catalog_data_hash)
|
233
|
+
result = subject.add_namevar_aliases(hash, catalog)
|
234
|
+
|
235
|
+
resource = result['resources'].find do |res|
|
236
|
+
res['type'] == 'Exec' and res['title'] == 'an_exec'
|
237
|
+
end
|
238
|
+
|
239
|
+
resource.should_not be_nil
|
240
|
+
resource['parameters'][:alias].should == ['something awesome']
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
describe "#sort_unordered_metaparams" do
|
246
|
+
let(:resource) do
|
247
|
+
Puppet::Resource.new(:exec, 'an_exec', :parameters => {:command => '/bin/true',
|
248
|
+
:path => ['/foo/goo', '/foo/bar'],
|
249
|
+
:audit => 'path',
|
250
|
+
:tag => ['c', 'b', 'a']})
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should leave ordered/singleton metaparams (and vanilla params) alone" do
|
254
|
+
hash = subject.add_parameters_if_missing(catalog_data_hash)
|
255
|
+
result = subject.sort_unordered_metaparams(hash)
|
256
|
+
|
257
|
+
resource = result['resources'].find do |res|
|
258
|
+
res['type'] == 'Exec' and res['title'] == 'an_exec'
|
259
|
+
end
|
260
|
+
|
261
|
+
resource.should_not be_nil
|
262
|
+
resource['parameters'][:command].should == '/bin/true'
|
263
|
+
resource['parameters'][:path].should == ['/foo/goo', '/foo/bar']
|
264
|
+
resource['parameters'][:audit].should == 'path'
|
265
|
+
end
|
266
|
+
|
267
|
+
it "should sort unordered metaparams with array values" do
|
268
|
+
hash = subject.add_parameters_if_missing(catalog_data_hash)
|
269
|
+
result = subject.sort_unordered_metaparams(hash)
|
270
|
+
|
271
|
+
resource = result['resources'].find do |res|
|
272
|
+
res['type'] == 'Exec' and res['title'] == 'an_exec'
|
273
|
+
end
|
274
|
+
|
275
|
+
resource.should_not be_nil
|
276
|
+
resource['parameters'][:audit].should == 'path'
|
277
|
+
resource['parameters'][:tag].should == ['a', 'b', 'c']
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
describe "#munge_edges" do
|
282
|
+
it "should replace existing source/target refs with type/title hashes" do
|
283
|
+
result = subject.munge_edges(catalog_data_hash)
|
284
|
+
|
285
|
+
# Ensure we don't get a vacuous success from an empty list
|
286
|
+
result['edges'].should_not be_empty
|
287
|
+
|
288
|
+
result['edges'].each do |edge|
|
289
|
+
edge['source'].should be_a(Hash)
|
290
|
+
edge['source'].keys.should =~ ['type', 'title']
|
291
|
+
edge['target'].should be_a(Hash)
|
292
|
+
edge['target'].keys.should =~ ['type', 'title']
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
it "should leave type/title hashes alone" do
|
297
|
+
hash = catalog_data_hash
|
298
|
+
|
299
|
+
edge = {'source' => {'type' => 'Notify', 'title' => 'bar'},
|
300
|
+
'target' => {'type' => 'Notify', 'title' => 'baz'},
|
301
|
+
'relationship' => 'notifies'}
|
302
|
+
|
303
|
+
hash['edges'] << edge.dup
|
304
|
+
|
305
|
+
result = subject.munge_edges(hash)
|
306
|
+
result['edges'].should include(edge)
|
307
|
+
end
|
308
|
+
|
309
|
+
it "should set the edge relationship to contains if it doesn't have one" do
|
310
|
+
result = subject.munge_edges(catalog_data_hash)
|
311
|
+
result['edges'].each do |edge|
|
312
|
+
edge['relationship'].should == 'contains'
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
describe "#synthesize_edges" do
|
318
|
+
it "should add edges based on relationship metaparameters" do
|
319
|
+
other_resource = Puppet::Resource.new(:notify, 'noone', :parameters => {:require => "Notify[anyone]"})
|
320
|
+
Puppet[:code] = [resource, other_resource].map(&:to_manifest).join
|
321
|
+
|
322
|
+
hash = catalog.to_data_hash
|
323
|
+
subject.add_parameters_if_missing(hash)
|
324
|
+
result = subject.synthesize_edges(hash, catalog)
|
325
|
+
|
326
|
+
edge = {'source' => {'type' => 'Notify', 'title' => 'anyone'},
|
327
|
+
'target' => {'type' => 'Notify', 'title' => 'noone'},
|
328
|
+
'relationship' => 'required-by'}
|
329
|
+
|
330
|
+
result['edges'].should include(edge)
|
331
|
+
end
|
332
|
+
|
333
|
+
it "should add edges from relationship arrows" do
|
334
|
+
other_resource = Puppet::Resource.new(:notify, 'noone')
|
335
|
+
Puppet[:code] = [resource, other_resource].map(&:to_manifest).join
|
336
|
+
Puppet[:code] << "Notify[anyone] -> Notify[noone]"
|
337
|
+
|
338
|
+
hash = catalog.to_data_hash
|
339
|
+
subject.add_parameters_if_missing(hash)
|
340
|
+
result = subject.synthesize_edges(hash, catalog)
|
341
|
+
|
342
|
+
edge = {'source' => {'type' => 'Notify', 'title' => 'anyone'},
|
343
|
+
'target' => {'type' => 'Notify', 'title' => 'noone'},
|
344
|
+
'relationship' => 'before'}
|
345
|
+
|
346
|
+
result['edges'].should include(edge)
|
347
|
+
end
|
348
|
+
|
349
|
+
it "should allow resources with newlines" do
|
350
|
+
Puppet[:code] = <<-MANIFEST
|
351
|
+
exec{"foo\nbar": }
|
352
|
+
exec{'/bin/true': subscribe => Exec["foo\nbar"]}
|
353
|
+
MANIFEST
|
354
|
+
|
355
|
+
expect { subject.munge_catalog(catalog) }.not_to raise_error
|
356
|
+
end
|
357
|
+
|
358
|
+
describe "exported resources" do
|
359
|
+
before :each do
|
360
|
+
Puppet[:storeconfigs] = true
|
361
|
+
Puppet[:storeconfigs_backend] = 'puppetdb'
|
362
|
+
Puppet::Resource.indirection.stubs(:search).returns []
|
363
|
+
end
|
364
|
+
|
365
|
+
let(:edge) do
|
366
|
+
{
|
367
|
+
'source' => {'type' => 'Notify', 'title' => 'source'},
|
368
|
+
'target' => {'type' => 'Notify', 'title' => 'target'},
|
369
|
+
'relationship' => 'before'
|
370
|
+
}
|
371
|
+
end
|
372
|
+
|
373
|
+
it "should add edges which refer to collected exported resources" do
|
374
|
+
Puppet[:code] = <<-MANIFEST
|
375
|
+
notify { source:
|
376
|
+
before => Notify[target],
|
377
|
+
}
|
378
|
+
|
379
|
+
@@notify { target: }
|
380
|
+
|
381
|
+
Notify <<| |>>
|
382
|
+
MANIFEST
|
383
|
+
|
384
|
+
result = subject.munge_catalog(catalog)
|
385
|
+
|
386
|
+
result['edges'].should include(edge)
|
387
|
+
end
|
388
|
+
|
389
|
+
it "should add edges defined on collected exported resources" do
|
390
|
+
Puppet[:code] = <<-MANIFEST
|
391
|
+
@@notify { source:
|
392
|
+
before => Notify[target],
|
393
|
+
}
|
394
|
+
|
395
|
+
notify { target: }
|
396
|
+
|
397
|
+
Notify <<| |>>
|
398
|
+
MANIFEST
|
399
|
+
|
400
|
+
result = subject.munge_catalog(catalog)
|
401
|
+
|
402
|
+
result['edges'].should include(edge)
|
403
|
+
end
|
404
|
+
|
405
|
+
it "should fail if an edge refers to an uncollected exported resource" do
|
406
|
+
Puppet[:code] = <<-MANIFEST
|
407
|
+
notify { source:
|
408
|
+
before => Notify[target],
|
409
|
+
}
|
410
|
+
|
411
|
+
@@notify { target: }
|
412
|
+
MANIFEST
|
413
|
+
|
414
|
+
expect do
|
415
|
+
subject.munge_catalog(catalog)
|
416
|
+
end.to raise_error(Puppet::Error, "Invalid relationship: Notify[source] { before => Notify[target] }, because Notify[target] is exported but not collected")
|
417
|
+
end
|
418
|
+
|
419
|
+
it "should not add edges defined on an uncollected exported resource" do
|
420
|
+
Puppet[:code] = <<-MANIFEST
|
421
|
+
@@notify { source:
|
422
|
+
before => Notify[target],
|
423
|
+
}
|
424
|
+
|
425
|
+
notify { target: }
|
426
|
+
MANIFEST
|
427
|
+
|
428
|
+
result = subject.munge_catalog(catalog)
|
429
|
+
|
430
|
+
result['edges'].should_not include(edge)
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
describe "virtual resources" do
|
435
|
+
let(:edge) do
|
436
|
+
{
|
437
|
+
'source' => {'type' => 'Notify', 'title' => 'source'},
|
438
|
+
'target' => {'type' => 'Notify', 'title' => 'target'},
|
439
|
+
'relationship' => 'before'
|
440
|
+
}
|
441
|
+
end
|
442
|
+
|
443
|
+
it "should add edges which refer to collected virtual resources" do
|
444
|
+
Puppet[:code] = <<-MANIFEST
|
445
|
+
notify { source:
|
446
|
+
before => Notify[target],
|
447
|
+
}
|
448
|
+
|
449
|
+
@notify { target: }
|
450
|
+
|
451
|
+
Notify <| |>
|
452
|
+
MANIFEST
|
453
|
+
|
454
|
+
result = subject.munge_catalog(catalog)
|
455
|
+
|
456
|
+
result['edges'].should include(edge)
|
457
|
+
end
|
458
|
+
|
459
|
+
if Puppet::Util::Puppetdb.puppet3compat?
|
460
|
+
it "should add edges which refer to collected virtual resources with hyphens in the classname" do
|
461
|
+
Puppet[:code] = <<-MANIFEST
|
462
|
+
define foo-bar- (){}
|
463
|
+
@foo-bar- { 'baz': }
|
464
|
+
|
465
|
+
notify { source:
|
466
|
+
before => Foo-bar-[baz],
|
467
|
+
}
|
468
|
+
|
469
|
+
Foo-bar- <| |>
|
470
|
+
MANIFEST
|
471
|
+
|
472
|
+
result = subject.munge_catalog(catalog)
|
473
|
+
other_edge = {
|
474
|
+
'source' => {'type' => 'Notify', 'title' => 'source'},
|
475
|
+
'target' => {'type' => 'Foo-bar-', 'title' => 'baz'},
|
476
|
+
'relationship' => 'before'
|
477
|
+
}
|
478
|
+
|
479
|
+
result['edges'].should include(other_edge)
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
it "should add edges defined on collected virtual resources" do
|
484
|
+
Puppet[:code] = <<-MANIFEST
|
485
|
+
@notify { source:
|
486
|
+
before => Notify[target],
|
487
|
+
}
|
488
|
+
|
489
|
+
notify { target: }
|
490
|
+
|
491
|
+
Notify <| |>
|
492
|
+
MANIFEST
|
493
|
+
|
494
|
+
result = subject.munge_catalog(catalog)
|
495
|
+
|
496
|
+
result['edges'].should include(edge)
|
497
|
+
end
|
498
|
+
|
499
|
+
it "should add edges which refer to realized virtual resources" do
|
500
|
+
Puppet[:code] = <<-MANIFEST
|
501
|
+
notify { source:
|
502
|
+
before => Notify[target],
|
503
|
+
}
|
504
|
+
|
505
|
+
@notify { target: }
|
506
|
+
|
507
|
+
realize Notify[target]
|
508
|
+
MANIFEST
|
509
|
+
|
510
|
+
result = subject.munge_catalog(catalog)
|
511
|
+
|
512
|
+
result['edges'].should include(edge)
|
513
|
+
end
|
514
|
+
|
515
|
+
it "should add edges defined on realized virtual resources" do
|
516
|
+
Puppet[:code] = <<-MANIFEST
|
517
|
+
@notify { source:
|
518
|
+
before => Notify[target],
|
519
|
+
}
|
520
|
+
|
521
|
+
notify { target: }
|
522
|
+
|
523
|
+
realize Notify[source]
|
524
|
+
MANIFEST
|
525
|
+
|
526
|
+
result = subject.munge_catalog(catalog)
|
527
|
+
|
528
|
+
result['edges'].should include(edge)
|
529
|
+
end
|
530
|
+
|
531
|
+
it "should fail if an edge refers to an uncollected virtual resource" do
|
532
|
+
Puppet[:code] = <<-MANIFEST
|
533
|
+
notify { source:
|
534
|
+
before => Notify[target],
|
535
|
+
}
|
536
|
+
|
537
|
+
@notify { target: }
|
538
|
+
MANIFEST
|
539
|
+
|
540
|
+
expect do
|
541
|
+
subject.munge_catalog(catalog)
|
542
|
+
end.to raise_error(Puppet::Error, "Invalid relationship: Notify[source] { before => Notify[target] }, because Notify[target] doesn't seem to be in the catalog")
|
543
|
+
end
|
544
|
+
|
545
|
+
it "should not add edges defined on an uncollected virtual resource" do
|
546
|
+
Puppet[:code] = <<-MANIFEST
|
547
|
+
@notify { source:
|
548
|
+
before => Notify[target],
|
549
|
+
}
|
550
|
+
|
551
|
+
notify { target: }
|
552
|
+
MANIFEST
|
553
|
+
|
554
|
+
result = subject.munge_catalog(catalog)
|
555
|
+
|
556
|
+
result['edges'].should_not include(edge)
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
it "should add edges even if the other end is an alias" do
|
561
|
+
other_resource = Puppet::Resource.new(:notify, 'noone', :parameters => {:alias => 'another_thing'})
|
562
|
+
resource[:require] = 'Notify[another_thing]'
|
563
|
+
Puppet[:code] = [resource, other_resource].map(&:to_manifest).join
|
564
|
+
|
565
|
+
hash = catalog.to_data_hash
|
566
|
+
subject.add_parameters_if_missing(hash)
|
567
|
+
subject.add_namevar_aliases(hash, catalog)
|
568
|
+
result = subject.synthesize_edges(hash, catalog)
|
569
|
+
|
570
|
+
edge = {'source' => {'type' => 'Notify', 'title' => 'noone'},
|
571
|
+
'target' => {'type' => 'Notify', 'title' => 'anyone'},
|
572
|
+
'relationship' => 'required-by'}
|
573
|
+
|
574
|
+
result['edges'].should include(edge)
|
575
|
+
end
|
576
|
+
|
577
|
+
it "should produce a reasonable error message for a missing 'before' relationship" do
|
578
|
+
resource[:before] = 'Notify[non-existent]'
|
579
|
+
|
580
|
+
hash = subject.add_parameters_if_missing(catalog_data_hash)
|
581
|
+
expect {
|
582
|
+
subject.synthesize_edges(hash, catalog)
|
583
|
+
}.to raise_error(Puppet::Error, "Invalid relationship: Notify[anyone] { before => Notify[non-existent] }, because Notify[non-existent] doesn't seem to be in the catalog")
|
584
|
+
end
|
585
|
+
|
586
|
+
it "should produce a reasonable error message for a missing 'required-by' relationship" do
|
587
|
+
resource[:require] = 'Notify[non-existent]'
|
588
|
+
hash = subject.add_parameters_if_missing(catalog_data_hash)
|
589
|
+
expect {
|
590
|
+
subject.synthesize_edges(hash, catalog)
|
591
|
+
}.to raise_error(Puppet::Error, "Invalid relationship: Notify[anyone] { require => Notify[non-existent] }, because Notify[non-existent] doesn't seem to be in the catalog")
|
592
|
+
end
|
593
|
+
|
594
|
+
it "should produce a reasonable error message for a missing 'notifies' relationship" do
|
595
|
+
resource[:notify] = 'Notify[non-existent]'
|
596
|
+
|
597
|
+
hash = subject.add_parameters_if_missing(catalog_data_hash)
|
598
|
+
expect {
|
599
|
+
subject.synthesize_edges(hash, catalog)
|
600
|
+
}.to raise_error(Puppet::Error, "Invalid relationship: Notify[anyone] { notify => Notify[non-existent] }, because Notify[non-existent] doesn't seem to be in the catalog")
|
601
|
+
end
|
602
|
+
|
603
|
+
it "should produce a reasonable error message for a missing 'subscription-of' relationship" do
|
604
|
+
resource[:subscribe] = 'Notify[non-existent]'
|
605
|
+
|
606
|
+
hash = subject.add_parameters_if_missing(catalog_data_hash)
|
607
|
+
expect {
|
608
|
+
subject.synthesize_edges(hash, catalog)
|
609
|
+
}.to raise_error(Puppet::Error, "Invalid relationship: Notify[anyone] { subscribe => Notify[non-existent] }, because Notify[non-existent] doesn't seem to be in the catalog")
|
610
|
+
end
|
611
|
+
|
612
|
+
it "should produce a reasonable error message for an invalid resourceref" do
|
613
|
+
resource[:subscribe] = 'Foobar::baz[name]'
|
614
|
+
|
615
|
+
hash = subject.add_parameters_if_missing(catalog_data_hash)
|
616
|
+
expect {
|
617
|
+
subject.synthesize_edges(hash, catalog)
|
618
|
+
}.to raise_error(Puppet::Error, "Invalid relationship: Notify[anyone] { subscribe => Foobar::baz[name] }, because Foobar::baz[name] doesn't seem to be in the correct format. Resource references should be formatted as: Classname['title'] or Modulename::Classname['title'] (take careful note of the capitalization).")
|
619
|
+
end
|
620
|
+
end #synthesize_edges
|
621
|
+
|
622
|
+
describe "#munge_catalog" do
|
623
|
+
it "should make an edge if the other end is referred to by its namevar" do
|
624
|
+
other_resource = Puppet::Resource.new(:notify, 'noone', :parameters => {:name => 'completely_different'})
|
625
|
+
resource[:require] = 'Notify[completely_different]'
|
626
|
+
Puppet[:code] = [resource, other_resource].map(&:to_manifest).join
|
627
|
+
|
628
|
+
result = subject.munge_catalog(catalog)
|
629
|
+
|
630
|
+
edge = {'source' => {'type' => 'Notify', 'title' => 'noone'},
|
631
|
+
'target' => {'type' => 'Notify', 'title' => 'anyone'},
|
632
|
+
'relationship' => 'required-by'}
|
633
|
+
|
634
|
+
result['edges'].should include(edge)
|
635
|
+
end
|
636
|
+
|
637
|
+
context "when dealing with file resources and trailing slashes in their titles" do
|
638
|
+
|
639
|
+
def test_file_require(resource_title, require_title)
|
640
|
+
other_resource = Puppet::Resource.new(:file, resource_title)
|
641
|
+
resource[:require] = "File[#{require_title}]"
|
642
|
+
Puppet[:code] = [resource, other_resource].map(&:to_manifest).join
|
643
|
+
result = subject.munge_catalog(catalog)
|
644
|
+
|
645
|
+
edge = {'source' => {'type' => 'File', 'title' => resource_title},
|
646
|
+
'target' => {'type' => 'Notify', 'title' => 'anyone'},
|
647
|
+
'relationship' => 'required-by'}
|
648
|
+
|
649
|
+
result['edges'].should include(edge)
|
650
|
+
end
|
651
|
+
|
652
|
+
it "should make an edge if the other end is a file resource with a missing trailing slash" do
|
653
|
+
test_file_require('/tmp/foo/', '/tmp/foo')
|
654
|
+
end
|
655
|
+
|
656
|
+
it "should make an edge if the other end is a file resource with an extra trailing slash" do
|
657
|
+
test_file_require('/tmp/foo', '/tmp/foo/')
|
658
|
+
end
|
659
|
+
|
660
|
+
it "should make an edge if the other end is a file resource with two missing trailing slashes" do
|
661
|
+
test_file_require('/tmp/foo//', '/tmp/foo')
|
662
|
+
end
|
663
|
+
|
664
|
+
it "should make an edge if the other end is a file resource with two extra trailing slashes" do
|
665
|
+
test_file_require('/tmp/foo', '/tmp/foo//')
|
666
|
+
end
|
667
|
+
end
|
668
|
+
|
669
|
+
it "should make an edge if the other end is an exec referred to by an alias" do
|
670
|
+
other_resource = Puppet::Resource.new(:exec, 'noone', :parameters => {:alias => 'completely_different', :path => '/anything'})
|
671
|
+
resource[:require] = 'Exec[completely_different]'
|
672
|
+
Puppet[:code] = [resource, other_resource].map(&:to_manifest).join
|
673
|
+
|
674
|
+
result = subject.munge_catalog(catalog)
|
675
|
+
|
676
|
+
edge = {'source' => {'type' => 'Exec', 'title' => 'noone'},
|
677
|
+
'target' => {'type' => 'Notify', 'title' => 'anyone'},
|
678
|
+
'relationship' => 'required-by'}
|
679
|
+
|
680
|
+
result['edges'].should include(edge)
|
681
|
+
end
|
682
|
+
|
683
|
+
it "should not include virtual resources" do
|
684
|
+
Puppet[:code] = <<-MANIFEST
|
685
|
+
@notify { something: }
|
686
|
+
MANIFEST
|
687
|
+
|
688
|
+
result = subject.munge_catalog(catalog)
|
689
|
+
|
690
|
+
result['resources'].each do |res|
|
691
|
+
[res['type'], res['title']].should_not == ['Notify', 'something']
|
692
|
+
end
|
693
|
+
end
|
694
|
+
|
695
|
+
it "should have the correct set of keys" do
|
696
|
+
result = subject.munge_catalog(catalog)
|
697
|
+
|
698
|
+
result.keys.should =~ ['certname', 'version', 'edges', 'resources',
|
699
|
+
'transaction_uuid', 'environment', 'producer_timestamp', "code_id"]
|
700
|
+
end
|
701
|
+
end
|
702
|
+
end
|
703
|
+
end
|