puppet 6.11.1-universal-darwin → 6.12.0-universal-darwin

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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/CODEOWNERS +1 -1
  3. data/Gemfile +1 -0
  4. data/Gemfile.lock +16 -16
  5. data/README.md +1 -1
  6. data/ext/build_defaults.yaml +1 -0
  7. data/ext/windows/service/daemon.rb +22 -17
  8. data/lib/puppet/concurrent.rb +2 -0
  9. data/lib/puppet/concurrent/lock.rb +16 -0
  10. data/lib/puppet/concurrent/synchronized.rb +15 -0
  11. data/lib/puppet/concurrent/thread_local_singleton.rb +14 -0
  12. data/lib/puppet/configurer.rb +45 -31
  13. data/lib/puppet/defaults.rb +42 -3
  14. data/lib/puppet/environments.rb +3 -0
  15. data/lib/puppet/error.rb +9 -1
  16. data/lib/puppet/forge.rb +3 -3
  17. data/lib/puppet/forge/errors.rb +2 -2
  18. data/lib/puppet/forge/repository.rb +30 -86
  19. data/lib/puppet/functions/camelcase.rb +2 -2
  20. data/lib/puppet/functions/epp.rb +4 -4
  21. data/lib/puppet/functions/find_file.rb +9 -9
  22. data/lib/puppet/functions/find_template.rb +63 -0
  23. data/lib/puppet/functions/inline_epp.rb +5 -5
  24. data/lib/puppet/http.rb +2 -0
  25. data/lib/puppet/http/client.rb +89 -17
  26. data/lib/puppet/http/resolver.rb +14 -1
  27. data/lib/puppet/http/resolver/server_list.rb +38 -0
  28. data/lib/puppet/http/resolver/settings.rb +3 -2
  29. data/lib/puppet/http/resolver/srv.rb +10 -4
  30. data/lib/puppet/http/service.rb +32 -0
  31. data/lib/puppet/http/service/ca.rb +11 -10
  32. data/lib/puppet/http/service/report.rb +40 -0
  33. data/lib/puppet/http/session.rb +11 -32
  34. data/lib/puppet/network/http/base_pool.rb +13 -0
  35. data/lib/puppet/node/environment.rb +13 -7
  36. data/lib/puppet/pal/pal_impl.rb +5 -0
  37. data/lib/puppet/parser/functions/epp.rb +3 -3
  38. data/lib/puppet/parser/functions/inline_epp.rb +5 -5
  39. data/lib/puppet/pops/evaluator/runtime3_support.rb +1 -1
  40. data/lib/puppet/pops/lookup/invocation.rb +10 -3
  41. data/lib/puppet/pops/model/pn_transformer.rb +5 -9
  42. data/lib/puppet/pops/parser/evaluating_parser.rb +3 -4
  43. data/lib/puppet/pops/serialization/json_path.rb +3 -3
  44. data/lib/puppet/pops/time/timespan.rb +3 -5
  45. data/lib/puppet/pops/types/string_converter.rb +6 -9
  46. data/lib/puppet/pops/types/type_calculator.rb +6 -10
  47. data/lib/puppet/pops/types/type_formatter.rb +9 -11
  48. data/lib/puppet/pops/types/type_parser.rb +3 -3
  49. data/lib/puppet/provider/package/portage.rb +3 -3
  50. data/lib/puppet/provider/package_targetable.rb +5 -4
  51. data/lib/puppet/provider/service/systemd.rb +1 -1
  52. data/lib/puppet/provider/user/hpux.rb +1 -1
  53. data/lib/puppet/runtime.rb +1 -0
  54. data/lib/puppet/ssl/ssl_provider.rb +20 -0
  55. data/lib/puppet/transaction.rb +33 -11
  56. data/lib/puppet/type.rb +1 -1
  57. data/lib/puppet/type/file/data_sync.rb +5 -1
  58. data/lib/puppet/type/group.rb +3 -2
  59. data/lib/puppet/type/user.rb +3 -2
  60. data/lib/puppet/util.rb +34 -11
  61. data/lib/puppet/util/logging.rb +30 -18
  62. data/lib/puppet/util/windows/adsi.rb +48 -18
  63. data/lib/puppet/version.rb +1 -1
  64. data/lib/puppet/x509/cert_provider.rb +9 -5
  65. data/locales/puppet.pot +155 -141
  66. data/man/man5/puppet.conf.5 +33 -3
  67. data/man/man8/puppet-agent.8 +1 -1
  68. data/man/man8/puppet-apply.8 +1 -1
  69. data/man/man8/puppet-catalog.8 +1 -1
  70. data/man/man8/puppet-config.8 +1 -1
  71. data/man/man8/puppet-describe.8 +1 -1
  72. data/man/man8/puppet-device.8 +1 -1
  73. data/man/man8/puppet-doc.8 +1 -1
  74. data/man/man8/puppet-epp.8 +1 -1
  75. data/man/man8/puppet-facts.8 +1 -1
  76. data/man/man8/puppet-filebucket.8 +1 -1
  77. data/man/man8/puppet-generate.8 +1 -1
  78. data/man/man8/puppet-help.8 +1 -1
  79. data/man/man8/puppet-key.8 +1 -1
  80. data/man/man8/puppet-lookup.8 +1 -1
  81. data/man/man8/puppet-man.8 +1 -1
  82. data/man/man8/puppet-module.8 +1 -1
  83. data/man/man8/puppet-node.8 +1 -1
  84. data/man/man8/puppet-parser.8 +1 -1
  85. data/man/man8/puppet-plugin.8 +1 -1
  86. data/man/man8/puppet-report.8 +1 -1
  87. data/man/man8/puppet-resource.8 +1 -1
  88. data/man/man8/puppet-script.8 +1 -1
  89. data/man/man8/puppet-ssl.8 +1 -1
  90. data/man/man8/puppet-status.8 +1 -1
  91. data/man/man8/puppet.8 +2 -2
  92. data/spec/fixtures/unit/forge/bacula.json +76 -0
  93. data/spec/integration/http/client_spec.rb +144 -0
  94. data/spec/integration/module_tool/forge_spec.rb +64 -0
  95. data/spec/lib/puppet_spec/https.rb +5 -3
  96. data/spec/spec_helper.rb +6 -2
  97. data/spec/unit/concurrent/lock_spec.rb +29 -0
  98. data/spec/unit/configurer_spec.rb +394 -399
  99. data/spec/unit/defaults_spec.rb +15 -4
  100. data/spec/unit/forge/errors_spec.rb +1 -1
  101. data/spec/unit/forge/forge_spec.rb +12 -54
  102. data/spec/unit/forge/module_release_spec.rb +19 -6
  103. data/spec/unit/forge/repository_spec.rb +63 -157
  104. data/spec/unit/forge_spec.rb +46 -116
  105. data/spec/unit/functions/find_template_spec.rb +69 -0
  106. data/spec/unit/http/client_spec.rb +138 -6
  107. data/spec/unit/http/resolver_spec.rb +49 -12
  108. data/spec/unit/http/service/ca_spec.rb +56 -5
  109. data/spec/unit/http/service/report_spec.rb +100 -0
  110. data/spec/unit/http/service_spec.rb +20 -0
  111. data/spec/unit/http/session_spec.rb +53 -18
  112. data/spec/unit/network/http/connection_spec.rb +0 -1
  113. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +8 -3
  114. data/spec/unit/provider/package/portage_spec.rb +4 -4
  115. data/spec/unit/provider/package_targetable_spec.rb +60 -0
  116. data/spec/unit/provider/user/hpux_spec.rb +2 -2
  117. data/spec/unit/ssl/ssl_provider_spec.rb +71 -0
  118. data/spec/unit/transaction_spec.rb +46 -0
  119. data/spec/unit/type/file/content_spec.rb +9 -3
  120. data/spec/unit/util/log_spec.rb +0 -138
  121. data/spec/unit/util/logging_spec.rb +200 -0
  122. data/spec/unit/util/windows/adsi_spec.rb +51 -0
  123. data/spec/unit/x509/cert_provider_spec.rb +24 -4
  124. data/tasks/manpages.rake +1 -0
  125. metadata +24 -5
  126. data/spec/lib/puppet_spec/validators.rb +0 -37
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+ require 'puppet/forge'
3
+ require 'puppet_spec/https'
4
+
5
+ describe Puppet::Forge, unless: Puppet::Util::Platform.jruby? do
6
+ include PuppetSpec::Files
7
+
8
+ before :all do
9
+ WebMock.disable!
10
+ end
11
+
12
+ after :all do
13
+ WebMock.enable!
14
+ end
15
+
16
+ before :each do
17
+ # make sure we don't take too long
18
+ Puppet[:http_connect_timeout] = '5s'
19
+ end
20
+
21
+ let(:hostname) { '127.0.0.1' }
22
+ let(:wrong_hostname) { 'localhost' }
23
+ let(:server) { PuppetSpec::HTTPSServer.new }
24
+ let(:ssl_provider) { Puppet::SSL::SSLProvider.new }
25
+
26
+ let(:http_response) do
27
+ File.read(fixtures('unit/forge/bacula.json'))
28
+ end
29
+
30
+ let(:release_response) do
31
+ releases = JSON.parse(http_response)
32
+ releases['results'] = []
33
+ JSON.dump(releases)
34
+ end
35
+
36
+ it 'fetching module release entries' do
37
+ # create a temp cacert bundle
38
+ ssl_file = tmpfile('systemstore')
39
+ File.write(ssl_file, server.ca_cert)
40
+
41
+ # override path to system cacert bundle, this must be done before
42
+ # the SSLContext is created and the call to X509::Store.set_default_paths
43
+ Puppet::Util.withenv("SSL_CERT_FILE" => ssl_file) do
44
+ response_proc = -> res {
45
+ res.status = 200
46
+ res.body = release_response
47
+ }
48
+
49
+ server.start_server(response_proc: response_proc) do |port|
50
+ forge = described_class.new("https://127.0.0.1:#{port}")
51
+ forge.fetch('bacula')
52
+ end
53
+ end
54
+ end
55
+
56
+ it 'returns a valid exception when there is an SSL verification problem' do
57
+ server.start_server do |port|
58
+ forge = described_class.new("https://#{wrong_hostname}:#{port}")
59
+ expect {
60
+ forge.fetch('mymodule')
61
+ }.to raise_error Puppet::Forge::Errors::SSLVerifyError, %r{^Unable to verify the SSL certificate at https://#{wrong_hostname}}
62
+ end
63
+ end
64
+ end
@@ -14,17 +14,19 @@ class PuppetSpec::HTTPSServer
14
14
  @config = WEBrick::Config::HTTP.dup
15
15
  end
16
16
 
17
- def handle_request(ctx, ssl)
17
+ def handle_request(ctx, ssl, response_proc)
18
18
  req = WEBrick::HTTPRequest.new(@config)
19
19
  req.parse(ssl)
20
20
 
21
21
  res = WEBrick::HTTPResponse.new(@config)
22
22
  res.status = 200
23
23
  res.body = 'OK'
24
+ response_proc.call(res) if response_proc
25
+
24
26
  res.send_response(ssl)
25
27
  end
26
28
 
27
- def start_server(ctx_proc: nil, &block)
29
+ def start_server(ctx_proc: nil, response_proc: nil, &block)
28
30
  errors = []
29
31
 
30
32
  IO.pipe {|stop_pipe_r, stop_pipe_w|
@@ -54,7 +56,7 @@ class PuppetSpec::HTTPSServer
54
56
 
55
57
  ssl = ssls.accept
56
58
  begin
57
- handle_request(ctx, ssl)
59
+ handle_request(ctx, ssl, response_proc)
58
60
  ensure
59
61
  ssl.close
60
62
  end
@@ -159,10 +159,14 @@ RSpec.configure do |config|
159
159
  Puppet::Test::TestHelper.before_each_test()
160
160
  end
161
161
 
162
+ # Facter 2 uses two versions of the GCE API, so match using regex
163
+ PUPPET_FACTER_2_GCE_URL = %r{^http://metadata/computeMetadata/v1(beta1)?}.freeze
164
+ PUPPET_FACTER_3_GCE_URL = "http://metadata.google.internal/computeMetadata/v1/?recursive=true&alt=json".freeze
165
+
162
166
  config.around :each do |example|
163
167
  # Ignore requests from Facter GCE fact in Travis
164
- stub_request(:get, "http://metadata/computeMetadata/v1beta1/?alt=json&recursive=true") # facter 2
165
- stub_request(:get, "http://metadata.google.internal/computeMetadata/v1/?recursive=true&alt=json") # facter 3
168
+ stub_request(:get, PUPPET_FACTER_2_GCE_URL)
169
+ stub_request(:get, PUPPET_FACTER_3_GCE_URL)
166
170
 
167
171
  # Enable VCR if the example is tagged with `:vcr` metadata.
168
172
  if example.metadata[:vcr]
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+ require 'puppet/concurrent/lock'
3
+
4
+ describe Puppet::Concurrent::Lock do
5
+ if Puppet::Util::Platform.jruby?
6
+ context 'on jruby' do
7
+ it 'synchronizes a block on itself' do
8
+ iterations = 100
9
+ value = 0
10
+
11
+ lock = Puppet::Concurrent::Lock.new
12
+ threads = iterations.times.collect do
13
+ Thread.new do
14
+ lock.synchronize do
15
+ tmp = (value += 1)
16
+ sleep(0.001)
17
+ # This update using tmp is designed to lose increments if threads overlap
18
+ value = tmp + 1
19
+ end
20
+ end
21
+ end
22
+ threads.each(&:join)
23
+
24
+ # In my testing this always fails by quite a lot when not synchronized (ie on mri)
25
+ expect(value).to eq(iterations * 2)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,108 +1,90 @@
1
1
  require 'spec_helper'
2
2
  require 'puppet/configurer'
3
+ require 'webmock/rspec'
3
4
 
4
5
  describe Puppet::Configurer do
5
6
  before do
6
- allow(Puppet.settings).to receive(:use).and_return(true)
7
- @agent = Puppet::Configurer.new
8
- allow(@agent).to receive(:init_storage)
9
- allow(Puppet::Util::Storage).to receive(:store)
7
+ Puppet::Node::Facts.indirection.terminus_class = :memory
8
+ Puppet::Node::Facts.indirection.save(facts)
9
+
10
10
  Puppet[:server] = "puppetmaster"
11
11
  Puppet[:report] = true
12
- end
13
12
 
14
- it "should include the Fact Handler module" do
15
- expect(Puppet::Configurer.ancestors).to be_include(Puppet::Configurer::FactHandler)
13
+ catalog.add_resource(resource)
16
14
  end
17
15
 
16
+ let(:configurer) { Puppet::Configurer.new }
17
+ let(:report) { Puppet::Transaction::Report.new }
18
+ let(:catalog) { Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote(Puppet[:environment].to_sym)) }
19
+ let(:resource) { Puppet::Resource.new(:notice, 'a') }
20
+ let(:facts) { Puppet::Node::Facts.new(Puppet[:node_name_value]) }
21
+
18
22
  describe "when executing a pre-run hook" do
19
23
  it "should do nothing if the hook is set to an empty string" do
20
24
  Puppet.settings[:prerun_command] = ""
21
- expect(Puppet::Util).not_to receive(:exec)
25
+ expect(Puppet::Util::Execution).not_to receive(:execute)
22
26
 
23
- @agent.execute_prerun_command
27
+ configurer.execute_prerun_command
24
28
  end
25
29
 
26
30
  it "should execute any pre-run command provided via the 'prerun_command' setting" do
27
31
  Puppet.settings[:prerun_command] = "/my/command"
28
32
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
29
33
 
30
- @agent.execute_prerun_command
34
+ configurer.execute_prerun_command
31
35
  end
32
36
 
33
37
  it "should fail if the command fails" do
34
38
  Puppet.settings[:prerun_command] = "/my/command"
35
39
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
36
40
 
37
- expect(@agent.execute_prerun_command).to be_falsey
41
+ expect(configurer.execute_prerun_command).to be_falsey
38
42
  end
39
43
  end
40
44
 
41
45
  describe "when executing a post-run hook" do
42
46
  it "should do nothing if the hook is set to an empty string" do
43
47
  Puppet.settings[:postrun_command] = ""
44
- expect(Puppet::Util).not_to receive(:exec)
48
+ expect(Puppet::Util::Execution).not_to receive(:execute)
45
49
 
46
- @agent.execute_postrun_command
50
+ configurer.execute_postrun_command
47
51
  end
48
52
 
49
53
  it "should execute any post-run command provided via the 'postrun_command' setting" do
50
54
  Puppet.settings[:postrun_command] = "/my/command"
51
55
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
52
56
 
53
- @agent.execute_postrun_command
57
+ configurer.execute_postrun_command
54
58
  end
55
59
 
56
60
  it "should fail if the command fails" do
57
61
  Puppet.settings[:postrun_command] = "/my/command"
58
62
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
59
63
 
60
- expect(@agent.execute_postrun_command).to be_falsey
64
+ expect(configurer.execute_postrun_command).to be_falsey
61
65
  end
62
66
  end
63
67
 
64
68
  describe "when executing a catalog run" do
65
69
  before do
66
- allow(Puppet.settings).to receive(:use).and_return(true)
67
- allow(@agent).to receive(:download_plugins)
68
- Puppet::Node::Facts.indirection.terminus_class = :memory
69
- @facts = Puppet::Node::Facts.new(Puppet[:node_name_value])
70
- Puppet::Node::Facts.indirection.save(@facts)
71
-
72
- @catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote(Puppet[:environment].to_sym))
73
- allow(@catalog).to receive(:to_ral).and_return(@catalog)
74
70
  Puppet::Resource::Catalog.indirection.terminus_class = :rest
75
- allow(Puppet::Resource::Catalog.indirection).to receive(:find).and_return(@catalog)
76
- allow(@agent).to receive(:send_report)
77
- allow(@agent).to receive(:save_last_run_summary)
78
-
79
- allow(Puppet::Util::Log).to receive(:close_all)
80
- end
81
-
82
- after :all do
83
- Puppet::Node::Facts.indirection.reset_terminus_class
84
- Puppet::Resource::Catalog.indirection.reset_terminus_class
85
- end
86
-
87
- it "should initialize storage" do
88
- expect(Puppet::Util::Storage).to receive(:load)
89
- @agent.run
71
+ allow(Puppet::Resource::Catalog.indirection).to receive(:find).and_return(catalog)
90
72
  end
91
73
 
92
74
  it "downloads plugins when told" do
93
- expect(@agent).to receive(:download_plugins)
94
- @agent.run(:pluginsync => true)
75
+ expect(configurer).to receive(:download_plugins)
76
+ configurer.run(:pluginsync => true)
95
77
  end
96
78
 
97
79
  it "does not download plugins when told" do
98
- expect(@agent).not_to receive(:download_plugins)
99
- @agent.run(:pluginsync => false)
80
+ expect(configurer).not_to receive(:download_plugins)
81
+ configurer.run(:pluginsync => false)
100
82
  end
101
83
 
102
84
  it "should carry on when it can't fetch its node definition" do
103
85
  error = Net::HTTPError.new(400, 'dummy server communication error')
104
86
  expect(Puppet::Node.indirection).to receive(:find).and_raise(error)
105
- expect(@agent.run).to eq(0)
87
+ expect(configurer.run).to eq(0)
106
88
  end
107
89
 
108
90
  it "applies a cached catalog when it can't connect to the master" do
@@ -110,200 +92,157 @@ describe Puppet::Configurer do
110
92
 
111
93
  expect(Puppet::Node.indirection).to receive(:find).and_raise(error)
112
94
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(:ignore_cache => true)).and_raise(error)
113
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(:ignore_terminus => true)).and_return(@catalog)
95
+ expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(:ignore_terminus => true)).and_return(catalog)
114
96
 
115
- expect(@agent.run).to eq(0)
97
+ expect(configurer.run).to eq(0)
116
98
  end
117
99
 
118
100
  it "should initialize a transaction report if one is not provided" do
119
- report = Puppet::Transaction::Report.new
120
101
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
121
102
 
122
- @agent.run
103
+ configurer.run
123
104
  end
124
105
 
125
106
  it "should respect node_name_fact when setting the host on a report" do
126
107
  Puppet[:node_name_fact] = 'my_name_fact'
127
- @facts.values = {'my_name_fact' => 'node_name_from_fact'}
128
-
129
- report = Puppet::Transaction::Report.new
108
+ facts.values = {'my_name_fact' => 'node_name_from_fact'}
109
+ Puppet::Node::Facts.indirection.save(facts)
130
110
 
131
- @agent.run(:report => report)
111
+ configurer.run(:report => report)
132
112
  expect(report.host).to eq('node_name_from_fact')
133
113
  end
134
114
 
135
- it "should pass the new report to the catalog" do
136
- report = Puppet::Transaction::Report.new
137
- allow(Puppet::Transaction::Report).to receive(:new).and_return(report)
138
- expect(@catalog).to receive(:apply).with(hash_including(report: report))
139
-
140
- @agent.run
141
- end
142
-
143
- it "should use the provided report if it was passed one" do
144
- report = Puppet::Transaction::Report.new
145
- expect(@catalog).to receive(:apply).with(hash_including(report: report))
146
-
147
- @agent.run(:report => report)
148
- end
149
-
150
- it "should set the report as a log destination" do
151
- report = Puppet::Transaction::Report.new
152
-
153
- expect(report).to receive(:<<).with(instance_of(Puppet::Util::Log)).at_least(:once)
115
+ it "creates a new report when applying the catalog" do
116
+ options = {}
117
+ configurer.run(options)
154
118
 
155
- @agent.run(:report => report)
119
+ expect(options[:report].metrics['time']['catalog_application']).to be_an_instance_of(Float)
156
120
  end
157
121
 
158
- it "should retrieve the catalog" do
159
- expect(@agent).to receive(:retrieve_catalog)
122
+ it "uses the provided report when applying the catalog" do
123
+ configurer.run(:report => report)
160
124
 
161
- @agent.run
125
+ expect(report.metrics['time']['catalog_application']).to be_an_instance_of(Float)
162
126
  end
163
127
 
164
128
  it "should log a failure and do nothing if no catalog can be retrieved" do
165
- expect(@agent).to receive(:retrieve_catalog).and_return(nil)
129
+ expect(configurer).to receive(:retrieve_catalog).and_return(nil)
166
130
 
167
131
  expect(Puppet).to receive(:err).with("Could not retrieve catalog; skipping run")
168
132
 
169
- @agent.run
133
+ configurer.run
170
134
  end
171
135
 
172
- it "should apply the catalog with all options to :run" do
173
- expect(@agent).to receive(:retrieve_catalog).and_return(@catalog)
136
+ it "passes arbitrary options when applying the catalog" do
137
+ expect(catalog).to receive(:apply).with(hash_including(one: true))
174
138
 
175
- expect(@catalog).to receive(:apply).with(hash_including(one: true))
176
- @agent.run :one => true
177
- end
178
-
179
- it "should accept a catalog and use it instead of retrieving a different one" do
180
- expect(@agent).not_to receive(:retrieve_catalog)
181
-
182
- expect(@catalog).to receive(:apply)
183
- @agent.run :one => true, :catalog => @catalog
139
+ configurer.run(catalog: catalog, one: true)
184
140
  end
185
141
 
186
142
  it "should benchmark how long it takes to apply the catalog" do
187
- expect(@agent).to receive(:benchmark).with(:notice, instance_of(String))
143
+ configurer.run(report: report)
188
144
 
189
- expect(@agent).to receive(:retrieve_catalog).and_return(@catalog)
190
-
191
- expect(@catalog).not_to receive(:apply) # because we're not yielding
192
- @agent.run
193
- end
194
-
195
- it "should execute post-run hooks after the run" do
196
- expect(@agent).to receive(:execute_postrun_command)
197
-
198
- @agent.run
145
+ expect(report.logs).to include(an_object_having_attributes(level: :notice, message: /Applied catalog in .* seconds/))
199
146
  end
200
147
 
201
148
  it "should create report with passed transaction_uuid and job_id" do
202
- @agent = Puppet::Configurer.new("test_tuuid", "test_jid")
203
- allow(@agent).to receive(:init_storage)
149
+ configurer = Puppet::Configurer.new("test_tuuid", "test_jid")
204
150
 
205
151
  report = Puppet::Transaction::Report.new(nil, "test", "aaaa")
206
152
  expect(Puppet::Transaction::Report).to receive(:new).with(anything, anything, 'test_tuuid', 'test_jid').and_return(report)
207
- expect(@agent).to receive(:send_report).with(report)
153
+ expect(configurer).to receive(:send_report).with(report)
208
154
 
209
- @agent.run
155
+ configurer.run
210
156
  end
211
157
 
212
158
  it "should send the report" do
213
159
  report = Puppet::Transaction::Report.new(nil, "test", "aaaa")
214
160
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
215
- expect(@agent).to receive(:send_report).with(report)
161
+ expect(configurer).to receive(:send_report).with(report)
216
162
 
217
163
  expect(report.environment).to eq("test")
218
164
  expect(report.transaction_uuid).to eq("aaaa")
219
165
 
220
- @agent.run
166
+ configurer.run
221
167
  end
222
168
 
223
169
  it "should send the transaction report even if the catalog could not be retrieved" do
224
- expect(@agent).to receive(:retrieve_catalog).and_return(nil)
170
+ expect(configurer).to receive(:retrieve_catalog).and_return(nil)
225
171
 
226
172
  report = Puppet::Transaction::Report.new(nil, "test", "aaaa")
227
173
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
228
- expect(@agent).to receive(:send_report).with(report)
174
+ expect(configurer).to receive(:send_report).with(report)
229
175
 
230
176
  expect(report.environment).to eq("test")
231
177
  expect(report.transaction_uuid).to eq("aaaa")
232
178
 
233
- @agent.run
179
+ configurer.run
234
180
  end
235
181
 
236
182
  it "should send the transaction report even if there is a failure" do
237
- expect(@agent).to receive(:retrieve_catalog).and_raise("whatever")
183
+ expect(configurer).to receive(:retrieve_catalog).and_raise("whatever")
238
184
 
239
185
  report = Puppet::Transaction::Report.new(nil, "test", "aaaa")
240
186
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
241
- expect(@agent).to receive(:send_report).with(report)
187
+ expect(configurer).to receive(:send_report).with(report)
242
188
 
243
189
  expect(report.environment).to eq("test")
244
190
  expect(report.transaction_uuid).to eq("aaaa")
245
191
 
246
- expect(@agent.run).to be_nil
192
+ expect(configurer.run).to be_nil
247
193
  end
248
194
 
249
195
  it "should remove the report as a log destination when the run is finished" do
250
- report = Puppet::Transaction::Report.new
251
196
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
252
197
 
253
- @agent.run
198
+ configurer.run
254
199
 
255
200
  expect(Puppet::Util::Log.destinations).not_to include(report)
256
201
  end
257
202
 
258
203
  it "should return the report exit_status as the result of the run" do
259
- report = Puppet::Transaction::Report.new
260
204
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
261
205
  expect(report).to receive(:exit_status).and_return(1234)
262
206
 
263
- expect(@agent.run).to eq(1234)
207
+ expect(configurer.run).to eq(1234)
264
208
  end
265
209
 
266
210
  it "should return nil if catalog application fails" do
267
- expect(@catalog).to receive(:apply).and_raise(Puppet::Error, 'One or more resource dependency cycles detected in graph')
268
- report = Puppet::Transaction::Report.new
269
- expect(@agent.run(catalog: @catalog, report: report)).to be_nil
211
+ expect_any_instance_of(Puppet::Resource::Catalog).to receive(:apply).and_raise(Puppet::Error, 'One or more resource dependency cycles detected in graph')
212
+ expect(configurer.run(catalog: catalog, report: report)).to be_nil
270
213
  end
271
214
 
272
215
  it "should send the transaction report even if the pre-run command fails" do
273
- report = Puppet::Transaction::Report.new
274
216
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
275
217
 
276
218
  Puppet.settings[:prerun_command] = "/my/command"
277
219
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
278
- expect(@agent).to receive(:send_report).with(report)
220
+ expect(configurer).to receive(:send_report).with(report)
279
221
 
280
- expect(@agent.run).to be_nil
222
+ expect(configurer.run).to be_nil
281
223
  end
282
224
 
283
225
  it "should include the pre-run command failure in the report" do
284
- report = Puppet::Transaction::Report.new
285
226
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
286
227
 
287
228
  Puppet.settings[:prerun_command] = "/my/command"
288
229
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
289
230
 
290
- expect(@agent.run).to be_nil
231
+ expect(configurer.run).to be_nil
291
232
  expect(report.logs.find { |x| x.message =~ /Could not run command from prerun_command/ }).to be
292
233
  end
293
234
 
294
235
  it "should send the transaction report even if the post-run command fails" do
295
- report = Puppet::Transaction::Report.new
296
236
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
297
237
 
298
238
  Puppet.settings[:postrun_command] = "/my/command"
299
239
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
300
- expect(@agent).to receive(:send_report).with(report)
240
+ expect(configurer).to receive(:send_report).with(report)
301
241
 
302
- expect(@agent.run).to be_nil
242
+ expect(configurer.run).to be_nil
303
243
  end
304
244
 
305
245
  it "should include the post-run command failure in the report" do
306
- report = Puppet::Transaction::Report.new
307
246
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
308
247
 
309
248
  Puppet.settings[:postrun_command] = "/my/command"
@@ -311,7 +250,7 @@ describe Puppet::Configurer do
311
250
 
312
251
  expect(report).to receive(:<<) { |log, _| expect(log.message).to match(/Could not run command from postrun_command/) }.at_least(:once)
313
252
 
314
- expect(@agent.run).to be_nil
253
+ expect(configurer.run).to be_nil
315
254
  end
316
255
 
317
256
  it "should execute post-run command even if the pre-run command fails" do
@@ -320,47 +259,42 @@ describe Puppet::Configurer do
320
259
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/precommand"]).and_raise(Puppet::ExecutionFailure, "Failed")
321
260
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/postcommand"])
322
261
 
323
- expect(@agent.run).to be_nil
262
+ expect(configurer.run).to be_nil
324
263
  end
325
264
 
326
265
  it "should finalize the report" do
327
- report = Puppet::Transaction::Report.new
328
266
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
329
267
 
330
268
  expect(report).to receive(:finalize_report)
331
- @agent.run
269
+ configurer.run
332
270
  end
333
271
 
334
272
  it "should not apply the catalog if the pre-run command fails" do
335
- report = Puppet::Transaction::Report.new
336
273
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
337
274
 
338
275
  Puppet.settings[:prerun_command] = "/my/command"
339
276
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
340
277
 
341
- expect(@catalog).not_to receive(:apply)
342
- expect(@agent).to receive(:send_report)
278
+ expect_any_instance_of(Puppet::Resource::Catalog).not_to receive(:apply)
279
+ expect(configurer).to receive(:send_report)
343
280
 
344
- expect(@agent.run).to be_nil
281
+ expect(configurer.run).to be_nil
345
282
  end
346
283
 
347
284
  it "should apply the catalog, send the report, and return nil if the post-run command fails" do
348
- report = Puppet::Transaction::Report.new
349
285
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
350
286
 
351
287
  Puppet.settings[:postrun_command] = "/my/command"
352
288
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
353
289
 
354
- expect(@catalog).to receive(:apply)
355
- expect(@agent).to receive(:send_report)
290
+ expect_any_instance_of(Puppet::Resource::Catalog).to receive(:apply)
291
+ expect(configurer).to receive(:send_report)
356
292
 
357
- expect(@agent.run).to be_nil
293
+ expect(configurer.run).to be_nil
358
294
  end
359
295
 
360
296
  it 'includes total time metrics in the report after successfully applying the catalog' do
361
- report = Puppet::Transaction::Report.new
362
- allow(@catalog).to receive(:apply).with(hash_including(report: report))
363
- @agent.run(report: report)
297
+ configurer.run(report: report)
364
298
 
365
299
  expect(report.metrics['time']).to be
366
300
  expect(report.metrics['time']['total']).to be_a_kind_of(Numeric)
@@ -370,17 +304,15 @@ describe Puppet::Configurer do
370
304
  Puppet.settings[:prerun_command] = "/my/command"
371
305
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
372
306
 
373
- report = Puppet::Transaction::Report.new
374
- @agent.run(report: report)
307
+ configurer.run(report: report)
375
308
 
376
309
  expect(report.metrics['time']).to be
377
310
  expect(report.metrics['time']['total']).to be_a_kind_of(Numeric)
378
311
  end
379
312
 
380
313
  it 'includes total time metrics in the report even if catalog retrieval fails' do
381
- report = Puppet::Transaction::Report.new
382
- allow(@agent).to receive(:prepare_and_retrieve_catalog_from_cache).and_raise
383
- @agent.run(:report => report)
314
+ allow(configurer).to receive(:prepare_and_retrieve_catalog_from_cache).and_raise
315
+ configurer.run(:report => report)
384
316
 
385
317
  expect(report.metrics['time']).to be
386
318
  expect(report.metrics['time']['total']).to be_a_kind_of(Numeric)
@@ -388,102 +320,93 @@ describe Puppet::Configurer do
388
320
 
389
321
  it "should refetch the catalog if the server specifies a new environment in the catalog" do
390
322
  catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote('second_env'))
391
- expect(@agent).to receive(:retrieve_catalog).and_return(catalog).twice
323
+ expect(configurer).to receive(:retrieve_catalog).and_return(catalog).twice
392
324
 
393
- @agent.run
325
+ configurer.run
394
326
  end
395
327
 
396
- it "should change the environment setting if the server specifies a new environment in the catalog" do
397
- allow(@catalog).to receive(:environment).and_return("second_env")
328
+ it "changes the configurer's environment if the server specifies a new environment in the catalog" do
329
+ allow_any_instance_of(Puppet::Resource::Catalog).to receive(:environment).and_return("second_env")
398
330
 
399
- @agent.run
331
+ configurer.run
400
332
 
401
- expect(@agent.environment).to eq("second_env")
333
+ expect(configurer.environment).to eq("second_env")
402
334
  end
403
335
 
404
- it "should fix the report if the server specifies a new environment in the catalog" do
405
- report = Puppet::Transaction::Report.new(nil, "test", "aaaa")
406
- expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
407
- expect(@agent).to receive(:send_report).with(report)
336
+ it "changes the report's environment if the server specifies a new environment in the catalog" do
337
+ allow_any_instance_of(Puppet::Resource::Catalog).to receive(:environment).and_return("second_env")
408
338
 
409
- allow(@catalog).to receive(:environment).and_return("second_env")
410
- allow(@agent).to receive(:retrieve_catalog).and_return(@catalog)
411
-
412
- @agent.run
339
+ configurer.run(report: report)
413
340
 
414
341
  expect(report.environment).to eq("second_env")
415
342
  end
416
343
 
417
344
  it "sends the transaction uuid in a catalog request" do
418
- @agent.instance_variable_set(:@transaction_uuid, 'aaa')
345
+ configurer = Puppet::Configurer.new('aaa')
419
346
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(transaction_uuid: 'aaa'))
420
- @agent.run
347
+ configurer.run
421
348
  end
422
349
 
423
350
  it "sends the transaction uuid in a catalog request" do
424
- @agent.instance_variable_set(:@job_id, 'aaa')
351
+ configurer = Puppet::Configurer.new('b', 'aaa')
425
352
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(job_id: 'aaa'))
426
- @agent.run
353
+ configurer.run
427
354
  end
428
355
 
429
356
  it "sets the static_catalog query param to true in a catalog request" do
430
357
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(static_catalog: true))
431
- @agent.run
358
+ configurer.run
432
359
  end
433
360
 
434
361
  it "sets the checksum_type query param to the default supported_checksum_types in a catalog request" do
435
362
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything,
436
363
  hash_including(checksum_type: 'md5.sha256.sha384.sha512.sha224'))
437
- @agent.run
364
+ configurer.run
438
365
  end
439
366
 
440
367
  it "sets the checksum_type query param to the supported_checksum_types setting in a catalog request" do
441
- # Regenerate the agent to pick up the new setting
442
368
  Puppet[:supported_checksum_types] = ['sha256']
443
- @agent = Puppet::Configurer.new
444
- allow(@agent).to receive(:init_storage)
445
- allow(@agent).to receive(:download_plugins)
446
- allow(@agent).to receive(:send_report)
447
- allow(@agent).to receive(:save_last_run_summary)
369
+ # Regenerate the agent to pick up the new setting
370
+ configurer = Puppet::Configurer.new
448
371
 
449
372
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(checksum_type: 'sha256'))
450
- @agent.run
373
+ configurer.run
451
374
  end
452
375
 
453
376
  describe "when not using a REST terminus for catalogs" do
454
377
  it "should not pass any facts when retrieving the catalog" do
378
+ # This is weird, we collect facts when constructing the node,
379
+ # but we don't send them in the indirector request. Then the compiler
380
+ # looks up the node, and collects its facts, which we could have sent
381
+ # in the first place. This seems like a bug.
455
382
  Puppet::Resource::Catalog.indirection.terminus_class = :compiler
456
- expect(@agent).not_to receive(:facts_for_uploading)
383
+
457
384
  expect(Puppet::Resource::Catalog.indirection).to receive(:find) do |name, options|
458
- options[:facts].nil?
459
- end.and_return(@catalog)
385
+ expect(options[:facts]).to be_nil
386
+ end.and_return(catalog)
460
387
 
461
- @agent.run
388
+ configurer.run
462
389
  end
463
390
  end
464
391
 
465
392
  describe "when using a REST terminus for catalogs" do
466
- it "should pass the prepared facts and the facts format as arguments when retrieving the catalog" do
393
+ it "should pass the url encoded facts and facts format as arguments when retrieving the catalog" do
467
394
  Puppet::Resource::Catalog.indirection.terminus_class = :rest
468
- # the "facts_for_uploading" are prepeared by first finding facts, and then encoding them
469
- # this mocks the "find" with a special value 12345, which is then expected back in the
470
- # call to "encode" - the encode in turn returns mocked data that is asserted as being
471
- # presented to the catalog terminus as options.
472
- #
473
- expect(@agent).to receive(:find_facts).and_return(12345)
474
- expect(@agent).to receive(:encode_facts).with(12345).and_return(:facts => "myfacts", :facts_format => :foo)
475
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(facts: "myfacts", facts_format: :foo)).and_return(@catalog)
476
-
477
- @agent.run
478
- end
479
- end
480
- end
481
395
 
482
- describe "when initialized with a transaction_uuid" do
483
- it "stores it" do
484
- expect(SecureRandom).not_to receive(:uuid)
485
- configurer = Puppet::Configurer.new('foo')
486
- expect(configurer.instance_variable_get(:@transaction_uuid) == 'foo')
396
+ facts.values = { 'foo' => 'bar' }
397
+ Puppet::Node::Facts.indirection.save(facts)
398
+
399
+ expect(
400
+ Puppet::Resource::Catalog.indirection
401
+ ).to receive(:find) do |_, options|
402
+ expect(options[:facts_format]).to eq("application/json")
403
+
404
+ unescaped = JSON.parse(CGI.unescape(options[:facts]))
405
+ expect(unescaped).to include("values" => {"foo" => "bar"})
406
+ end.and_return(catalog)
407
+
408
+ configurer.run
409
+ end
487
410
  end
488
411
  end
489
412
 
@@ -491,56 +414,52 @@ describe Puppet::Configurer do
491
414
  include PuppetSpec::Files
492
415
 
493
416
  before do
494
- allow(Puppet.settings).to receive(:use).and_return(true)
495
- @configurer = Puppet::Configurer.new
496
417
  Puppet[:lastrunfile] = tmpfile('last_run_file')
497
-
498
- @report = Puppet::Transaction::Report.new
499
418
  Puppet[:reports] = "none"
500
419
  end
501
420
 
502
421
  it "should print a report summary if configured to do so" do
503
422
  Puppet.settings[:summarize] = true
504
423
 
505
- expect(@report).to receive(:summary).and_return("stuff")
424
+ expect(report).to receive(:summary).and_return("stuff")
506
425
 
507
- expect(@configurer).to receive(:puts).with("stuff")
508
- @configurer.send_report(@report)
426
+ expect(configurer).to receive(:puts).with("stuff")
427
+ configurer.send_report(report)
509
428
  end
510
429
 
511
430
  it "should not print a report summary if not configured to do so" do
512
431
  Puppet.settings[:summarize] = false
513
432
 
514
- expect(@configurer).not_to receive(:puts)
515
- @configurer.send_report(@report)
433
+ expect(configurer).not_to receive(:puts)
434
+ configurer.send_report(report)
516
435
  end
517
436
 
518
437
  it "should save the report if reporting is enabled" do
519
438
  Puppet.settings[:report] = true
520
439
 
521
- expect(Puppet::Transaction::Report.indirection).to receive(:save).with(@report, nil, instance_of(Hash))
522
- @configurer.send_report(@report)
440
+ expect(Puppet::Transaction::Report.indirection).to receive(:save).with(report, nil, instance_of(Hash))
441
+ configurer.send_report(report)
523
442
  end
524
443
 
525
444
  it "should not save the report if reporting is disabled" do
526
445
  Puppet.settings[:report] = false
527
446
 
528
- expect(Puppet::Transaction::Report.indirection).not_to receive(:save).with(@report, nil, instance_of(Hash))
529
- @configurer.send_report(@report)
447
+ expect(Puppet::Transaction::Report.indirection).not_to receive(:save).with(report, nil, instance_of(Hash))
448
+ configurer.send_report(report)
530
449
  end
531
450
 
532
451
  it "should save the last run summary if reporting is enabled" do
533
452
  Puppet.settings[:report] = true
534
453
 
535
- expect(@configurer).to receive(:save_last_run_summary).with(@report)
536
- @configurer.send_report(@report)
454
+ expect(configurer).to receive(:save_last_run_summary).with(report)
455
+ configurer.send_report(report)
537
456
  end
538
457
 
539
458
  it "should save the last run summary if reporting is disabled" do
540
459
  Puppet.settings[:report] = false
541
460
 
542
- expect(@configurer).to receive(:save_last_run_summary).with(@report)
543
- @configurer.send_report(@report)
461
+ expect(configurer).to receive(:save_last_run_summary).with(report)
462
+ configurer.send_report(report)
544
463
  end
545
464
 
546
465
  it "should log but not fail if saving the report fails" do
@@ -548,8 +467,9 @@ describe Puppet::Configurer do
548
467
 
549
468
  expect(Puppet::Transaction::Report.indirection).to receive(:save).and_raise("whatever")
550
469
 
551
- expect(Puppet).to receive(:send_log).with(:err, 'Could not send report: whatever')
552
- @configurer.send_report(@report)
470
+ configurer.send_report(report)
471
+
472
+ expect(@logs).to include(an_object_having_attributes(level: :err, message: 'Could not send report: whatever'))
553
473
  end
554
474
  end
555
475
 
@@ -557,22 +477,17 @@ describe Puppet::Configurer do
557
477
  include PuppetSpec::Files
558
478
 
559
479
  before do
560
- allow(Puppet.settings).to receive(:use).and_return(true)
561
- @configurer = Puppet::Configurer.new
562
-
563
- @report = double('report', :raw_summary => {})
564
-
565
480
  Puppet[:lastrunfile] = tmpfile('last_run_file')
566
481
  end
567
482
 
568
483
  it "should write the last run file" do
569
- @configurer.save_last_run_summary(@report)
484
+ configurer.save_last_run_summary(report)
570
485
  expect(Puppet::FileSystem.exist?(Puppet[:lastrunfile])).to be_truthy
571
486
  end
572
487
 
573
488
  it "should write the raw summary as yaml" do
574
- expect(@report).to receive(:raw_summary).and_return("summary")
575
- @configurer.save_last_run_summary(@report)
489
+ expect(report).to receive(:raw_summary).and_return("summary")
490
+ configurer.save_last_run_summary(report)
576
491
  expect(File.read(Puppet[:lastrunfile])).to eq(YAML.dump("summary"))
577
492
  end
578
493
 
@@ -587,13 +502,14 @@ describe Puppet::Configurer do
587
502
 
588
503
  expect(Puppet::Util).to receive(:replace_file).and_yield(fh)
589
504
 
590
- expect(Puppet).to receive(:send_log).with(:err, 'Could not save last run local report: failed to do print')
591
- @configurer.save_last_run_summary(@report)
505
+ configurer.save_last_run_summary(report)
506
+
507
+ expect(@logs).to include(an_object_having_attributes(level: :err, message: 'Could not save last run local report: failed to do print'))
592
508
  end
593
509
 
594
510
  it "should create the last run file with the correct mode" do
595
511
  expect(Puppet.settings.setting(:lastrunfile)).to receive(:mode).and_return('664')
596
- @configurer.save_last_run_summary(@report)
512
+ configurer.save_last_run_summary(report)
597
513
 
598
514
  if Puppet::Util::Platform.windows?
599
515
  require 'puppet/util/windows/security'
@@ -606,26 +522,28 @@ describe Puppet::Configurer do
606
522
 
607
523
  it "should report invalid last run file permissions" do
608
524
  expect(Puppet.settings.setting(:lastrunfile)).to receive(:mode).and_return('892')
609
- expect(Puppet).to receive(:send_log).with(:err, /Could not save last run local report.*892 is invalid/)
610
- @configurer.save_last_run_summary(@report)
525
+
526
+ configurer.save_last_run_summary(report)
527
+
528
+ expect(@logs).to include(an_object_having_attributes(level: :err, message: /Could not save last run local report.*892 is invalid/))
611
529
  end
612
530
  end
613
531
 
614
532
  describe "when requesting a node" do
615
533
  it "uses the transaction uuid in the request" do
616
534
  expect(Puppet::Node.indirection).to receive(:find).with(anything, hash_including(transaction_uuid: anything)).twice
617
- @agent.run
535
+ configurer.run
618
536
  end
619
537
 
620
538
  it "sends an explicitly configured environment request" do
621
539
  expect(Puppet.settings).to receive(:set_by_config?).with(:environment).and_return(true)
622
540
  expect(Puppet::Node.indirection).to receive(:find).with(anything, hash_including(configured_environment: Puppet[:environment])).twice
623
- @agent.run
541
+ configurer.run
624
542
  end
625
543
 
626
544
  it "does not send a configured_environment when using the default" do
627
545
  expect(Puppet::Node.indirection).to receive(:find).with(anything, hash_including(configured_environment: nil)).twice
628
- @agent.run
546
+ configurer.run
629
547
  end
630
548
  end
631
549
 
@@ -656,14 +574,6 @@ describe Puppet::Configurer do
656
574
 
657
575
  describe "when retrieving a catalog" do
658
576
  before do
659
- allow(Puppet.settings).to receive(:use).and_return(true)
660
- allow(@agent).to receive(:facts_for_uploading).and_return({})
661
- allow(@agent).to receive(:download_plugins)
662
-
663
- # retrieve a catalog in the current environment, so we don't try to converge unexpectedly
664
- @catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote(Puppet[:environment].to_sym))
665
-
666
- # this is the default when using a Configurer instance
667
577
  allow(Puppet::Resource::Catalog.indirection).to receive(:terminus_class).and_return(:rest)
668
578
  end
669
579
 
@@ -673,101 +583,139 @@ describe Puppet::Configurer do
673
583
  end
674
584
 
675
585
  it "should first look in the cache for a catalog" do
676
- expects_cached_catalog_only(@catalog)
586
+ expects_cached_catalog_only(catalog)
677
587
 
678
- expect(@agent.retrieve_catalog({})).to eq(@catalog)
588
+ configurer.run
679
589
  end
680
590
 
681
591
  it "should not make a node request or pluginsync when a cached catalog is successfully retrieved" do
682
592
  expect(Puppet::Node.indirection).not_to receive(:find)
683
- expects_cached_catalog_only(@catalog)
684
- expect(@agent).not_to receive(:download_plugins)
593
+ expects_cached_catalog_only(catalog)
594
+ expect(configurer).not_to receive(:download_plugins)
685
595
 
686
- @agent.run
596
+ configurer.run
687
597
  end
688
598
 
689
599
  it "should make a node request and pluginsync when a cached catalog cannot be retrieved" do
690
600
  expect(Puppet::Node.indirection).to receive(:find).and_return(nil)
691
- expects_fallback_to_new_catalog(@catalog)
692
- expect(@agent).to receive(:download_plugins)
601
+ expects_fallback_to_new_catalog(catalog)
602
+ expect(configurer).to receive(:download_plugins)
693
603
 
694
- @agent.run
604
+ configurer.run
695
605
  end
696
606
 
697
607
  it "should set its cached_catalog_status to 'explicitly_requested'" do
698
- expects_cached_catalog_only(@catalog)
608
+ expects_cached_catalog_only(catalog)
609
+
610
+ options = {}
611
+ configurer.run(options)
699
612
 
700
- @agent.retrieve_catalog({})
701
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('explicitly_requested')
613
+ expect(options[:report].cached_catalog_status).to eq('explicitly_requested')
702
614
  end
703
615
 
704
616
  it "should set its cached_catalog_status to 'explicitly requested' if the cached catalog is from a different environment" do
705
617
  cached_catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote('second_env'))
706
618
  expects_cached_catalog_only(cached_catalog)
707
619
 
708
- @agent.retrieve_catalog({})
709
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('explicitly_requested')
710
- end
711
-
712
- it "should compile a new catalog if none is found in the cache" do
713
- expects_fallback_to_new_catalog(@catalog)
620
+ options = {}
621
+ configurer.run(options)
714
622
 
715
- expect(@agent.retrieve_catalog({})).to eq(@catalog)
623
+ expect(options[:report].cached_catalog_status).to eq('explicitly_requested')
716
624
  end
717
625
 
718
- it "should set its cached_catalog_status to 'not_used' if no catalog is found in the cache" do
719
- expects_fallback_to_new_catalog(@catalog)
626
+ it "should pluginsync and compile a new catalog if none is found in the cache" do
627
+ expects_fallback_to_new_catalog(catalog)
628
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/plugins}).to_return(:status => 404)
629
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/pluginfacts}).to_return(:status => 404)
720
630
 
721
- @agent.retrieve_catalog({})
722
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('not_used')
631
+ options = {}
632
+ configurer.run(options)
633
+
634
+ expect(options[:report].cached_catalog_status).to eq('not_used')
723
635
  end
724
636
 
725
637
  it "should not attempt to retrieve a cached catalog again if the first attempt failed" do
726
638
  expect(Puppet::Node.indirection).to receive(:find).and_return(nil)
727
639
  expects_neither_new_or_cached_catalog
728
640
 
729
- @agent.run
641
+ # after failing to use a cached catalog, we'll need to pluginsync before getting
642
+ # a new catalog, which also fails.
643
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/plugins}).to_return(:status => 404)
644
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/pluginfacts}).to_return(:status => 404)
645
+
646
+ configurer.run
730
647
  end
731
648
 
732
649
  it "should return the cached catalog when the environment doesn't match" do
733
650
  cached_catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote('second_env'))
734
651
  expects_cached_catalog_only(cached_catalog)
735
652
 
653
+ allow(Puppet).to receive(:info)
736
654
  expect(Puppet).to receive(:info).with("Using cached catalog from environment 'second_env'")
737
- expect(@agent.retrieve_catalog({})).to eq(cached_catalog)
655
+
656
+ configurer.run
657
+ end
658
+
659
+ it "applies the catalog passed as options when the catalog cache terminus is not set" do
660
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/plugins}).to_return(:status => 404)
661
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/pluginfacts}).to_return(:status => 404)
662
+
663
+ catalog.add_resource(Puppet::Resource.new('notify', 'from apply'))
664
+ configurer.run(catalog: catalog.to_ral)
665
+
666
+ # make sure cache class is not set to avoid surprises later
667
+ expect(Puppet::Resource::Catalog.indirection).to_not be_cache
668
+ expect(@logs).to include(an_object_having_attributes(level: :notice, message: /defined 'message' as 'from apply'/))
669
+ end
670
+
671
+ it "applies the cached catalog when the catalog cache terminus is set, ignoring the catalog passed as options" do
672
+ Puppet::Resource::Catalog.indirection.cache_class = :json
673
+
674
+ cached_catalog = Puppet::Resource::Catalog.new(Puppet[:node_name_value], Puppet[:environment])
675
+ cached_catalog.add_resource(Puppet::Resource.new('notify', 'from cache'))
676
+
677
+ # update cached catalog
678
+ Puppet.settings.use(:main, :agent)
679
+ path = Puppet::Resource::Catalog.indirection.cache.path(cached_catalog.name)
680
+ FileUtils.mkdir(File.dirname(path))
681
+ File.write(path, cached_catalog.render(:json))
682
+
683
+ configurer.run(catalog: catalog.to_ral)
684
+
685
+ expect(@logs).to include(an_object_having_attributes(level: :notice, message: /defined 'message' as 'from cache'/))
738
686
  end
739
687
  end
740
688
 
741
689
  describe "and strict environment mode is set" do
742
690
  before do
743
- allow(@catalog).to receive(:to_ral).and_return(@catalog)
744
- allow(@catalog).to receive(:write_class_file)
745
- allow(@catalog).to receive(:write_resource_file)
746
- allow(@agent).to receive(:send_report)
747
- allow(@agent).to receive(:save_last_run_summary)
748
691
  Puppet.settings[:strict_environment_mode] = true
749
692
  end
750
693
 
751
694
  it "should not make a node request" do
752
- expects_new_catalog_only(@catalog)
695
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/plugins}).to_return(:status => 404)
696
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/pluginfacts}).to_return(:status => 404)
697
+ expects_new_catalog_only(catalog)
698
+
753
699
  expect(Puppet::Node.indirection).not_to receive(:find)
754
700
 
755
- @agent.run
701
+ configurer.run
756
702
  end
757
703
 
758
704
  it "should return nil when the catalog's environment doesn't match the agent specified environment" do
759
- @agent.instance_variable_set(:@environment, 'second_env')
760
- expects_new_catalog_only(@catalog)
705
+ Puppet[:environment] = 'second_env'
706
+ configurer = Puppet::Configurer.new
707
+
708
+ catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote("production"))
709
+ expects_new_catalog_only(catalog)
761
710
 
762
711
  expect(Puppet).to receive(:err).with("Not using catalog because its environment 'production' does not match agent specified environment 'second_env' and strict_environment_mode is set")
763
- expect(@agent.run).to be_nil
712
+ expect(configurer.run).to be_nil
764
713
  end
765
714
 
766
- it "should not return nil when the catalog's environment matches the agent specified environment" do
767
- @agent.instance_variable_set(:@environment, 'production')
768
- expects_new_catalog_only(@catalog)
715
+ it "should return 0 when the catalog's environment matches the agent specified environment" do
716
+ expects_new_catalog_only(catalog)
769
717
 
770
- expect(@agent.run).to eq(0)
718
+ expect(configurer.run).to eq(0)
771
719
  end
772
720
 
773
721
  describe "and a cached catalog is explicitly requested" do
@@ -776,83 +724,81 @@ describe Puppet::Configurer do
776
724
  end
777
725
 
778
726
  it "should return nil when the cached catalog's environment doesn't match the agent specified environment" do
779
- @agent.instance_variable_set(:@environment, 'second_env')
780
- expects_cached_catalog_only(@catalog)
727
+ Puppet[:environment] = 'second_env'
728
+ configurer = Puppet::Configurer.new
729
+
730
+ catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote("production"))
731
+ expects_cached_catalog_only(catalog)
781
732
 
782
733
  expect(Puppet).to receive(:err).with("Not using catalog because its environment 'production' does not match agent specified environment 'second_env' and strict_environment_mode is set")
783
- expect(@agent.run).to be_nil
734
+ expect(configurer.run).to be_nil
784
735
  end
785
736
 
786
737
  it "should proceed with the cached catalog if its environment matchs the local environment" do
787
- Puppet.settings[:use_cached_catalog] = true
788
- @agent.instance_variable_set(:@environment, 'production')
789
- expects_cached_catalog_only(@catalog)
738
+ expects_cached_catalog_only(catalog)
790
739
 
791
- expect(@agent.run).to eq(0)
740
+ expect(configurer.run).to eq(0)
792
741
  end
793
742
  end
794
743
  end
795
744
 
796
- it "should use the Catalog class to get its catalog" do
797
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).and_return(@catalog)
798
-
799
- @agent.retrieve_catalog({})
800
- end
801
-
802
745
  it "should set its cached_catalog_status to 'not_used' when downloading a new catalog" do
803
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true)).and_return(@catalog)
746
+ expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true)).and_return(catalog)
804
747
 
805
- @agent.retrieve_catalog({})
806
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('not_used')
748
+ options = {}
749
+ configurer.run(options)
750
+
751
+ expect(options[:report].cached_catalog_status).to eq('not_used')
807
752
  end
808
753
 
809
754
  it "should use its node_name_value to retrieve the catalog" do
810
- allow(Facter).to receive(:value).and_return("eh")
811
- Puppet.settings[:node_name_value] = "myhost.domain.com"
812
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with("myhost.domain.com", anything).and_return(@catalog)
755
+ myhost_facts = Puppet::Node::Facts.new("myhost.domain.com")
756
+ Puppet::Node::Facts.indirection.save(myhost_facts)
813
757
 
814
- @agent.retrieve_catalog({})
815
- end
816
-
817
- it "should default to returning a catalog retrieved directly from the server, skipping the cache" do
818
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true)).and_return(@catalog)
758
+ Puppet.settings[:node_name_value] = "myhost.domain.com"
759
+ expect(Puppet::Resource::Catalog.indirection).to receive(:find).with("myhost.domain.com", anything).and_return(catalog)
819
760
 
820
- expect(@agent.retrieve_catalog({})).to eq(@catalog)
761
+ configurer.run
821
762
  end
822
763
 
823
- it "should log and return the cached catalog when no catalog can be retrieved from the server" do
824
- expects_fallback_to_cached_catalog(@catalog)
764
+ it "should log when no catalog can be retrieved from the server" do
765
+ expects_fallback_to_cached_catalog(catalog)
825
766
 
767
+ allow(Puppet).to receive(:info)
826
768
  expect(Puppet).to receive(:info).with("Using cached catalog from environment 'production'")
827
- expect(@agent.retrieve_catalog({})).to eq(@catalog)
769
+ configurer.run
828
770
  end
829
771
 
830
772
  it "should set its cached_catalog_status to 'on_failure' when no catalog can be retrieved from the server" do
831
- expects_fallback_to_cached_catalog(@catalog)
773
+ expects_fallback_to_cached_catalog(catalog)
832
774
 
833
- @agent.retrieve_catalog({})
834
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('on_failure')
775
+ options = {}
776
+ configurer.run(options)
777
+
778
+ expect(options[:report].cached_catalog_status).to eq('on_failure')
835
779
  end
836
780
 
837
781
  it "should not look in the cache for a catalog if one is returned from the server" do
838
- expects_new_catalog_only(@catalog)
782
+ expects_new_catalog_only(catalog)
839
783
 
840
- expect(@agent.retrieve_catalog({})).to eq(@catalog)
784
+ configurer.run
841
785
  end
842
786
 
843
787
  it "should return the cached catalog when retrieving the remote catalog throws an exception" do
844
788
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true)).and_raise("eh")
845
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_terminus: true)).and_return(@catalog)
789
+ expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_terminus: true)).and_return(catalog)
846
790
 
847
- expect(@agent.retrieve_catalog({})).to eq(@catalog)
791
+ configurer.run
848
792
  end
849
793
 
850
794
  it "should set its cached_catalog_status to 'on_failure' when retrieving the remote catalog throws an exception" do
851
795
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true)).and_raise("eh")
852
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_terminus: true)).and_return(@catalog)
796
+ expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_terminus: true)).and_return(catalog)
797
+
798
+ options = {}
799
+ configurer.run(options)
853
800
 
854
- @agent.retrieve_catalog({})
855
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('on_failure')
801
+ expect(options[:report].cached_catalog_status).to eq('on_failure')
856
802
  end
857
803
 
858
804
  it "should log and return nil if no catalog can be retrieved from the server and :usecacheonfailure is disabled" do
@@ -861,120 +807,173 @@ describe Puppet::Configurer do
861
807
 
862
808
  expect(Puppet).to receive(:warning).with('Not using cache on failed catalog')
863
809
 
864
- expect(@agent.retrieve_catalog({})).to be_nil
810
+ expect(configurer.run).to be_nil
865
811
  end
866
812
 
867
813
  it "should set its cached_catalog_status to 'not_used' if no catalog can be retrieved from the server and :usecacheonfailure is disabled or fails to retrieve a catalog" do
868
814
  Puppet[:usecacheonfailure] = false
869
815
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true)).and_return(nil)
870
816
 
871
- @agent.retrieve_catalog({})
872
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('not_used')
817
+ options = {}
818
+ configurer.run(options)
819
+
820
+ expect(options[:report].cached_catalog_status).to eq('not_used')
873
821
  end
874
822
 
875
823
  it "should return nil if no cached catalog is available and no catalog can be retrieved from the server" do
876
824
  expects_neither_new_or_cached_catalog
877
825
 
878
- expect(@agent.retrieve_catalog({})).to be_nil
826
+ expect(configurer.run).to be_nil
879
827
  end
880
828
 
881
829
  it "should return nil if its cached catalog environment doesn't match server-specified environment" do
882
830
  cached_catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote('second_env'))
883
- @agent.instance_variable_set(:@node_environment, 'production')
884
831
 
885
832
  expects_fallback_to_cached_catalog(cached_catalog)
886
833
 
834
+ allow(Puppet).to receive(:err)
887
835
  expect(Puppet).to receive(:err).with("Not using cached catalog because its environment 'second_env' does not match 'production'")
888
- expect(@agent.retrieve_catalog({})).to be_nil
836
+ expect(configurer.run).to be_nil
889
837
  end
890
838
 
891
839
  it "should set its cached_catalog_status to 'not_used' if the cached catalog environment doesn't match server-specified environment" do
892
840
  cached_catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote('second_env'))
893
- @agent.instance_variable_set(:@node_environment, 'production')
894
841
 
895
842
  expects_fallback_to_cached_catalog(cached_catalog)
896
843
 
897
- @agent.retrieve_catalog({})
898
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('not_used')
899
- end
900
-
901
- it "should return its cached catalog if the environment matches the server-specified environment" do
902
- cached_catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote(Puppet[:environment]))
903
- @agent.instance_variable_set(:@node_environment, cached_catalog.environment)
904
-
905
- expects_fallback_to_cached_catalog(cached_catalog)
906
-
907
- expect(@agent.retrieve_catalog({})).to eq(cached_catalog)
844
+ options = {}
845
+ configurer.run(options)
846
+ expect(options[:report].cached_catalog_status).to eq('not_used')
908
847
  end
909
848
 
910
849
  it "should set its cached_catalog_status to 'on_failure' if the cached catalog environment matches server-specified environment" do
911
- cached_catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote(Puppet[:environment]))
912
- @agent.instance_variable_set(:@node_environment, cached_catalog.environment)
913
-
914
- expects_fallback_to_cached_catalog(cached_catalog)
850
+ expects_fallback_to_cached_catalog(catalog)
915
851
 
916
- @agent.retrieve_catalog({})
917
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('on_failure')
852
+ options = {}
853
+ configurer.run(options)
854
+ expect(options[:report].cached_catalog_status).to eq('on_failure')
918
855
  end
919
856
 
920
857
  it "should not update the cached catalog in noop mode" do
921
858
  Puppet[:noop] = true
922
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true, ignore_cache_save: true)).and_return(@catalog)
923
859
 
924
- @agent.retrieve_catalog({})
860
+ stub_request(:get, %r{/puppet/v3/catalog}).to_return(:status => 200, :body => catalog.render(:json), :headers => {'Content-Type' => 'application/json'})
861
+
862
+ Puppet::Resource::Catalog.indirection.cache_class = :json
863
+ path = Puppet::Resource::Catalog.indirection.cache.path(catalog.name)
864
+
865
+ expect(File).to_not be_exist(path)
866
+ configurer.run
867
+ expect(File).to_not be_exist(path)
925
868
  end
926
869
 
927
870
  it "should update the cached catalog when not in noop mode" do
928
871
  Puppet[:noop] = false
929
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true, ignore_cache_save: false)).and_return(@catalog)
872
+ Puppet[:log_level] = 'info'
873
+
874
+ stub_request(:get, %r{/puppet/v3/catalog}).to_return(:status => 200, :body => catalog.render(:json), :headers => {'Content-Type' => 'application/json'})
875
+
876
+ Puppet::Resource::Catalog.indirection.cache_class = :json
877
+ cache_path = Puppet::Resource::Catalog.indirection.cache.path(Puppet[:node_name_value])
878
+
879
+ expect(File).to_not be_exist(cache_path)
880
+ configurer.run
881
+ expect(File).to be_exist(cache_path)
882
+
883
+ expect(@logs).to include(an_object_having_attributes(level: :info, message: "Caching catalog for #{Puppet[:node_name_value]}"))
884
+ end
885
+
886
+ it "successfully applies the catalog without a cache" do
887
+ stub_request(:get, %r{/puppet/v3/catalog}).to_return(:status => 200, :body => catalog.render(:json), :headers => {'Content-Type' => 'application/json'})
888
+
889
+ Puppet::Resource::Catalog.indirection.cache_class = nil
890
+
891
+ expect(configurer.run).to eq(0)
892
+ end
893
+
894
+ it "should not update the cached catalog when running puppet apply" do
895
+ Puppet::Resource::Catalog.indirection.cache_class = :json
896
+ path = Puppet::Resource::Catalog.indirection.cache.path(catalog.name)
930
897
 
931
- @agent.retrieve_catalog({})
898
+ expect(File).to_not be_exist(path)
899
+ configurer.run(catalog: catalog)
900
+ expect(File).to_not be_exist(path)
932
901
  end
933
902
  end
934
903
 
935
- describe "when converting the catalog" do
936
- before do
937
- allow(Puppet.settings).to receive(:use).and_return(true)
904
+ describe "when converging the environment" do
905
+ let(:apple) { Puppet::Resource::Catalog.new(Puppet[:node_name_value], Puppet::Node::Environment.remote('apple')) }
906
+ let(:banana) { Puppet::Resource::Catalog.new(Puppet[:node_name_value], Puppet::Node::Environment.remote('banana')) }
938
907
 
939
- allow(catalog).to receive(:to_ral).and_return(ral_catalog)
908
+ before :each do
909
+ apple.add_resource(resource)
910
+ banana.add_resource(resource)
940
911
  end
941
912
 
942
- let (:catalog) { Puppet::Resource::Catalog.new('tester', Puppet::Node::Environment.remote(Puppet[:environment].to_sym)) }
943
- let (:ral_catalog) { Puppet::Resource::Catalog.new('tester', Puppet::Node::Environment.remote(Puppet[:environment].to_sym)) }
913
+ it "converges after multiple attempts" do
914
+ expect(Puppet::Resource::Catalog.indirection).to receive(:find).and_return(apple, banana, banana)
915
+
916
+ allow(Puppet).to receive(:notice)
917
+ expect(Puppet).to receive(:notice).with("Local environment: 'production' doesn't match server specified environment 'apple', restarting agent run with environment 'apple'")
918
+ expect(Puppet).to receive(:notice).with("Local environment: 'apple' doesn't match server specified environment 'banana', restarting agent run with environment 'banana'")
944
919
 
945
- it "should convert the catalog to a RAL-formed catalog" do
946
- expect(@agent.convert_catalog(catalog, 10)).to equal(ral_catalog)
920
+ configurer.run
947
921
  end
948
922
 
949
- it "should finalize the catalog" do
950
- expect(ral_catalog).to receive(:finalize)
923
+ it "raises if it can't converge after 4 tries after the initial catalog request" do
924
+ expect(Puppet::Resource::Catalog.indirection).to receive(:find).and_return(apple, banana, apple, banana, apple)
951
925
 
952
- @agent.convert_catalog(catalog, 10)
926
+ configurer.run
927
+
928
+ expect(@logs).to include(an_object_having_attributes(level: :err, message: "Failed to apply catalog: Catalog environment didn't stabilize after 4 fetches, aborting run"))
953
929
  end
930
+ end
954
931
 
955
- it "should record the passed retrieval time with the RAL catalog" do
956
- expect(ral_catalog).to receive(:retrieval_duration=).with(10)
932
+ describe "when converting the catalog" do
933
+ it "converts Puppet::Resource into Puppet::Type::Notify" do
934
+ expect(configurer).to receive(:apply_catalog) do |ral, _|
935
+ expect(ral.resources).to contain(an_instance_of(Puppet::Type::Notify))
936
+ end
957
937
 
958
- @agent.convert_catalog(catalog, 10)
938
+ configurer.run(catalog: catalog)
959
939
  end
960
940
 
961
- it "should write the RAL catalog's class file" do
962
- expect(ral_catalog).to receive(:write_class_file)
941
+ it "adds default schedules" do
942
+ expect(configurer).to receive(:apply_catalog) do |ral, _|
943
+ expect(ral.resources.map(&:to_ref)).to contain(%w{Schedule[puppet] Schedule[hourly] Schedule[daily] Schedule[weekly] Schedule[monthly] Schedule[never]})
944
+ end
945
+
946
+ configurer.run
947
+ end
948
+
949
+ it "records the retrieval duration to the catalog" do
950
+ expect(configurer).to receive(:apply_catalog) do |ral, _|
951
+ expect(ral.retrieval_duration).to be_an_instance_of(Float)
952
+ end
963
953
 
964
- @agent.convert_catalog(catalog, 10)
954
+ configurer.run
965
955
  end
966
956
 
967
- it "should write the RAL catalog's resource file" do
968
- expect(ral_catalog).to receive(:write_resource_file)
957
+ it "writes the class file containing applied settings classes" do
958
+ expect(File).to_not be_exist(Puppet[:classfile])
959
+
960
+ configurer.run
969
961
 
970
- @agent.convert_catalog(catalog, 10)
962
+ expect(File.read(Puppet[:classfile]).chomp).to eq('settings')
971
963
  end
972
964
 
973
- it "should set catalog conversion time on the report" do
974
- report = Puppet::Transaction::Report.new
965
+ it "writes an empty resource file since no resources are 'managed'" do
966
+ expect(File).to_not be_exist(Puppet[:resourcefile])
975
967
 
976
- expect(report).to receive(:add_times).with(:convert_catalog, kind_of(Numeric))
977
- @agent.convert_catalog(catalog, 10, {:report => report})
968
+ configurer.run
969
+
970
+ expect(File.read(Puppet[:resourcefile]).chomp).to eq("")
971
+ end
972
+
973
+ it "adds the conversion time to the report" do
974
+ configurer.run(report: report)
975
+
976
+ expect(report.metrics['time']['convert_catalog']).to be_an_instance_of(Float)
978
977
  end
979
978
  end
980
979
 
@@ -995,66 +994,62 @@ describe Puppet::Configurer do
995
994
  describe "when attempting failover" do
996
995
  it "should not failover if server_list is not set" do
997
996
  Puppet.settings[:server_list] = []
998
- expect(@agent).not_to receive(:find_functional_server)
999
- @agent.run
997
+ configurer.run
1000
998
  end
1001
999
 
1002
1000
  it "should not failover during an apply run" do
1003
1001
  Puppet.settings[:server_list] = ["myserver:123"]
1004
- expect(@agent).not_to receive(:find_functional_server)
1005
1002
  catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote(Puppet[:environment].to_sym))
1006
- @agent.run :catalog => catalog
1003
+ configurer.run(catalog: catalog)
1007
1004
  end
1008
1005
 
1009
1006
  it "should select a server when it receives 200 OK response" do
1010
1007
  Puppet.settings[:server_list] = ["myserver:123"]
1011
- response = Net::HTTPOK.new(nil, 200, 'OK')
1012
- allow(Puppet::Network::HttpPool).to receive(:connection).with('myserver', 123, anything).and_return(double('request', get: response))
1013
- allow(@agent).to receive(:run_internal)
1008
+
1009
+ stub_request(:get, 'https://myserver:123/status/v1/simple/master').to_return(status: 200)
1014
1010
 
1015
1011
  options = {}
1016
- @agent.run(options)
1012
+ configurer.run(options)
1017
1013
  expect(options[:report].master_used).to eq('myserver:123')
1018
1014
  end
1019
1015
 
1020
- it "queries the simple status for the 'master' service" do
1021
- Puppet.settings[:server_list] = ["myserver:123"]
1022
- response = Net::HTTPOK.new(nil, 200, 'OK')
1023
- http = double('request')
1024
- expect(http).to receive(:get).with('/status/v1/simple/master').and_return(response)
1025
- allow(Puppet::Network::HttpPool).to receive(:connection).with('myserver', 123, anything).and_return(http)
1026
- allow(@agent).to receive(:run_internal)
1027
-
1028
- @agent.run
1029
- end
1030
-
1031
1016
  it "should report when a server is unavailable" do
1032
1017
  Puppet.settings[:server_list] = ["myserver:123"]
1033
- response = Net::HTTPInternalServerError.new(nil, 500, 'Internal Server Error')
1034
- allow(Puppet::Network::HttpPool).to receive(:connection).with('myserver', 123, anything).and_return(double('request', get: response))
1035
1018
 
1019
+ stub_request(:get, 'https://myserver:123/status/v1/simple/master').to_return(status: [500, "Internal Server Error"])
1020
+
1021
+ allow(Puppet).to receive(:debug)
1036
1022
  expect(Puppet).to receive(:debug).with("Puppet server myserver:123 is unavailable: 500 Internal Server Error")
1037
- expect{ @agent.run }.to raise_error(Puppet::Error, /Could not select a functional puppet master from server_list/)
1023
+
1024
+ expect {
1025
+ configurer.run
1026
+ }.to raise_error(Puppet::Error, /Could not select a functional puppet master from server_list:/)
1038
1027
  end
1039
1028
 
1040
1029
  it "should error when no servers in 'server_list' are reachable" do
1041
- Puppet.settings[:server_list] = ["myserver:123"]
1042
- error = Net::HTTPError.new(400, 'dummy server communication error')
1043
- allow(Puppet::Network::HttpPool).to receive(:connection).with('myserver', 123, anything).and_return(double('request', get: error))
1030
+ Puppet.settings[:server_list] = "myserver:123,someotherservername"
1044
1031
 
1045
- options = {}
1046
- expect{ @agent.run(options) }.to raise_error(Puppet::Error, /Could not select a functional puppet master from server_list/)
1047
- expect(options[:report].master_used).to be_nil
1032
+ stub_request(:get, 'https://myserver:123/status/v1/simple/master').to_return(status: 400)
1033
+ stub_request(:get, 'https://someotherservername:8140/status/v1/simple/master').to_return(status: 400)
1034
+
1035
+ expect{
1036
+ configurer.run
1037
+ }.to raise_error(Puppet::Error, /Could not select a functional puppet master from server_list: 'myserver:123,someotherservername'/)
1048
1038
  end
1049
1039
 
1050
1040
  it "should not make multiple node requests when the server is found" do
1051
1041
  Puppet.settings[:server_list] = ["myserver:123"]
1052
- response = Net::HTTPOK.new(nil, 200, 'OK')
1053
1042
 
1054
- expect(Puppet::Network::HttpPool).to receive(:connection).with('myserver', 123, anything).and_return(double('request', get: response))
1055
- allow(@agent).to receive(:run_internal)
1043
+ Puppet::Node.indirection.terminus_class = :rest
1044
+ Puppet::Resource::Catalog.indirection.terminus_class = :rest
1045
+
1046
+ stub_request(:get, 'https://myserver:123/status/v1/simple/master').to_return(status: 200)
1047
+ stub_request(:get, %r{https://myserver:123/puppet/v3/catalog}).to_return(status: 200)
1048
+ node_request = stub_request(:get, %r{https://myserver:123/puppet/v3/node/}).to_return(status: 200)
1049
+
1050
+ configurer.run
1056
1051
 
1057
- @agent.run
1052
+ expect(node_request).to have_been_requested.once
1058
1053
  end
1059
1054
  end
1060
1055
  end