puppet 6.25.0-x64-mingw32 → 6.27.0-x64-mingw32

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 (106) hide show
  1. checksums.yaml +4 -4
  2. data/CODEOWNERS +1 -1
  3. data/Gemfile +2 -2
  4. data/Gemfile.lock +39 -32
  5. data/lib/puppet/application/lookup.rb +74 -24
  6. data/lib/puppet/concurrent/thread_local_singleton.rb +5 -3
  7. data/lib/puppet/configurer.rb +65 -11
  8. data/lib/puppet/defaults.rb +19 -3
  9. data/lib/puppet/face/generate.rb +2 -0
  10. data/lib/puppet/file_serving/metadata.rb +3 -0
  11. data/lib/puppet/file_system/file_impl.rb +7 -7
  12. data/lib/puppet/file_system/jruby.rb +1 -1
  13. data/lib/puppet/file_system/windows.rb +4 -4
  14. data/lib/puppet/file_system.rb +1 -1
  15. data/lib/puppet/functions/next.rb +18 -1
  16. data/lib/puppet/functions/tree_each.rb +0 -1
  17. data/lib/puppet/functions/versioncmp.rb +6 -2
  18. data/lib/puppet/generate/type.rb +9 -0
  19. data/lib/puppet/http/client.rb +1 -1
  20. data/lib/puppet/http/redirector.rb +5 -0
  21. data/lib/puppet/node.rb +1 -1
  22. data/lib/puppet/parser/resource.rb +1 -1
  23. data/lib/puppet/pops/evaluator/closure.rb +7 -5
  24. data/lib/puppet/pops/evaluator/runtime3_resource_support.rb +1 -0
  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 +813 -794
  28. data/lib/puppet/pops/serialization/to_data_converter.rb +6 -18
  29. data/lib/puppet/provider/service/init.rb +5 -4
  30. data/lib/puppet/resource/catalog.rb +1 -1
  31. data/lib/puppet/resource.rb +38 -5
  32. data/lib/puppet/ssl/ssl_provider.rb +10 -7
  33. data/lib/puppet/ssl/verifier.rb +6 -0
  34. data/lib/puppet/transaction/persistence.rb +22 -12
  35. data/lib/puppet/type/exec.rb +1 -1
  36. data/lib/puppet/type/file/data_sync.rb +1 -1
  37. data/lib/puppet/type/user.rb +40 -38
  38. data/lib/puppet/util/json.rb +17 -0
  39. data/lib/puppet/util/log.rb +7 -2
  40. data/lib/puppet/util/monkey_patches.rb +6 -2
  41. data/lib/puppet/util/package.rb +25 -16
  42. data/lib/puppet/util/windows/service.rb +0 -5
  43. data/lib/puppet/util/windows.rb +3 -0
  44. data/lib/puppet/util/yaml.rb +21 -2
  45. data/lib/puppet/util.rb +1 -2
  46. data/lib/puppet/version.rb +1 -1
  47. data/lib/puppet.rb +1 -0
  48. data/locales/puppet.pot +5 -10454
  49. data/man/man5/puppet.conf.5 +21 -2
  50. data/man/man8/puppet-agent.8 +1 -1
  51. data/man/man8/puppet-apply.8 +1 -1
  52. data/man/man8/puppet-catalog.8 +1 -1
  53. data/man/man8/puppet-config.8 +1 -1
  54. data/man/man8/puppet-describe.8 +1 -1
  55. data/man/man8/puppet-device.8 +1 -1
  56. data/man/man8/puppet-doc.8 +1 -1
  57. data/man/man8/puppet-epp.8 +1 -1
  58. data/man/man8/puppet-facts.8 +1 -1
  59. data/man/man8/puppet-filebucket.8 +1 -1
  60. data/man/man8/puppet-generate.8 +1 -1
  61. data/man/man8/puppet-help.8 +1 -1
  62. data/man/man8/puppet-key.8 +1 -1
  63. data/man/man8/puppet-lookup.8 +9 -6
  64. data/man/man8/puppet-man.8 +1 -1
  65. data/man/man8/puppet-module.8 +1 -1
  66. data/man/man8/puppet-node.8 +1 -1
  67. data/man/man8/puppet-parser.8 +1 -1
  68. data/man/man8/puppet-plugin.8 +1 -1
  69. data/man/man8/puppet-report.8 +1 -1
  70. data/man/man8/puppet-resource.8 +1 -1
  71. data/man/man8/puppet-script.8 +1 -1
  72. data/man/man8/puppet-ssl.8 +1 -1
  73. data/man/man8/puppet-status.8 +1 -1
  74. data/man/man8/puppet.8 +2 -2
  75. data/spec/fixtures/integration/application/agent/cached_deferred_catalog.json +2 -1
  76. data/spec/fixtures/unit/forge/bacula.json +1 -1
  77. data/spec/integration/application/agent_spec.rb +28 -0
  78. data/spec/integration/application/lookup_spec.rb +81 -50
  79. data/spec/integration/application/resource_spec.rb +6 -2
  80. data/spec/integration/http/client_spec.rb +30 -0
  81. data/spec/integration/parser/pcore_resource_spec.rb +10 -0
  82. data/spec/shared_contexts/l10n.rb +5 -0
  83. data/spec/unit/application/lookup_spec.rb +131 -10
  84. data/spec/unit/concurrent/thread_local_singleton_spec.rb +39 -0
  85. data/spec/unit/configurer_spec.rb +197 -73
  86. data/spec/unit/face/generate_spec.rb +64 -0
  87. data/spec/unit/file_system_spec.rb +34 -4
  88. data/spec/unit/forge/module_release_spec.rb +3 -3
  89. data/spec/unit/functions/versioncmp_spec.rb +40 -4
  90. data/spec/unit/http/client_spec.rb +58 -1
  91. data/spec/unit/node_spec.rb +6 -0
  92. data/spec/unit/pops/parser/parse_containers_spec.rb +2 -2
  93. data/spec/unit/pops/serialization/to_from_hr_spec.rb +0 -58
  94. data/spec/unit/pops/validator/validator_spec.rb +5 -0
  95. data/spec/unit/provider/service/gentoo_spec.rb +6 -5
  96. data/spec/unit/provider/service/init_spec.rb +15 -9
  97. data/spec/unit/provider/service/openwrt_spec.rb +21 -29
  98. data/spec/unit/provider/service/redhat_spec.rb +3 -2
  99. data/spec/unit/resource/catalog_spec.rb +14 -1
  100. data/spec/unit/resource_spec.rb +58 -2
  101. data/spec/unit/transaction/persistence_spec.rb +51 -0
  102. data/spec/unit/type/user_spec.rb +0 -45
  103. data/spec/unit/util/json_spec.rb +126 -0
  104. data/spec/unit/util/windows_spec.rb +23 -0
  105. data/spec/unit/util/yaml_spec.rb +54 -29
  106. metadata +9 -3
@@ -77,6 +77,12 @@ describe Puppet::HTTP::Client, unless: Puppet::Util::Platform.jruby? do
77
77
  }
78
78
  }
79
79
 
80
+ let(:systemstore) do
81
+ res = tmpfile('systemstore')
82
+ File.write(res, https_server.ca_cert)
83
+ res
84
+ end
85
+
80
86
  it "mutually authenticates the connection" do
81
87
  client_context = ssl_provider.create_context(
82
88
  cacerts: [https_server.ca_cert], crls: [https_server.ca_crl],
@@ -88,6 +94,30 @@ describe Puppet::HTTP::Client, unless: Puppet::Util::Platform.jruby? do
88
94
  expect(res).to be_success
89
95
  end
90
96
  end
97
+
98
+ it "connects when the server's CA is in the system store and the connection is mutually authenticated using create_context" do
99
+ Puppet::Util.withenv("SSL_CERT_FILE" => systemstore) do
100
+ client_context = ssl_provider.create_context(
101
+ cacerts: [https_server.ca_cert], crls: [https_server.ca_crl],
102
+ client_cert: https_server.server_cert, private_key: https_server.server_key,
103
+ revocation: false, include_system_store: true
104
+ )
105
+ https_server.start_server(ctx_proc: ctx_proc) do |port|
106
+ res = client.get(URI("https://127.0.0.1:#{port}"), options: {ssl_context: client_context})
107
+ expect(res).to be_success
108
+ end
109
+ end
110
+ end
111
+
112
+ it "connects when the server's CA is in the system store and the connection is mutually authenticated uning load_context" do
113
+ Puppet::Util.withenv("SSL_CERT_FILE" => systemstore) do
114
+ client_context = ssl_provider.load_context(revocation: false, include_system_store: true)
115
+ https_server.start_server(ctx_proc: ctx_proc) do |port|
116
+ res = client.get(URI("https://127.0.0.1:#{port}"), options: {ssl_context: client_context})
117
+ expect(res).to be_success
118
+ end
119
+ end
120
+ end
91
121
  end
92
122
 
93
123
  context "with a system trust store" do
@@ -136,6 +136,16 @@ describe 'when pcore described resources types are in use' do
136
136
  expect(catalog.resource(:cap, "c")['message']).to eq('c works')
137
137
  end
138
138
 
139
+ it 'considers Pcore types to be builtin ' do
140
+ genface.types
141
+ catalog = compile_to_catalog(<<-MANIFEST)
142
+ test1 { 'a':
143
+ message => 'a works'
144
+ }
145
+ MANIFEST
146
+ expect(catalog.resource(:test1, "a").kind).to eq('compilable_type')
147
+ end
148
+
139
149
  it 'the validity of attribute names are checked' do
140
150
  genface.types
141
151
  expect do
@@ -4,7 +4,11 @@ RSpec.shared_context('l10n') do |locale|
4
4
  before :all do
5
5
  @old_locale = Locale.current
6
6
  Locale.current = locale
7
+
8
+ @old_gettext_disabled = Puppet::GettextConfig.instance_variable_get(:@gettext_disabled)
9
+ Puppet::GettextConfig.instance_variable_set(:@gettext_disabled, false)
7
10
  Puppet::GettextConfig.setup_locale
11
+ Puppet::GettextConfig.create_default_text_domain
8
12
 
9
13
  # overwrite stubs with real implementation
10
14
  ::Object.send(:remove_method, :_)
@@ -17,6 +21,7 @@ RSpec.shared_context('l10n') do |locale|
17
21
  after :all do
18
22
  Locale.current = @old_locale
19
23
 
24
+ Puppet::GettextConfig.instance_variable_set(:@gettext_disabled, @old_gettext_disabled)
20
25
  # restore stubs
21
26
  load File.expand_path(File.join(__dir__, '../../lib/puppet/gettext/stubs.rb'))
22
27
  end
@@ -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
@@ -2,14 +2,24 @@ require 'spec_helper'
2
2
  require 'puppet/configurer'
3
3
 
4
4
  describe Puppet::Configurer do
5
+ include PuppetSpec::Files
6
+
5
7
  before do
6
8
  Puppet[:server] = "puppetmaster"
7
9
  Puppet[:report] = true
8
10
 
9
11
  catalog.add_resource(resource)
10
- allow_any_instance_of(described_class).to(
11
- receive(:valid_server_environment?).and_return(true)
12
- )
12
+
13
+ Puppet[:lastrunfile] = file_containing('last_run_summary.yaml', <<~SUMMARY)
14
+ ---
15
+ version:
16
+ config: 1624882680
17
+ puppet: #{Puppet.version}
18
+ application:
19
+ initial_environment: #{Puppet[:environment]}
20
+ converged_environment: #{Puppet[:environment]}
21
+ run_mode: agent
22
+ SUMMARY
13
23
  end
14
24
 
15
25
  let(:node_name) { Puppet[:node_name_value] }
@@ -65,10 +75,44 @@ describe Puppet::Configurer do
65
75
  end
66
76
  end
67
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
+
68
109
  describe "when executing a catalog run" do
69
110
  before do
70
111
  Puppet::Resource::Catalog.indirection.terminus_class = :rest
71
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
+ )
72
116
  end
73
117
 
74
118
  it "downloads plugins when told" do
@@ -742,7 +786,7 @@ describe Puppet::Configurer do
742
786
  expect(configurer.run).to be_nil
743
787
  end
744
788
 
745
- it "should proceed with the cached catalog if its environment matchs the local environment" do
789
+ it "should proceed with the cached catalog if its environment matches the local environment" do
746
790
  expects_cached_catalog_only(catalog)
747
791
 
748
792
  expect(configurer.run).to eq(0)
@@ -1099,7 +1143,6 @@ describe Puppet::Configurer do
1099
1143
  end
1100
1144
 
1101
1145
  describe "when selecting an environment" do
1102
- include PuppetSpec::Files
1103
1146
  include PuppetSpec::Settings
1104
1147
 
1105
1148
  describe "when the last used environment is available" do
@@ -1118,118 +1161,199 @@ describe Puppet::Configurer do
1118
1161
  SUMMARY
1119
1162
  end
1120
1163
 
1121
- it "prefers the environment set via cli" do
1122
- Puppet.settings.handlearg('--environment', 'usethis')
1123
- configurer.run
1124
-
1125
- expect(configurer.environment).to eq('usethis')
1126
- end
1164
+ describe "when the use_last_environment is set to true" do
1165
+ before do
1166
+ expect(Puppet::Node.indirection).not_to receive(:find)
1167
+ .with(anything, hash_including(:ignore_cache => true, :fail_on_404 => true))
1168
+ end
1127
1169
 
1128
- it "prefers the environment set via config" do
1129
- FileUtils.mkdir_p(Puppet[:confdir])
1130
- set_puppet_conf(Puppet[:confdir], <<~CONF)
1131
- [main]
1132
- environment = usethis
1133
- CONF
1170
+ it "prefers the environment set via cli" do
1171
+ Puppet.settings.handlearg('--environment', 'usethis')
1172
+ configurer.run
1134
1173
 
1135
- Puppet.initialize_settings
1136
- configurer.run
1174
+ expect(configurer.environment).to eq('usethis')
1175
+ end
1137
1176
 
1138
- expect(configurer.environment).to eq('usethis')
1139
- end
1177
+ it "prefers the environment set via lastrunfile over config" do
1178
+ FileUtils.mkdir_p(Puppet[:confdir])
1179
+ set_puppet_conf(Puppet[:confdir], <<~CONF)
1180
+ [main]
1181
+ environment = usethis
1182
+ lastrunfile = #{Puppet[:lastrunfile]}
1183
+ CONF
1140
1184
 
1141
- it "uses environment from Puppet[:environment] if given a catalog" do
1142
- configurer.run(catalog: catalog)
1185
+ Puppet.initialize_settings
1186
+ configurer.run
1143
1187
 
1144
- expect(configurer.environment).to eq(Puppet[:environment])
1145
- end
1188
+ expect(configurer.environment).to eq(last_server_specified_environment)
1189
+ end
1146
1190
 
1147
- it "uses environment from Puppet[:environment] if use_cached_catalog = true" do
1148
- Puppet[:use_cached_catalog] = true
1149
- expects_cached_catalog_only(catalog)
1150
- configurer.run
1191
+ it "uses the environment from Puppet[:environment] if given a catalog" do
1192
+ configurer.run(catalog: catalog)
1151
1193
 
1152
- expect(configurer.environment).to eq(Puppet[:environment])
1153
- end
1194
+ expect(configurer.environment).to eq(Puppet[:environment])
1195
+ end
1154
1196
 
1155
- describe "when the environment is not set via CLI" do
1156
- it "uses the environment found in lastrunfile if the key exists" do
1197
+ it "uses the environment from Puppet[:environment] if use_cached_catalog = true" do
1198
+ Puppet[:use_cached_catalog] = true
1199
+ expects_cached_catalog_only(catalog)
1157
1200
  configurer.run
1158
1201
 
1159
- expect(configurer.environment).to eq(last_server_specified_environment)
1202
+ expect(configurer.environment).to eq(Puppet[:environment])
1160
1203
  end
1161
1204
 
1162
- it "pushes the converged environment found in lastrunfile over the existing context" do
1163
- initial_env = Puppet::Node::Environment.remote('production')
1164
- Puppet.push_context(
1165
- current_environment: initial_env,
1166
- loaders: Puppet::Pops::Loaders.new(initial_env, true))
1205
+ describe "when the environment is not set via CLI" do
1206
+ it "uses the environment found in lastrunfile if the key exists" do
1207
+ configurer.run
1208
+
1209
+ expect(configurer.environment).to eq(last_server_specified_environment)
1210
+ end
1211
+
1212
+ it "pushes the converged environment found in lastrunfile over the existing context" do
1213
+ initial_env = Puppet::Node::Environment.remote('production')
1214
+ Puppet.push_context(
1215
+ current_environment: initial_env,
1216
+ loaders: Puppet::Pops::Loaders.new(initial_env, true))
1217
+
1218
+ expect(Puppet).to receive(:push_context).with(
1219
+ hash_including(:current_environment, :loaders),
1220
+ "Local node environment #{last_server_specified_environment} for configurer transaction"
1221
+ ).once.and_call_original
1222
+
1223
+ configurer.run
1224
+ end
1225
+
1226
+ it "uses the environment from Puppet[:environment] if strict_environment_mode is set" do
1227
+ Puppet[:strict_environment_mode] = true
1228
+ configurer.run
1229
+
1230
+ expect(configurer.environment).to eq(Puppet[:environment])
1231
+ end
1232
+
1233
+ it "uses the environment from Puppet[:environment] if initial_environment is the same as converged_environment" do
1234
+ Puppet[:lastrunfile] = file_containing('last_run_summary.yaml', <<~SUMMARY)
1235
+ ---
1236
+ version:
1237
+ config: 1624882680
1238
+ puppet: 6.24.0
1239
+ application:
1240
+ initial_environment: development
1241
+ converged_environment: development
1242
+ run_mode: agent
1243
+ SUMMARY
1244
+ configurer.run
1245
+
1246
+ expect(configurer.environment).to eq(Puppet[:environment])
1247
+ end
1248
+ end
1249
+ end
1250
+
1251
+ describe "when the use_last_environment setting is set to false" do
1252
+ let(:node_environment) { Puppet::Node::Environment.remote(:salam) }
1253
+ let(:node) { Puppet::Node.new(Puppet[:node_name_value]) }
1167
1254
 
1168
- expect(Puppet).to receive(:push_context).with(
1169
- hash_including(:current_environment, :loaders),
1170
- "Local node environment #{last_server_specified_environment} for configurer transaction"
1171
- ).once.and_call_original
1255
+ before do
1256
+ Puppet[:use_last_environment] = false
1257
+ node.environment = node_environment
1258
+
1259
+ allow(Puppet::Node.indirection).to receive(:find)
1260
+ allow(Puppet::Node.indirection).to receive(:find)
1261
+ .with(anything, hash_including(:ignore_cache => true, :fail_on_404 => true))
1262
+ .and_return(node)
1263
+ end
1264
+
1265
+ it "does a node request" do
1266
+ expect(Puppet::Node.indirection).to receive(:find)
1267
+ .with(anything, hash_including(:ignore_cache => true, :fail_on_404 => true))
1172
1268
 
1173
1269
  configurer.run
1174
1270
  end
1175
1271
 
1176
- it "uses environment from Puppet[:environment] if strict_environment_mode is set" do
1177
- Puppet[:strict_environment_mode] = true
1272
+ it "uses the node environment from the node request" do
1178
1273
  configurer.run
1179
1274
 
1180
- expect(configurer.environment).to eq(Puppet[:environment])
1275
+ expect(configurer.environment).to eq(node_environment.name.to_s)
1181
1276
  end
1277
+ end
1278
+ end
1182
1279
 
1183
- it "uses environment from Puppet[:environment] if initial_environment is the same as converged_environment" do
1280
+ describe "when the last used environment is not available" do
1281
+ describe "when the node request succeeds" do
1282
+ let(:node_environment) { Puppet::Node::Environment.remote(:salam) }
1283
+ let(:node) { Puppet::Node.new(Puppet[:node_name_value]) }
1284
+ let(:last_server_specified_environment) { 'development' }
1285
+
1286
+ before do
1287
+ node.environment = node_environment
1288
+
1289
+ allow(Puppet::Node.indirection).to receive(:find)
1290
+ allow(Puppet::Node.indirection).to receive(:find)
1291
+ .with(anything, hash_including(:ignore_cache => true, :fail_on_404 => true))
1292
+ .and_return(node)
1293
+ end
1294
+
1295
+ it "uses the environment from the node request if the run mode doesn't match" do
1184
1296
  Puppet[:lastrunfile] = file_containing('last_run_summary.yaml', <<~SUMMARY)
1185
- ---
1186
- version:
1187
- config: 1624882680
1188
- puppet: 6.24.0
1189
- application:
1190
- initial_environment: development
1191
- converged_environment: development
1192
- run_mode: agent
1297
+ ---
1298
+ version:
1299
+ config: 1624882680
1300
+ puppet: 6.24.0
1301
+ application:
1302
+ initial_environment: #{Puppet[:environment]}
1303
+ converged_environment: #{last_server_specified_environment}
1304
+ run_mode: user
1193
1305
  SUMMARY
1194
1306
  configurer.run
1195
1307
 
1196
- expect(configurer.environment).to eq(Puppet[:environment])
1308
+ expect(configurer.environment).to eq(node_environment.name.to_s)
1197
1309
  end
1198
1310
 
1199
- it "uses environment from Puppet[:environment] if the run mode doesn't match" do
1311
+ it "uses the environment from the node request if lastrunfile does not contain the expected keys" do
1200
1312
  Puppet[:lastrunfile] = file_containing('last_run_summary.yaml', <<~SUMMARY)
1201
- ---
1202
- version:
1203
- config: 1624882680
1204
- puppet: 6.24.0
1205
- application:
1206
- initial_environment: #{Puppet[:environment]}
1207
- converged_environment: #{last_server_specified_environment}
1208
- run_mode: user
1313
+ ---
1314
+ version:
1315
+ config: 1624882680
1316
+ puppet: 6.24.0
1209
1317
  SUMMARY
1210
1318
  configurer.run
1211
1319
 
1212
- expect(configurer.environment).to eq(Puppet[:environment])
1320
+ expect(configurer.environment).to eq(node_environment.name.to_s)
1213
1321
  end
1214
1322
 
1215
- it "uses environment from Puppet[:environment] if lastrunfile is invalid YAML" do
1323
+ it "uses the environment from the node request if lastrunfile is invalid YAML" do
1216
1324
  Puppet[:lastrunfile] = file_containing('last_run_summary.yaml', <<~SUMMARY)
1217
- Key: 'this is my very very very ' +
1218
- 'long string'
1325
+ Key: 'this is my very very very ' +
1326
+ 'long string'
1219
1327
  SUMMARY
1220
1328
  configurer.run
1221
1329
 
1222
- expect(configurer.environment).to eq(Puppet[:environment])
1330
+ expect(configurer.environment).to eq(node_environment.name.to_s)
1223
1331
  end
1224
1332
 
1225
- it "uses environment from Puppet[:environment] if lastrunfile exists but is empty" do
1333
+ it "uses the environment from the node request if lastrunfile exists but is empty" do
1226
1334
  Puppet[:lastrunfile] = file_containing('last_run_summary.yaml', '')
1227
1335
  configurer.run
1228
1336
 
1229
- expect(configurer.environment).to eq(Puppet[:environment])
1337
+ expect(configurer.environment).to eq(node_environment.name.to_s)
1338
+ end
1339
+
1340
+ it "uses the environment from the node request if the last used one cannot be found" do
1341
+ Puppet[:lastrunfile] = tmpfile('last_run_summary.yaml')
1342
+ configurer.run
1343
+
1344
+ expect(configurer.environment).to eq(node_environment.name.to_s)
1345
+ end
1346
+ end
1347
+
1348
+ describe "when the node request fails" do
1349
+ before do
1350
+ allow(Puppet::Node.indirection).to receive(:find).and_call_original
1351
+ allow(Puppet::Node.indirection).to receive(:find)
1352
+ .with(anything, hash_including(:ignore_cache => true, :fail_on_404 => true))
1353
+ .and_raise(Puppet::Error)
1230
1354
  end
1231
1355
 
1232
- it "uses environment from Puppet[:environment] if the last used one cannot be found" do
1356
+ it "uses the environment from Puppet[:environment] if the last used one cannot be found" do
1233
1357
  Puppet[:lastrunfile] = tmpfile('last_run_summary.yaml')
1234
1358
  configurer.run
1235
1359