puppet 7.12.1 → 7.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/CODEOWNERS +1 -1
  3. data/Gemfile +2 -2
  4. data/Gemfile.lock +36 -31
  5. data/ext/project_data.yaml +1 -1
  6. data/lib/puppet/application/lookup.rb +74 -24
  7. data/lib/puppet/concurrent/thread_local_singleton.rb +5 -3
  8. data/lib/puppet/configurer.rb +8 -14
  9. data/lib/puppet/defaults.rb +13 -1
  10. data/lib/puppet/face/generate.rb +2 -0
  11. data/lib/puppet/file_serving/metadata.rb +3 -0
  12. data/lib/puppet/file_system/file_impl.rb +7 -7
  13. data/lib/puppet/file_system/jruby.rb +1 -1
  14. data/lib/puppet/file_system/path_pattern.rb +10 -15
  15. data/lib/puppet/file_system/uniquefile.rb +1 -1
  16. data/lib/puppet/file_system/windows.rb +4 -4
  17. data/lib/puppet/file_system.rb +1 -1
  18. data/lib/puppet/functions/next.rb +18 -1
  19. data/lib/puppet/functions/tree_each.rb +0 -1
  20. data/lib/puppet/functions/versioncmp.rb +6 -2
  21. data/lib/puppet/generate/type.rb +9 -0
  22. data/lib/puppet/graph/simple_graph.rb +2 -1
  23. data/lib/puppet/http/client.rb +1 -1
  24. data/lib/puppet/node.rb +1 -1
  25. data/lib/puppet/pops/parser/code_merger.rb +4 -4
  26. data/lib/puppet/pops/parser/egrammar.ra +2 -0
  27. data/lib/puppet/pops/parser/eparser.rb +574 -558
  28. data/lib/puppet/pops/serialization/to_data_converter.rb +6 -18
  29. data/lib/puppet/pops/validation/checker4_0.rb +7 -2
  30. data/lib/puppet/provider/service/init.rb +5 -4
  31. data/lib/puppet/resource/type_collection.rb +21 -17
  32. data/lib/puppet/ssl/verifier.rb +3 -1
  33. data/lib/puppet/transaction/persistence.rb +22 -12
  34. data/lib/puppet/type/exec.rb +1 -1
  35. data/lib/puppet/type/file/data_sync.rb +1 -1
  36. data/lib/puppet/type/file/group.rb +8 -1
  37. data/lib/puppet/type/file/owner.rb +8 -1
  38. data/lib/puppet/type/user.rb +41 -39
  39. data/lib/puppet/util/json.rb +17 -0
  40. data/lib/puppet/util/log.rb +7 -2
  41. data/lib/puppet/util/monkey_patches.rb +26 -4
  42. data/lib/puppet/util/package.rb +25 -16
  43. data/lib/puppet/util/yaml.rb +16 -1
  44. data/lib/puppet/util.rb +1 -0
  45. data/lib/puppet/version.rb +1 -1
  46. data/lib/puppet.rb +1 -0
  47. data/locales/puppet.pot +5 -9741
  48. data/man/man5/puppet.conf.5 +21 -2
  49. data/man/man8/puppet-agent.8 +1 -1
  50. data/man/man8/puppet-apply.8 +1 -1
  51. data/man/man8/puppet-catalog.8 +1 -1
  52. data/man/man8/puppet-config.8 +1 -1
  53. data/man/man8/puppet-describe.8 +1 -1
  54. data/man/man8/puppet-device.8 +1 -1
  55. data/man/man8/puppet-doc.8 +1 -1
  56. data/man/man8/puppet-epp.8 +1 -1
  57. data/man/man8/puppet-facts.8 +1 -1
  58. data/man/man8/puppet-filebucket.8 +1 -1
  59. data/man/man8/puppet-generate.8 +1 -1
  60. data/man/man8/puppet-help.8 +1 -1
  61. data/man/man8/puppet-lookup.8 +9 -6
  62. data/man/man8/puppet-module.8 +1 -1
  63. data/man/man8/puppet-node.8 +1 -1
  64. data/man/man8/puppet-parser.8 +1 -1
  65. data/man/man8/puppet-plugin.8 +1 -1
  66. data/man/man8/puppet-report.8 +1 -1
  67. data/man/man8/puppet-resource.8 +1 -1
  68. data/man/man8/puppet-script.8 +1 -1
  69. data/man/man8/puppet-ssl.8 +1 -1
  70. data/man/man8/puppet.8 +2 -2
  71. data/spec/fixtures/unit/forge/bacula.json +1 -1
  72. data/spec/integration/application/lookup_spec.rb +81 -50
  73. data/spec/integration/application/resource_spec.rb +6 -2
  74. data/spec/integration/parser/pcore_resource_spec.rb +10 -0
  75. data/spec/shared_contexts/l10n.rb +5 -0
  76. data/spec/unit/application/lookup_spec.rb +131 -10
  77. data/spec/unit/concurrent/thread_local_singleton_spec.rb +39 -0
  78. data/spec/unit/configurer_spec.rb +124 -61
  79. data/spec/unit/confiner_spec.rb +6 -6
  80. data/spec/unit/face/generate_spec.rb +64 -0
  81. data/spec/unit/file_system/uniquefile_spec.rb +7 -1
  82. data/spec/unit/file_system_spec.rb +34 -4
  83. data/spec/unit/forge/module_release_spec.rb +3 -3
  84. data/spec/unit/functions/versioncmp_spec.rb +40 -4
  85. data/spec/unit/node_spec.rb +6 -0
  86. data/spec/unit/pops/parser/parse_containers_spec.rb +2 -2
  87. data/spec/unit/pops/serialization/to_from_hr_spec.rb +0 -58
  88. data/spec/unit/pops/validator/validator_spec.rb +5 -0
  89. data/spec/unit/provider/service/gentoo_spec.rb +6 -5
  90. data/spec/unit/provider/service/init_spec.rb +15 -9
  91. data/spec/unit/provider/service/openwrt_spec.rb +21 -29
  92. data/spec/unit/provider/service/redhat_spec.rb +3 -2
  93. data/spec/unit/transaction/persistence_spec.rb +51 -0
  94. data/spec/unit/type/file/group_spec.rb +7 -0
  95. data/spec/unit/type/file/owner_spec.rb +7 -0
  96. data/spec/unit/type/user_spec.rb +67 -45
  97. data/spec/unit/util/json_spec.rb +126 -0
  98. data/spec/unit/util/windows_spec.rb +23 -0
  99. data/spec/unit/util/yaml_spec.rb +37 -13
  100. metadata +17 -5
@@ -518,34 +518,155 @@ Searching for "a"
518
518
  end
519
519
 
520
520
  it 'receives extra facts in top scope' do
521
- file_path = tmpdir('lookup_spec')
522
- filename = File.join(file_path, "facts.yaml")
523
- File.open(filename, "w+") { |f| f.write(<<-YAML.unindent) }
521
+ file_path = file_containing('facts.yaml', <<~CONTENT)
524
522
  ---
525
523
  cx: ' C from facts'
526
- YAML
524
+ CONTENT
527
525
 
528
526
  lookup.options[:node] = node
529
- lookup.options[:fact_file] = filename
527
+ lookup.options[:fact_file] = file_path
530
528
  lookup.options[:render_as] = :s
531
529
  allow(lookup.command_line).to receive(:args).and_return(['c'])
532
530
  expect(run_lookup(lookup)).to eql("This is C from facts")
533
531
  end
534
532
 
535
533
  it 'receives extra facts in the facts hash' do
536
- file_path = tmpdir('lookup_spec')
537
- filename = File.join(file_path, "facts.yaml")
538
- File.open(filename, "w+") { |f| f.write(<<-YAML.unindent) }
534
+ file_path = file_containing('facts.yaml', <<~CONTENT)
539
535
  ---
540
536
  cx: ' G from facts'
541
- YAML
537
+ CONTENT
542
538
 
543
539
  lookup.options[:node] = node
544
- lookup.options[:fact_file] = filename
540
+ lookup.options[:fact_file] = file_path
545
541
  lookup.options[:render_as] = :s
546
542
  allow(lookup.command_line).to receive(:args).and_return(['g'])
547
543
  expect(run_lookup(lookup)).to eql("This is G from facts in facts hash")
548
544
  end
545
+
546
+ describe 'when retrieving given facts' do
547
+ before do
548
+ lookup.options[:node] = node
549
+ allow(lookup.command_line).to receive(:args).and_return(['g'])
550
+ end
551
+
552
+ it 'loads files with yaml extension as yaml on first try' do
553
+ file_path = file_containing('facts.yaml', <<~CONTENT)
554
+ ---
555
+ cx: ' G from facts'
556
+ CONTENT
557
+ lookup.options[:fact_file] = file_path
558
+
559
+ expect(Puppet::Util::Yaml).to receive(:safe_load_file).with(file_path, []).and_call_original
560
+ run_lookup(lookup)
561
+ end
562
+
563
+ it 'loads files with yml extension as yaml on first try' do
564
+ file_path = file_containing('facts.yml', <<~CONTENT)
565
+ ---
566
+ cx: ' G from facts'
567
+ CONTENT
568
+ lookup.options[:fact_file] = file_path
569
+
570
+ expect(Puppet::Util::Yaml).to receive(:safe_load_file).with(file_path, []).and_call_original
571
+ run_lookup(lookup)
572
+ end
573
+
574
+ it 'loads files with json extension as json on first try' do
575
+ file_path = file_containing('facts.json', <<~CONTENT)
576
+ {
577
+ "cx": " G from facts"
578
+ }
579
+ CONTENT
580
+ lookup.options[:fact_file] = file_path
581
+
582
+ expect(Puppet::Util::Json).to receive(:load_file).with(file_path, {}).and_call_original
583
+ run_lookup(lookup)
584
+ end
585
+
586
+ it 'detects file format accordingly even with random file extension' do
587
+ file_path = file_containing('facts.txt', <<~CONTENT)
588
+ {
589
+ "cx": " G from facts"
590
+ }
591
+ CONTENT
592
+ lookup.options[:fact_file] = file_path
593
+
594
+ expect(Puppet::Util::Json).to receive(:load_file_if_valid).with(file_path).and_call_original
595
+ expect(Puppet::Util::Yaml).not_to receive(:safe_load_file_if_valid).with(file_path)
596
+ run_lookup(lookup)
597
+ end
598
+
599
+ it 'detects file without extension as json due to valid contents' do
600
+ file_path = file_containing('facts', <<~CONTENT)
601
+ {
602
+ "cx": " G from facts"
603
+ }
604
+ CONTENT
605
+ lookup.options[:fact_file] = file_path
606
+
607
+ expect(Puppet::Util::Json).to receive(:load_file_if_valid).with(file_path).and_call_original
608
+ expect(Puppet::Util::Yaml).not_to receive(:safe_load_file_if_valid).with(file_path)
609
+ run_lookup(lookup)
610
+ end
611
+
612
+ it 'detects file without extension as yaml due to valid contents' do
613
+ file_path = file_containing('facts', <<~CONTENT)
614
+ ---
615
+ cx: ' G from facts'
616
+ CONTENT
617
+ lookup.options[:fact_file] = file_path
618
+
619
+ expect(Puppet::Util::Json.load_file_if_valid(file_path)).to be_nil
620
+ expect(Puppet::Util::Yaml).to receive(:safe_load_file_if_valid).with(file_path).and_call_original
621
+ run_lookup(lookup)
622
+ end
623
+
624
+ it 'raises error due to invalid contents' do
625
+ file_path = file_containing('facts.yml', <<~CONTENT)
626
+ INVALID CONTENT
627
+ CONTENT
628
+ lookup.options[:fact_file] = file_path
629
+
630
+ expect {
631
+ lookup.run_command
632
+ }.to raise_error(/Incorrectly formatted data in .+ given via the --facts flag \(only accepts yaml and json files\)/)
633
+ end
634
+
635
+ it "fails when a node doesn't have facts" do
636
+ lookup.options[:node] = "bad.node"
637
+ allow(lookup.command_line).to receive(:args).and_return(['c'])
638
+
639
+ expected_error = "No facts available for target node: #{lookup.options[:node]}"
640
+ expect { lookup.run_command }.to raise_error(RuntimeError, expected_error)
641
+ end
642
+
643
+ it 'raises error due to missing trusted information facts in --facts file' do
644
+ file_path = file_containing('facts.yaml', <<~CONTENT)
645
+ ---
646
+ fqdn: some.fqdn.com
647
+ CONTENT
648
+ lookup.options[:fact_file] = file_path
649
+
650
+ expect {
651
+ lookup.run_command
652
+ }.to raise_error(/When overriding any of the hostname,domain,fqdn,clientcert facts with #{file_path} given via the --facts flag, they must all be overridden./)
653
+ end
654
+
655
+ it 'does not fail when all trusted information facts are provided via --facts file' do
656
+ file_path = file_containing('facts.yaml', <<~CONTENT)
657
+ ---
658
+ fqdn: some.fqdn.com
659
+ hostname: some.hostname
660
+ domain: some.domain
661
+ clientcert: some.clientcert
662
+ CONTENT
663
+ lookup.options[:fact_file] = file_path
664
+
665
+ expect {
666
+ lookup.run_command
667
+ }.to exit_with(0)
668
+ end
669
+ end
549
670
  end
550
671
 
551
672
  context 'using a puppet function as data provider' do
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+ require 'puppet/concurrent/thread_local_singleton'
3
+
4
+ class PuppetSpec::Singleton
5
+ extend Puppet::Concurrent::ThreadLocalSingleton
6
+ end
7
+
8
+ # Use the `equal?` matcher to ensure we get the same object
9
+ describe Puppet::Concurrent::ThreadLocalSingleton do
10
+ it 'returns the same object for a single thread' do
11
+ expect(PuppetSpec::Singleton.singleton).to equal(PuppetSpec::Singleton.singleton)
12
+ end
13
+
14
+ it 'is not inherited for a newly created thread' do
15
+ main_thread_local = PuppetSpec::Singleton.singleton
16
+ Thread.new do
17
+ expect(main_thread_local).to_not equal(PuppetSpec::Singleton.singleton)
18
+ end.join
19
+ end
20
+
21
+ it 'does not leak outside a thread' do
22
+ thread_local = nil
23
+ Thread.new do
24
+ thread_local = PuppetSpec::Singleton.singleton
25
+ end.join
26
+ expect(thread_local).to_not equal(PuppetSpec::Singleton.singleton)
27
+ end
28
+
29
+ it 'is different for each thread' do
30
+ locals = []
31
+ Thread.new do
32
+ locals << PuppetSpec::Singleton.singleton
33
+ end.join
34
+ Thread.new do
35
+ locals << PuppetSpec::Singleton.singleton
36
+ end.join
37
+ expect(locals.first).to_not equal(locals.last)
38
+ end
39
+ end
@@ -9,9 +9,6 @@ describe Puppet::Configurer do
9
9
  Puppet[:report] = true
10
10
 
11
11
  catalog.add_resource(resource)
12
- allow_any_instance_of(described_class).to(
13
- receive(:valid_server_environment?).and_return(true)
14
- )
15
12
 
16
13
  Puppet[:lastrunfile] = file_containing('last_run_summary.yaml', <<~SUMMARY)
17
14
  ---
@@ -78,10 +75,44 @@ describe Puppet::Configurer do
78
75
  end
79
76
  end
80
77
 
78
+ describe "when executing a catalog run without stubbing valid_server_environment?" do
79
+ before do
80
+ Puppet::Resource::Catalog.indirection.terminus_class = :rest
81
+ allow(Puppet::Resource::Catalog.indirection).to receive(:find).and_return(catalog)
82
+ end
83
+
84
+ it 'skips initial plugin sync if environment is not found and no strict_environment_mode' do
85
+ body = "{\"message\":\"Not Found: Could not find environment 'fasdfad'\",\"issue_kind\":\"RUNTIME_ERROR\"}"
86
+ stub_request(:get, %r{/puppet/v3/file_metadatas/plugins?}).to_return(
87
+ status: 404, body: body, headers: {'Content-Type' => 'application/json'}
88
+ )
89
+
90
+ configurer.run(:pluginsync => true)
91
+
92
+ expect(@logs).to include(an_object_having_attributes(level: :notice, message: %r{Environment 'production' not found on server, skipping initial pluginsync.}))
93
+ expect(@logs).to include(an_object_having_attributes(level: :notice, message: /Applied catalog in .* seconds/))
94
+ end
95
+
96
+ it 'if strict_environment_mode is set and environment is not found, aborts the puppet run' do
97
+ Puppet[:strict_environment_mode] = true
98
+ body = "{\"message\":\"Not Found: Could not find environment 'fasdfad'\",\"issue_kind\":\"RUNTIME_ERROR\"}"
99
+ stub_request(:get, %r{/puppet/v3/file_metadatas/plugins?}).to_return(
100
+ status: 404, body: body, headers: {'Content-Type' => 'application/json'}
101
+ )
102
+
103
+ configurer.run(:pluginsync => true)
104
+
105
+ expect(@logs).to include(an_object_having_attributes(level: :err, message: %r{Failed to apply catalog: Environment 'production' not found on server, aborting run.}))
106
+ end
107
+ end
108
+
81
109
  describe "when executing a catalog run" do
82
110
  before do
83
111
  Puppet::Resource::Catalog.indirection.terminus_class = :rest
84
112
  allow(Puppet::Resource::Catalog.indirection).to receive(:find).and_return(catalog)
113
+ allow_any_instance_of(described_class).to(
114
+ receive(:valid_server_environment?).and_return(true)
115
+ )
85
116
  end
86
117
 
87
118
  it "downloads plugins when told" do
@@ -1251,88 +1282,120 @@ describe Puppet::Configurer do
1251
1282
  converged_environment: #{last_server_specified_environment}
1252
1283
  run_mode: agent
1253
1284
  SUMMARY
1285
+ end
1254
1286
 
1255
- expect(Puppet::Node.indirection).not_to receive(:find)
1287
+ describe "when the use_last_environment is set to true" do
1288
+ before do
1289
+ expect(Puppet::Node.indirection).not_to receive(:find)
1256
1290
  .with(anything, hash_including(:ignore_cache => true, :fail_on_404 => true))
1257
- end
1291
+ end
1258
1292
 
1259
- it "prefers the environment set via cli" do
1260
- Puppet.settings.handlearg('--environment', 'usethis')
1261
- configurer.run
1293
+ it "prefers the environment set via cli" do
1294
+ Puppet.settings.handlearg('--environment', 'usethis')
1295
+ configurer.run
1262
1296
 
1263
- expect(configurer.environment).to eq('usethis')
1264
- end
1297
+ expect(configurer.environment).to eq('usethis')
1298
+ end
1265
1299
 
1266
- it "prefers the environment set via lastrunfile over config" do
1267
- FileUtils.mkdir_p(Puppet[:confdir])
1268
- set_puppet_conf(Puppet[:confdir], <<~CONF)
1269
- [main]
1270
- environment = usethis
1271
- lastrunfile = #{Puppet[:lastrunfile]}
1272
- CONF
1300
+ it "prefers the environment set via lastrunfile over config" do
1301
+ FileUtils.mkdir_p(Puppet[:confdir])
1302
+ set_puppet_conf(Puppet[:confdir], <<~CONF)
1303
+ [main]
1304
+ environment = usethis
1305
+ lastrunfile = #{Puppet[:lastrunfile]}
1306
+ CONF
1273
1307
 
1274
- Puppet.initialize_settings
1275
- configurer.run
1308
+ Puppet.initialize_settings
1309
+ configurer.run
1276
1310
 
1277
- expect(configurer.environment).to eq(last_server_specified_environment)
1278
- end
1311
+ expect(configurer.environment).to eq(last_server_specified_environment)
1312
+ end
1279
1313
 
1280
- it "uses the environment from Puppet[:environment] if given a catalog" do
1281
- configurer.run(catalog: catalog)
1314
+ it "uses the environment from Puppet[:environment] if given a catalog" do
1315
+ configurer.run(catalog: catalog)
1282
1316
 
1283
- expect(configurer.environment).to eq(Puppet[:environment])
1284
- end
1317
+ expect(configurer.environment).to eq(Puppet[:environment])
1318
+ end
1285
1319
 
1286
- it "uses the environment from Puppet[:environment] if use_cached_catalog = true" do
1287
- Puppet[:use_cached_catalog] = true
1288
- expects_cached_catalog_only(catalog)
1289
- configurer.run
1320
+ it "uses the environment from Puppet[:environment] if use_cached_catalog = true" do
1321
+ Puppet[:use_cached_catalog] = true
1322
+ expects_cached_catalog_only(catalog)
1323
+ configurer.run
1290
1324
 
1291
- expect(configurer.environment).to eq(Puppet[:environment])
1292
- end
1325
+ expect(configurer.environment).to eq(Puppet[:environment])
1326
+ end
1293
1327
 
1294
- describe "when the environment is not set via CLI" do
1295
- it "uses the environment found in lastrunfile if the key exists" do
1296
- configurer.run
1328
+ describe "when the environment is not set via CLI" do
1329
+ it "uses the environment found in lastrunfile if the key exists" do
1330
+ configurer.run
1297
1331
 
1298
- expect(configurer.environment).to eq(last_server_specified_environment)
1332
+ expect(configurer.environment).to eq(last_server_specified_environment)
1333
+ end
1334
+
1335
+ it "pushes the converged environment found in lastrunfile over the existing context" do
1336
+ initial_env = Puppet::Node::Environment.remote('production')
1337
+ Puppet.push_context(
1338
+ current_environment: initial_env,
1339
+ loaders: Puppet::Pops::Loaders.new(initial_env, true))
1340
+
1341
+ expect(Puppet).to receive(:push_context).with(
1342
+ hash_including(:current_environment, :loaders),
1343
+ "Local node environment #{last_server_specified_environment} for configurer transaction"
1344
+ ).once.and_call_original
1345
+
1346
+ configurer.run
1347
+ end
1348
+
1349
+ it "uses the environment from Puppet[:environment] if strict_environment_mode is set" do
1350
+ Puppet[:strict_environment_mode] = true
1351
+ configurer.run
1352
+
1353
+ expect(configurer.environment).to eq(Puppet[:environment])
1354
+ end
1355
+
1356
+ it "uses the environment from Puppet[:environment] if initial_environment is the same as converged_environment" do
1357
+ Puppet[:lastrunfile] = file_containing('last_run_summary.yaml', <<~SUMMARY)
1358
+ ---
1359
+ version:
1360
+ config: 1624882680
1361
+ puppet: 6.24.0
1362
+ application:
1363
+ initial_environment: development
1364
+ converged_environment: development
1365
+ run_mode: agent
1366
+ SUMMARY
1367
+ configurer.run
1368
+
1369
+ expect(configurer.environment).to eq(Puppet[:environment])
1370
+ end
1299
1371
  end
1372
+ end
1300
1373
 
1301
- it "pushes the converged environment found in lastrunfile over the existing context" do
1302
- initial_env = Puppet::Node::Environment.remote('production')
1303
- Puppet.push_context(
1304
- current_environment: initial_env,
1305
- loaders: Puppet::Pops::Loaders.new(initial_env, true))
1374
+ describe "when the use_last_environment setting is set to false" do
1375
+ let(:node_environment) { Puppet::Node::Environment.remote(:salam) }
1376
+ let(:node) { Puppet::Node.new(Puppet[:node_name_value]) }
1306
1377
 
1307
- expect(Puppet).to receive(:push_context).with(
1308
- hash_including(:current_environment, :loaders),
1309
- "Local node environment #{last_server_specified_environment} for configurer transaction"
1310
- ).once.and_call_original
1378
+ before do
1379
+ Puppet[:use_last_environment] = false
1380
+ node.environment = node_environment
1311
1381
 
1312
- configurer.run
1382
+ allow(Puppet::Node.indirection).to receive(:find)
1383
+ allow(Puppet::Node.indirection).to receive(:find)
1384
+ .with(anything, hash_including(:ignore_cache => true, :fail_on_404 => true))
1385
+ .and_return(node)
1313
1386
  end
1314
1387
 
1315
- it "uses the environment from Puppet[:environment] if strict_environment_mode is set" do
1316
- Puppet[:strict_environment_mode] = true
1317
- configurer.run
1388
+ it "does a node request" do
1389
+ expect(Puppet::Node.indirection).to receive(:find)
1390
+ .with(anything, hash_including(:ignore_cache => true, :fail_on_404 => true))
1318
1391
 
1319
- expect(configurer.environment).to eq(Puppet[:environment])
1392
+ configurer.run
1320
1393
  end
1321
1394
 
1322
- it "uses the environment from Puppet[:environment] if initial_environment is the same as converged_environment" do
1323
- Puppet[:lastrunfile] = file_containing('last_run_summary.yaml', <<~SUMMARY)
1324
- ---
1325
- version:
1326
- config: 1624882680
1327
- puppet: 6.24.0
1328
- application:
1329
- initial_environment: development
1330
- converged_environment: development
1331
- run_mode: agent
1332
- SUMMARY
1395
+ it "uses the node environment from the node request" do
1333
1396
  configurer.run
1334
1397
 
1335
- expect(configurer.environment).to eq(Puppet[:environment])
1398
+ expect(configurer.environment).to eq(node_environment.name.to_s)
1336
1399
  end
1337
1400
  end
1338
1401
  end
@@ -3,6 +3,8 @@ require 'spec_helper'
3
3
  require 'puppet/confiner'
4
4
 
5
5
  describe Puppet::Confiner do
6
+ let(:coll) { Puppet::ConfineCollection.new('') }
7
+
6
8
  before do
7
9
  @object = Object.new
8
10
  @object.extend(Puppet::Confiner)
@@ -21,7 +23,6 @@ describe Puppet::Confiner do
21
23
  end
22
24
 
23
25
  it "should delegate its confine method to its confine collection" do
24
- coll = double('collection')
25
26
  allow(@object).to receive(:confine_collection).and_return(coll)
26
27
  expect(coll).to receive(:confine).with(:foo => :bar, :bee => :baz)
27
28
  @object.confine(:foo => :bar, :bee => :baz)
@@ -39,22 +40,21 @@ describe Puppet::Confiner do
39
40
 
40
41
  describe "when testing suitability" do
41
42
  before do
42
- @coll = double('collection')
43
- allow(@object).to receive(:confine_collection).and_return(@coll)
43
+ allow(@object).to receive(:confine_collection).and_return(coll)
44
44
  end
45
45
 
46
46
  it "should return true if the confine collection is valid" do
47
- expect(@coll).to receive(:valid?).and_return(true)
47
+ expect(coll).to receive(:valid?).and_return(true)
48
48
  expect(@object).to be_suitable
49
49
  end
50
50
 
51
51
  it "should return false if the confine collection is invalid" do
52
- expect(@coll).to receive(:valid?).and_return(false)
52
+ expect(coll).to receive(:valid?).and_return(false)
53
53
  expect(@object).not_to be_suitable
54
54
  end
55
55
 
56
56
  it "should return the summary of the confine collection if a long result is asked for" do
57
- expect(@coll).to receive(:summary).and_return("myresult")
57
+ expect(coll).to receive(:summary).and_return("myresult")
58
58
  expect(@object.suitable?(false)).to eq("myresult")
59
59
  end
60
60
  end
@@ -221,6 +221,70 @@ describe Puppet::Face[:generate, :current] do
221
221
  end
222
222
 
223
223
  end
224
+
225
+ context "in an environment with a faulty type" do
226
+ let(:dir) do
227
+ dir_containing('environments', { 'testing_generate2' => {
228
+ 'environment.conf' => "modulepath = modules",
229
+ 'manifests' => { 'site.pp' => "" },
230
+ 'modules' => {
231
+ 'm3' => {
232
+ 'lib' => { 'puppet' => { 'type' => {
233
+ 'test3.rb' => <<-EOF
234
+ module Puppet
235
+ Type.newtype(:test3) do
236
+ @doc = "Docs for resource"
237
+ def self.title_patterns
238
+ identity = lambda {|x| x}
239
+ [
240
+ [
241
+ /^(.*)_(.*)$/,
242
+ [
243
+ [:name, identity ]
244
+ ]
245
+ ]
246
+ ]
247
+ end
248
+ newproperty(:message) do
249
+ desc "Docs for 'message' property"
250
+ end
251
+ newparam(:name) do
252
+ desc "Docs for 'name' parameter"
253
+ isnamevar
254
+ end
255
+ end; end
256
+ EOF
257
+ } }
258
+ }
259
+ }
260
+ }}})
261
+ end
262
+
263
+ let(:modulepath) do
264
+ File.join(dir, 'testing_generate2', 'modules')
265
+ end
266
+
267
+ let(:m3) do
268
+ File.join(modulepath, 'm3')
269
+ end
270
+
271
+ around(:each) do |example|
272
+ Puppet.settings.initialize_global_settings
273
+ Puppet[:manifest] = ''
274
+ loader = Puppet::Environments::Directories.new(dir, [])
275
+ Puppet.override(:environments => loader) do
276
+ Puppet.override(:current_environment => loader.get('testing_generate2')) do
277
+ example.run
278
+ end
279
+ end
280
+ end
281
+
282
+ it 'fails when using procs for title patterns' do
283
+ expect {
284
+ genface.types(:format => 'pcore')
285
+ }.to exit_with(1)
286
+ end
287
+ end
224
288
  end
225
289
 
226
290
  def from_an_interactive_terminal
@@ -80,7 +80,7 @@ describe Puppet::FileSystem::Uniquefile do
80
80
  lock = File.join(dir, 'path', 'to', 'lock')
81
81
 
82
82
  expect {
83
- Puppet::FileSystem::Uniquefile.open_tmp(lock) { |tmp| }
83
+ Puppet::FileSystem::Uniquefile.new('foo', lock) { |tmp| }
84
84
  }.to raise_error(Errno::ENOENT, %r{No such file or directory - A directory component in .* does not exist or is a dangling symbolic link})
85
85
  end
86
86
 
@@ -102,6 +102,12 @@ describe Puppet::FileSystem::Uniquefile do
102
102
  expect(filename).to eq(temp_rune_utf8)
103
103
  end
104
104
 
105
+ it "preserves tilde characters" do
106
+ Puppet::FileSystem::Uniquefile.open_tmp('~foo') do |file|
107
+ expect(File.basename(file.path)).to start_with('~foo')
108
+ end
109
+ end
110
+
105
111
  context "Ruby 1.9.3 Tempfile tests" do
106
112
  # the remaining tests in this file are ported directly from the ruby 1.9.3 source,
107
113
  # since most of this file was ported from there
@@ -984,11 +984,12 @@ describe "Puppet::FileSystem" do
984
984
  end
985
985
 
986
986
  it 'preserves file ownership' do
987
- allow(Puppet::FileSystem).to receive(:lstat)
988
- .with(Puppet::FileSystem.pathname(dest))
989
- .and_return(double(uid: 1, gid: 2))
987
+ FileUtils.touch(dest)
988
+ allow(File).to receive(:lstat).and_call_original
989
+ allow(File).to receive(:lstat).with(Pathname.new(dest)).and_return(double(uid: 1, gid: 2, 'directory?': false))
990
990
 
991
- expect(FileUtils).to receive(:chown).with(1, 2, /#{dest}/)
991
+ allow(File).to receive(:chown).and_call_original
992
+ expect(FileUtils).to receive(:chown).with(1, 2, any_args)
992
993
 
993
994
  Puppet::FileSystem.replace_file(dest, 0644) { |f| f.write(content) }
994
995
  end
@@ -1163,4 +1164,33 @@ describe "Puppet::FileSystem" do
1163
1164
  expect(File.mtime(dest)).to be_within(1).of(tomorrow)
1164
1165
  end
1165
1166
  end
1167
+
1168
+ context '#chmod' do
1169
+ let(:dest) { tmpfile('abs_file') }
1170
+
1171
+ it "changes the mode given an absolute string" do
1172
+ Puppet::FileSystem.touch(dest)
1173
+ Puppet::FileSystem.chmod(0644, dest)
1174
+ expect(File.stat(dest).mode & 0777).to eq(0644)
1175
+ end
1176
+
1177
+ it "returns true if given an absolute pathname" do
1178
+ Puppet::FileSystem.touch(dest)
1179
+ Puppet::FileSystem.chmod(0644, Pathname.new(dest))
1180
+ expect(File.stat(dest).mode & 0777).to eq(0644)
1181
+ end
1182
+
1183
+ it "raises if the file doesn't exist" do
1184
+ klass = Puppet::Util::Platform.windows? ? Puppet::Error : Errno::ENOENT
1185
+ expect {
1186
+ Puppet::FileSystem.chmod(0644, dest)
1187
+ }.to raise_error(klass)
1188
+ end
1189
+
1190
+ it "raises ArgumentError if dest is invalid" do
1191
+ expect {
1192
+ Puppet::FileSystem.chmod(0644, nil)
1193
+ }.to raise_error(ArgumentError, /expected Pathname, got: 'NilClass'/)
1194
+ end
1195
+ end
1166
1196
  end
@@ -90,7 +90,7 @@ describe Puppet::Forge::ModuleRelease do
90
90
  "checksums": { },
91
91
  "version": "#{module_version}",
92
92
  "description": "Standard Library for Puppet Modules",
93
- "source": "git://github.com/puppetlabs/puppetlabs-stdlib.git",
93
+ "source": "https://github.com/puppetlabs/puppetlabs-stdlib",
94
94
  "project_page": "https://github.com/puppetlabs/puppetlabs-stdlib",
95
95
  "summary": "Puppet Module Standard Library",
96
96
  "dependencies": [
@@ -204,7 +204,7 @@ describe Puppet::Forge::ModuleRelease do
204
204
  "checksums": { },
205
205
  "version": "#{module_version}",
206
206
  "description": "Standard Library for Puppet Modules",
207
- "source": "git://github.com/puppetlabs/puppetlabs-stdlib.git",
207
+ "source": "https://github.com/puppetlabs/puppetlabs-stdlib",
208
208
  "project_page": "https://github.com/puppetlabs/puppetlabs-stdlib",
209
209
  "summary": "Puppet Module Standard Library",
210
210
  "author": "#{module_author}",
@@ -279,7 +279,7 @@ describe Puppet::Forge::ModuleRelease do
279
279
  "checksums": { },
280
280
  "version": "#{module_version}",
281
281
  "description": "Standard Library for Puppet Modules",
282
- "source": "git://github.com/puppetlabs/puppetlabs-stdlib.git",
282
+ "source": "https://github.com/puppetlabs/puppetlabs-stdlib",
283
283
  "project_page": "https://github.com/puppetlabs/puppetlabs-stdlib",
284
284
  "summary": "Puppet Module Standard Library",
285
285
  "dependencies": [