puppet 3.5.0.rc3 → 3.5.1.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (54) hide show
  1. data/lib/puppet.rb +11 -2
  2. data/lib/puppet/defaults.rb +3 -2
  3. data/lib/puppet/environments.rb +16 -0
  4. data/lib/puppet/network/http/api/v1.rb +6 -2
  5. data/lib/puppet/network/http/issues.rb +1 -0
  6. data/lib/puppet/node/environment.rb +9 -5
  7. data/lib/puppet/pops/parser/interpolation_support.rb +8 -4
  8. data/lib/puppet/provider/yumrepo/inifile.rb +60 -20
  9. data/lib/puppet/test/test_helper.rb +1 -8
  10. data/lib/puppet/type/yumrepo.rb +43 -9
  11. data/lib/puppet/util/inifile.rb +209 -86
  12. data/lib/puppet/version.rb +1 -1
  13. data/spec/integration/application/apply_spec.rb +3 -1
  14. data/spec/integration/directory_environments_spec.rb +2 -1
  15. data/spec/integration/indirector/file_content/file_server_spec.rb +1 -1
  16. data/spec/integration/node/environment_spec.rb +2 -2
  17. data/spec/integration/resource/type_collection_spec.rb +1 -1
  18. data/spec/unit/application/apply_spec.rb +1 -1
  19. data/spec/unit/environments_spec.rb +35 -36
  20. data/spec/unit/face/module/install_spec.rb +1 -1
  21. data/spec/unit/face/module/list_spec.rb +3 -3
  22. data/spec/unit/face/module/uninstall_spec.rb +1 -1
  23. data/spec/unit/face/parser_spec.rb +1 -1
  24. data/spec/unit/indirector/node/active_record_spec.rb +1 -1
  25. data/spec/unit/indirector/node/ldap_spec.rb +4 -4
  26. data/spec/unit/indirector/node/plain_spec.rb +1 -1
  27. data/spec/unit/indirector/request_spec.rb +3 -3
  28. data/spec/unit/module_spec.rb +6 -6
  29. data/spec/unit/module_tool/applications/installer_spec.rb +1 -1
  30. data/spec/unit/module_tool/applications/uninstaller_spec.rb +1 -1
  31. data/spec/unit/module_tool_spec.rb +1 -1
  32. data/spec/unit/network/http/api/v1_spec.rb +11 -1
  33. data/spec/unit/network/http/api/v2/environments_spec.rb +1 -1
  34. data/spec/unit/node/environment_spec.rb +1 -1
  35. data/spec/unit/node_spec.rb +1 -1
  36. data/spec/unit/parser/ast/collection_spec.rb +1 -1
  37. data/spec/unit/parser/compiler_spec.rb +1 -1
  38. data/spec/unit/parser/files_spec.rb +2 -2
  39. data/spec/unit/parser/functions_spec.rb +2 -2
  40. data/spec/unit/parser/parser_spec.rb +2 -2
  41. data/spec/unit/parser/resource_spec.rb +1 -1
  42. data/spec/unit/parser/scope_spec.rb +3 -3
  43. data/spec/unit/pops/parser/lexer2_spec.rb +11 -0
  44. data/spec/unit/pops/parser/parse_heredoc_spec.rb +15 -1
  45. data/spec/unit/provider/yumrepo/inifile_spec.rb +71 -23
  46. data/spec/unit/rails/host_spec.rb +1 -1
  47. data/spec/unit/resource/type_collection_spec.rb +1 -1
  48. data/spec/unit/resource/type_spec.rb +1 -1
  49. data/spec/unit/resource_spec.rb +1 -1
  50. data/spec/unit/type/yumrepo_spec.rb +214 -49
  51. data/spec/unit/util/autoload_spec.rb +1 -1
  52. data/spec/unit/util/inifile_spec.rb +492 -0
  53. data/spec/unit/util/rdoc/parser_spec.rb +2 -2
  54. metadata +3009 -3030
@@ -24,7 +24,7 @@ describe Puppet::Util::Autoload do
24
24
  end
25
25
 
26
26
  it "should collect all of the lib directories that exist in the current environment's module path" do
27
- environment = Puppet::Node::Environment.create(:foo, [@dira, @dirb, @dirc], '')
27
+ environment = Puppet::Node::Environment.create(:foo, [@dira, @dirb, @dirc])
28
28
  Dir.expects(:entries).with(@dira).returns %w{. .. one two}
29
29
  Dir.expects(:entries).with(@dirb).returns %w{. .. one two}
30
30
 
@@ -0,0 +1,492 @@
1
+ require 'spec_helper'
2
+ require 'puppet/util/inifile'
3
+
4
+ describe Puppet::Util::IniConfig::Section do
5
+
6
+ subject { described_class.new('testsection', '/some/imaginary/file') }
7
+
8
+ describe "determining if the section is dirty" do
9
+ it "is not dirty on creation" do
10
+ expect(subject).to_not be_dirty
11
+ end
12
+
13
+ it "is dirty if a key is changed" do
14
+ subject['hello'] = 'world'
15
+ expect(subject).to be_dirty
16
+ end
17
+
18
+ it "is dirty if the section has been explicitly marked as dirty" do
19
+ subject.mark_dirty
20
+ expect(subject).to be_dirty
21
+ end
22
+
23
+ it "is dirty if the section is marked for deletion" do
24
+ subject.destroy = true
25
+ expect(subject).to be_dirty
26
+ end
27
+
28
+ it "is clean if the section has been explicitly marked as clean" do
29
+ subject['hello'] = 'world'
30
+ subject.mark_clean
31
+ expect(subject).to_not be_dirty
32
+ end
33
+ end
34
+
35
+ describe "reading an entry" do
36
+ it "returns nil if the key is not present" do
37
+ expect(subject['hello']).to be_nil
38
+ end
39
+
40
+ it "returns the value if the key is specified" do
41
+ subject.entries << ['hello', 'world']
42
+ expect(subject['hello']).to eq 'world'
43
+ end
44
+
45
+ it "ignores comments when looking for a match" do
46
+ subject.entries << '#this = comment'
47
+ expect(subject['#this']).to be_nil
48
+ end
49
+ end
50
+
51
+ describe "formatting the section" do
52
+ it "prefixes the output with the section header" do
53
+ expect(subject.format).to eq "[testsection]\n"
54
+ end
55
+
56
+ it "restores comments and blank lines" do
57
+ subject.entries << "#comment\n"
58
+ subject.entries << " "
59
+ expect(subject.format).to eq(
60
+ "[testsection]\n" +
61
+ "#comment\n" +
62
+ " "
63
+ )
64
+ end
65
+
66
+ it "adds all keys that have values" do
67
+ subject.entries << ['somekey', 'somevalue']
68
+ expect(subject.format).to eq("[testsection]\nsomekey=somevalue\n")
69
+ end
70
+
71
+ it "excludes keys that have a value of nil" do
72
+ subject.entries << ['empty', nil]
73
+ expect(subject.format).to eq("[testsection]\n")
74
+ end
75
+
76
+ it "preserves the order of the section" do
77
+ subject.entries << ['firstkey', 'firstval']
78
+ subject.entries << "# I am a comment, hear me roar\n"
79
+ subject.entries << ['secondkey', 'secondval']
80
+
81
+ expect(subject.format).to eq(
82
+ "[testsection]\n" +
83
+ "firstkey=firstval\n" +
84
+ "# I am a comment, hear me roar\n" +
85
+ "secondkey=secondval\n"
86
+ )
87
+ end
88
+
89
+ it "is empty if the section is marked for deletion" do
90
+ subject.entries << ['firstkey', 'firstval']
91
+ subject.destroy = true
92
+ expect(subject.format).to eq('')
93
+ end
94
+ end
95
+ end
96
+
97
+ describe Puppet::Util::IniConfig::PhysicalFile do
98
+ subject { described_class.new('/some/nonexistent/file') }
99
+
100
+ let(:first_sect) do
101
+ sect = Puppet::Util::IniConfig::Section.new('firstsection', '/some/imaginary/file')
102
+ sect.entries << "# comment\n" << ['onefish', 'redfish'] << "\n"
103
+ sect
104
+ end
105
+
106
+ let(:second_sect) do
107
+ sect = Puppet::Util::IniConfig::Section.new('secondsection', '/some/imaginary/file')
108
+ sect.entries << ['twofish', 'bluefish']
109
+ sect
110
+ end
111
+
112
+ describe "when reading a file" do
113
+ it "raises an error if the file does not exist" do
114
+ subject.filetype.stubs(:read)
115
+ expect {
116
+ subject.read
117
+ }.to raise_error(%r[Cannot read nonexistent file .*/some/nonexistent/file])
118
+ end
119
+
120
+ it "passes the contents of the file to #parse" do
121
+ subject.filetype.stubs(:read).returns "[section]"
122
+ subject.expects(:parse).with("[section]")
123
+
124
+ subject.read
125
+ end
126
+
127
+ end
128
+
129
+ describe "when parsing a file" do
130
+ describe "parsing sections" do
131
+ it "creates new sections the first time that the section is found" do
132
+ text = "[mysect]\n"
133
+
134
+ subject.parse(text)
135
+
136
+ expect(subject.contents).to have(1).items
137
+ sect = subject.contents[0]
138
+ expect(sect.name).to eq "mysect"
139
+ end
140
+
141
+ it "raises an error if a section is redefined in the file" do
142
+ text = "[mysect]\n[mysect]\n"
143
+
144
+ expect {
145
+ subject.parse(text)
146
+ }.to raise_error(Puppet::Util::IniConfig::IniParseError,
147
+ /Section "mysect" is already defined, cannot redefine/)
148
+ end
149
+
150
+ it "raises an error if a section is redefined in the file collection" do
151
+ subject.file_collection = stub('file collection', :get_section => true)
152
+ text = "[mysect]\n[mysect]\n"
153
+
154
+ expect {
155
+ subject.parse(text)
156
+ }.to raise_error(Puppet::Util::IniConfig::IniParseError,
157
+ /Section "mysect" is already defined, cannot redefine/)
158
+ end
159
+
160
+ end
161
+
162
+ describe "parsing properties" do
163
+ it "raises an error if the property is not within a section" do
164
+ text = "key=val\n"
165
+
166
+ expect {
167
+ subject.parse(text)
168
+ }.to raise_error(Puppet::Util::IniConfig::IniParseError,
169
+ /Property with key "key" outside of a section/)
170
+ end
171
+
172
+ it "adds the property to the current section" do
173
+ text = "[main]\nkey=val\n"
174
+
175
+ subject.parse(text)
176
+ expect(subject.contents).to have(1).items
177
+ sect = subject.contents[0]
178
+ expect(sect['key']).to eq "val"
179
+ end
180
+ end
181
+
182
+ describe "parsing line continuations" do
183
+
184
+ it "adds the continued line to the last parsed property" do
185
+ text = "[main]\nkey=val\n moreval"
186
+
187
+ subject.parse(text)
188
+ expect(subject.contents).to have(1).items
189
+ sect = subject.contents[0]
190
+ expect(sect['key']).to eq "val\n moreval"
191
+ end
192
+ end
193
+
194
+ describe "parsing comments and whitespace" do
195
+ it "treats # as a comment leader" do
196
+ text = "# octothorpe comment"
197
+
198
+ subject.parse(text)
199
+ expect(subject.contents).to eq ["# octothorpe comment"]
200
+ end
201
+
202
+ it "treats ; as a comment leader" do
203
+ text = "; semicolon comment"
204
+
205
+ subject.parse(text)
206
+ expect(subject.contents).to eq ["; semicolon comment"]
207
+ end
208
+
209
+ it "treates 'rem' as a comment leader" do
210
+ text = "rem rapid eye movement comment"
211
+
212
+ subject.parse(text)
213
+ expect(subject.contents).to eq ["rem rapid eye movement comment"]
214
+ end
215
+
216
+ it "stores comments and whitespace in a section in the correct section" do
217
+ text = "[main]\n; main section comment"
218
+
219
+ subject.parse(text)
220
+
221
+ sect = subject.get_section("main")
222
+ expect(sect.entries).to eq ["; main section comment"]
223
+ end
224
+ end
225
+ end
226
+
227
+ it "can return all sections" do
228
+ text = "[first]\n" +
229
+ "; comment\n" +
230
+ "[second]\n" +
231
+ "key=value"
232
+
233
+ subject.parse(text)
234
+
235
+ sections = subject.sections
236
+ expect(sections).to have(2).items
237
+ expect(sections[0].name).to eq "first"
238
+ expect(sections[1].name).to eq "second"
239
+ end
240
+
241
+ it "can retrieve a specific section" do
242
+ text = "[first]\n" +
243
+ "; comment\n" +
244
+ "[second]\n" +
245
+ "key=value"
246
+
247
+ subject.parse(text)
248
+
249
+ section = subject.get_section("second")
250
+ expect(section.name).to eq "second"
251
+ expect(section["key"]).to eq "value"
252
+ end
253
+
254
+ describe "formatting" do
255
+
256
+ it "concatenates each formatted section in order" do
257
+ subject.contents << first_sect << second_sect
258
+
259
+ expected = "[firstsection]\n" +
260
+ "# comment\n" +
261
+ "onefish=redfish\n" +
262
+ "\n" +
263
+ "[secondsection]\n" +
264
+ "twofish=bluefish\n"
265
+
266
+ expect(subject.format).to eq expected
267
+ end
268
+
269
+ it "includes comments that are not within a section" do
270
+ subject.contents << "# This comment is not in a section\n" << first_sect << second_sect
271
+
272
+ expected = "# This comment is not in a section\n" +
273
+ "[firstsection]\n" +
274
+ "# comment\n" +
275
+ "onefish=redfish\n" +
276
+ "\n" +
277
+ "[secondsection]\n" +
278
+ "twofish=bluefish\n"
279
+
280
+ expect(subject.format).to eq expected
281
+ end
282
+
283
+ it "excludes sections that are marked to be destroyed" do
284
+ subject.contents << first_sect << second_sect
285
+ first_sect.destroy = true
286
+
287
+ expected = "[secondsection]\n" + "twofish=bluefish\n"
288
+
289
+ expect(subject.format).to eq expected
290
+ end
291
+ end
292
+
293
+ describe "storing the file" do
294
+ describe "with empty contents" do
295
+ describe "and destroy_empty is true" do
296
+ before { subject.destroy_empty = true }
297
+ it "removes the file if there are no sections" do
298
+ File.expects(:unlink)
299
+ subject.store
300
+ end
301
+
302
+ it "removes the file if all sections are marked to be destroyed" do
303
+ subject.contents << first_sect << second_sect
304
+ first_sect.destroy = true
305
+ second_sect.destroy = true
306
+
307
+ File.expects(:unlink)
308
+ subject.store
309
+ end
310
+
311
+ it "doesn't remove the file if not all sections are marked to be destroyed" do
312
+ subject.contents << first_sect << second_sect
313
+ first_sect.destroy = true
314
+ second_sect.destroy = false
315
+
316
+ File.expects(:unlink).never
317
+ subject.filetype.stubs(:write)
318
+ subject.store
319
+ end
320
+ end
321
+
322
+ it "rewrites the file if destroy_empty is false" do
323
+ subject.contents << first_sect << second_sect
324
+ first_sect.destroy = true
325
+ second_sect.destroy = true
326
+
327
+ File.expects(:unlink).never
328
+ subject.stubs(:format).returns "formatted"
329
+ subject.filetype.expects(:write).with("formatted")
330
+ subject.store
331
+ end
332
+ end
333
+
334
+ it "rewrites the file if any section is dirty" do
335
+ subject.contents << first_sect << second_sect
336
+ first_sect.mark_dirty
337
+ second_sect.mark_clean
338
+
339
+ subject.stubs(:format).returns "formatted"
340
+ subject.filetype.expects(:write).with("formatted")
341
+ subject.store
342
+ end
343
+
344
+ it "doesn't modify the file if all sections are clean" do
345
+ subject.contents << first_sect << second_sect
346
+ first_sect.mark_clean
347
+ second_sect.mark_clean
348
+
349
+ subject.stubs(:format).returns "formatted"
350
+ subject.filetype.expects(:write).never
351
+ subject.store
352
+ end
353
+ end
354
+ end
355
+
356
+ describe Puppet::Util::IniConfig::FileCollection do
357
+
358
+ let(:path_a) { '/some/nonexistent/file/a' }
359
+ let(:path_b) { '/some/nonexistent/file/b' }
360
+
361
+ let(:file_a) { Puppet::Util::IniConfig::PhysicalFile.new(path_a) }
362
+ let(:file_b) { Puppet::Util::IniConfig::PhysicalFile.new(path_b) }
363
+
364
+ let(:sect_a1) { Puppet::Util::IniConfig::Section.new('sect_a1', path_a) }
365
+ let(:sect_a2) { Puppet::Util::IniConfig::Section.new('sect_a2', path_a) }
366
+
367
+ let(:sect_b1) { Puppet::Util::IniConfig::Section.new('sect_b1', path_b) }
368
+ let(:sect_b2) { Puppet::Util::IniConfig::Section.new('sect_b2', path_b) }
369
+
370
+ before do
371
+ file_a.contents << sect_a1 << sect_a2
372
+ file_b.contents << sect_b1 << sect_b2
373
+ end
374
+
375
+ describe "reading a file" do
376
+ let(:stub_file) { stub('Physical file') }
377
+
378
+ it "creates a new PhysicalFile and uses that to read the file" do
379
+ stub_file.expects(:read)
380
+ stub_file.expects(:file_collection=)
381
+ Puppet::Util::IniConfig::PhysicalFile.expects(:new).with(path_a).returns stub_file
382
+
383
+ subject.read(path_a)
384
+ end
385
+
386
+ it "stores the PhysicalFile and the path to the file" do
387
+ stub_file.stubs(:read)
388
+ stub_file.stubs(:file_collection=)
389
+ Puppet::Util::IniConfig::PhysicalFile.stubs(:new).with(path_a).returns stub_file
390
+ subject.read(path_a)
391
+
392
+ path, physical_file = subject.files.first
393
+
394
+ expect(path).to eq(path_a)
395
+ expect(physical_file).to eq stub_file
396
+ end
397
+ end
398
+
399
+ describe "storing all files" do
400
+ before do
401
+ subject.files[path_a] = file_a
402
+ subject.files[path_b] = file_b
403
+ end
404
+
405
+ it "stores all files in the collection" do
406
+ file_a.expects(:store).once
407
+ file_b.expects(:store).once
408
+
409
+ subject.store
410
+ end
411
+ end
412
+
413
+ describe "iterating over sections" do
414
+ before do
415
+ subject.files[path_a] = file_a
416
+ subject.files[path_b] = file_b
417
+ end
418
+
419
+ it "yields every section from every file" do
420
+ [sect_a1, sect_a2, sect_b1, sect_b2].each do |sect|
421
+ sect.expects(:touch).once
422
+ end
423
+
424
+ subject.each_section do |sect|
425
+ sect.touch
426
+ end
427
+ end
428
+ end
429
+
430
+ describe "iterating over files" do
431
+ before do
432
+ subject.files[path_a] = file_a
433
+ subject.files[path_b] = file_b
434
+ end
435
+
436
+ it "yields the path to every file in the collection" do
437
+ seen = []
438
+ subject.each_file do |file|
439
+ seen << file
440
+ end
441
+
442
+ expect(seen).to include(path_a)
443
+ expect(seen).to include(path_b)
444
+ end
445
+ end
446
+
447
+ describe "retrieving a specific section" do
448
+ before do
449
+ subject.files[path_a] = file_a
450
+ subject.files[path_b] = file_b
451
+ end
452
+
453
+ it "retrieves the first section defined" do
454
+ expect(subject.get_section('sect_b1')).to eq sect_b1
455
+ end
456
+
457
+ it "returns nil if there was no section with the given name" do
458
+ expect(subject.get_section('nope')).to be_nil
459
+ end
460
+
461
+ it "allows #[] to be used as an alias to #get_section" do
462
+ expect(subject['b2']).to eq subject.get_section('b2')
463
+ end
464
+ end
465
+
466
+ describe "checking if a section has been defined" do
467
+ before do
468
+ subject.files[path_a] = file_a
469
+ subject.files[path_b] = file_b
470
+ end
471
+
472
+ it "is true if a section with the given name is defined" do
473
+ expect(subject.include?('sect_a1')).to be_true
474
+ end
475
+
476
+ it "is false if a section with the given name can't be found" do
477
+ expect(subject.include?('nonexistent')).to be_false
478
+ end
479
+ end
480
+
481
+ describe "adding a new section" do
482
+ before do
483
+ subject.files[path_a] = file_a
484
+ subject.files[path_b] = file_b
485
+ end
486
+
487
+ it "adds the section to the appropriate file" do
488
+ file_a.expects(:add_section).with('newsect')
489
+ subject.add_section('newsect', path_a)
490
+ end
491
+ end
492
+ end