puppet 6.11.1 → 6.12.0
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.
- checksums.yaml +4 -4
- data/CODEOWNERS +1 -1
- data/Gemfile +1 -0
- data/Gemfile.lock +16 -16
- data/README.md +1 -1
- data/ext/build_defaults.yaml +1 -0
- data/ext/windows/service/daemon.rb +22 -17
- data/lib/puppet/concurrent.rb +2 -0
- data/lib/puppet/concurrent/lock.rb +16 -0
- data/lib/puppet/concurrent/synchronized.rb +15 -0
- data/lib/puppet/concurrent/thread_local_singleton.rb +14 -0
- data/lib/puppet/configurer.rb +45 -31
- data/lib/puppet/defaults.rb +42 -3
- data/lib/puppet/environments.rb +3 -0
- data/lib/puppet/error.rb +9 -1
- data/lib/puppet/forge.rb +3 -3
- data/lib/puppet/forge/errors.rb +2 -2
- data/lib/puppet/forge/repository.rb +30 -86
- data/lib/puppet/functions/camelcase.rb +2 -2
- data/lib/puppet/functions/epp.rb +4 -4
- data/lib/puppet/functions/find_file.rb +9 -9
- data/lib/puppet/functions/find_template.rb +63 -0
- data/lib/puppet/functions/inline_epp.rb +5 -5
- data/lib/puppet/http.rb +2 -0
- data/lib/puppet/http/client.rb +89 -17
- data/lib/puppet/http/resolver.rb +14 -1
- data/lib/puppet/http/resolver/server_list.rb +38 -0
- data/lib/puppet/http/resolver/settings.rb +3 -2
- data/lib/puppet/http/resolver/srv.rb +10 -4
- data/lib/puppet/http/service.rb +32 -0
- data/lib/puppet/http/service/ca.rb +11 -10
- data/lib/puppet/http/service/report.rb +40 -0
- data/lib/puppet/http/session.rb +11 -32
- data/lib/puppet/network/http/base_pool.rb +13 -0
- data/lib/puppet/node/environment.rb +13 -7
- data/lib/puppet/pal/pal_impl.rb +5 -0
- data/lib/puppet/parser/functions/epp.rb +3 -3
- data/lib/puppet/parser/functions/inline_epp.rb +5 -5
- data/lib/puppet/pops/evaluator/runtime3_support.rb +1 -1
- data/lib/puppet/pops/lookup/invocation.rb +10 -3
- data/lib/puppet/pops/model/pn_transformer.rb +5 -9
- data/lib/puppet/pops/parser/evaluating_parser.rb +3 -4
- data/lib/puppet/pops/serialization/json_path.rb +3 -3
- data/lib/puppet/pops/time/timespan.rb +3 -5
- data/lib/puppet/pops/types/string_converter.rb +6 -9
- data/lib/puppet/pops/types/type_calculator.rb +6 -10
- data/lib/puppet/pops/types/type_formatter.rb +9 -11
- data/lib/puppet/pops/types/type_parser.rb +3 -3
- data/lib/puppet/provider/package/portage.rb +3 -3
- data/lib/puppet/provider/package_targetable.rb +5 -4
- data/lib/puppet/provider/service/systemd.rb +1 -1
- data/lib/puppet/provider/user/hpux.rb +1 -1
- data/lib/puppet/runtime.rb +1 -0
- data/lib/puppet/ssl/ssl_provider.rb +20 -0
- data/lib/puppet/transaction.rb +33 -11
- data/lib/puppet/type.rb +1 -1
- data/lib/puppet/type/file/data_sync.rb +5 -1
- data/lib/puppet/type/group.rb +3 -2
- data/lib/puppet/type/user.rb +3 -2
- data/lib/puppet/util.rb +34 -11
- data/lib/puppet/util/logging.rb +30 -18
- data/lib/puppet/util/windows/adsi.rb +48 -18
- data/lib/puppet/version.rb +1 -1
- data/lib/puppet/x509/cert_provider.rb +9 -5
- data/locales/puppet.pot +155 -141
- data/man/man5/puppet.conf.5 +33 -3
- data/man/man8/puppet-agent.8 +1 -1
- data/man/man8/puppet-apply.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-config.8 +1 -1
- data/man/man8/puppet-describe.8 +1 -1
- data/man/man8/puppet-device.8 +1 -1
- data/man/man8/puppet-doc.8 +1 -1
- data/man/man8/puppet-epp.8 +1 -1
- data/man/man8/puppet-facts.8 +1 -1
- data/man/man8/puppet-filebucket.8 +1 -1
- data/man/man8/puppet-generate.8 +1 -1
- data/man/man8/puppet-help.8 +1 -1
- data/man/man8/puppet-key.8 +1 -1
- data/man/man8/puppet-lookup.8 +1 -1
- data/man/man8/puppet-man.8 +1 -1
- data/man/man8/puppet-module.8 +1 -1
- data/man/man8/puppet-node.8 +1 -1
- data/man/man8/puppet-parser.8 +1 -1
- data/man/man8/puppet-plugin.8 +1 -1
- data/man/man8/puppet-report.8 +1 -1
- data/man/man8/puppet-resource.8 +1 -1
- data/man/man8/puppet-script.8 +1 -1
- data/man/man8/puppet-ssl.8 +1 -1
- data/man/man8/puppet-status.8 +1 -1
- data/man/man8/puppet.8 +2 -2
- data/spec/fixtures/unit/forge/bacula.json +76 -0
- data/spec/integration/http/client_spec.rb +144 -0
- data/spec/integration/module_tool/forge_spec.rb +64 -0
- data/spec/lib/puppet_spec/https.rb +5 -3
- data/spec/spec_helper.rb +6 -2
- data/spec/unit/concurrent/lock_spec.rb +29 -0
- data/spec/unit/configurer_spec.rb +394 -399
- data/spec/unit/defaults_spec.rb +15 -4
- data/spec/unit/forge/errors_spec.rb +1 -1
- data/spec/unit/forge/forge_spec.rb +12 -54
- data/spec/unit/forge/module_release_spec.rb +19 -6
- data/spec/unit/forge/repository_spec.rb +63 -157
- data/spec/unit/forge_spec.rb +46 -116
- data/spec/unit/functions/find_template_spec.rb +69 -0
- data/spec/unit/http/client_spec.rb +138 -6
- data/spec/unit/http/resolver_spec.rb +49 -12
- data/spec/unit/http/service/ca_spec.rb +56 -5
- data/spec/unit/http/service/report_spec.rb +100 -0
- data/spec/unit/http/service_spec.rb +20 -0
- data/spec/unit/http/session_spec.rb +53 -18
- data/spec/unit/network/http/connection_spec.rb +0 -1
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +8 -3
- data/spec/unit/provider/package/portage_spec.rb +4 -4
- data/spec/unit/provider/package_targetable_spec.rb +60 -0
- data/spec/unit/provider/user/hpux_spec.rb +2 -2
- data/spec/unit/ssl/ssl_provider_spec.rb +71 -0
- data/spec/unit/transaction_spec.rb +46 -0
- data/spec/unit/type/file/content_spec.rb +9 -3
- data/spec/unit/util/log_spec.rb +0 -138
- data/spec/unit/util/logging_spec.rb +200 -0
- data/spec/unit/util/windows/adsi_spec.rb +51 -0
- data/spec/unit/x509/cert_provider_spec.rb +24 -4
- data/tasks/manpages.rake +1 -0
- metadata +24 -5
- 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
|
data/spec/spec_helper.rb
CHANGED
@@ -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,
|
165
|
-
stub_request(:get,
|
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
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
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(:
|
25
|
+
expect(Puppet::Util::Execution).not_to receive(:execute)
|
22
26
|
|
23
|
-
|
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
|
-
|
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(
|
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(:
|
48
|
+
expect(Puppet::Util::Execution).not_to receive(:execute)
|
45
49
|
|
46
|
-
|
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
|
-
|
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(
|
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(
|
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(
|
94
|
-
|
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(
|
99
|
-
|
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(
|
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(
|
95
|
+
expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(:ignore_terminus => true)).and_return(catalog)
|
114
96
|
|
115
|
-
expect(
|
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
|
-
|
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
|
-
|
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
|
-
|
111
|
+
configurer.run(:report => report)
|
132
112
|
expect(report.host).to eq('node_name_from_fact')
|
133
113
|
end
|
134
114
|
|
135
|
-
it "
|
136
|
-
|
137
|
-
|
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
|
-
|
119
|
+
expect(options[:report].metrics['time']['catalog_application']).to be_an_instance_of(Float)
|
156
120
|
end
|
157
121
|
|
158
|
-
it "
|
159
|
-
|
122
|
+
it "uses the provided report when applying the catalog" do
|
123
|
+
configurer.run(:report => report)
|
160
124
|
|
161
|
-
|
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(
|
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
|
-
|
133
|
+
configurer.run
|
170
134
|
end
|
171
135
|
|
172
|
-
it "
|
173
|
-
expect(
|
136
|
+
it "passes arbitrary options when applying the catalog" do
|
137
|
+
expect(catalog).to receive(:apply).with(hash_including(one: true))
|
174
138
|
|
175
|
-
|
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
|
-
|
143
|
+
configurer.run(report: report)
|
188
144
|
|
189
|
-
expect(
|
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
|
-
|
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(
|
153
|
+
expect(configurer).to receive(:send_report).with(report)
|
208
154
|
|
209
|
-
|
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(
|
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
|
-
|
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(
|
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(
|
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
|
-
|
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(
|
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(
|
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(
|
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
|
-
|
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(
|
207
|
+
expect(configurer.run).to eq(1234)
|
264
208
|
end
|
265
209
|
|
266
210
|
it "should return nil if catalog application fails" do
|
267
|
-
|
268
|
-
report
|
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(
|
220
|
+
expect(configurer).to receive(:send_report).with(report)
|
279
221
|
|
280
|
-
expect(
|
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(
|
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(
|
240
|
+
expect(configurer).to receive(:send_report).with(report)
|
301
241
|
|
302
|
-
expect(
|
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(
|
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(
|
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
|
-
|
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
|
-
|
342
|
-
expect(
|
278
|
+
expect_any_instance_of(Puppet::Resource::Catalog).not_to receive(:apply)
|
279
|
+
expect(configurer).to receive(:send_report)
|
343
280
|
|
344
|
-
expect(
|
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
|
-
|
355
|
-
expect(
|
290
|
+
expect_any_instance_of(Puppet::Resource::Catalog).to receive(:apply)
|
291
|
+
expect(configurer).to receive(:send_report)
|
356
292
|
|
357
|
-
expect(
|
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
|
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
|
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
|
-
|
382
|
-
|
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(
|
323
|
+
expect(configurer).to receive(:retrieve_catalog).and_return(catalog).twice
|
392
324
|
|
393
|
-
|
325
|
+
configurer.run
|
394
326
|
end
|
395
327
|
|
396
|
-
it "
|
397
|
-
|
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
|
-
|
331
|
+
configurer.run
|
400
332
|
|
401
|
-
expect(
|
333
|
+
expect(configurer.environment).to eq("second_env")
|
402
334
|
end
|
403
335
|
|
404
|
-
it "
|
405
|
-
|
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
|
-
|
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
|
-
|
345
|
+
configurer = Puppet::Configurer.new('aaa')
|
419
346
|
expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(transaction_uuid: 'aaa'))
|
420
|
-
|
347
|
+
configurer.run
|
421
348
|
end
|
422
349
|
|
423
350
|
it "sends the transaction uuid in a catalog request" do
|
424
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
444
|
-
|
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
|
-
|
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
|
-
|
383
|
+
|
457
384
|
expect(Puppet::Resource::Catalog.indirection).to receive(:find) do |name, options|
|
458
|
-
options[:facts].
|
459
|
-
end.and_return(
|
385
|
+
expect(options[:facts]).to be_nil
|
386
|
+
end.and_return(catalog)
|
460
387
|
|
461
|
-
|
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
|
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
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
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(
|
424
|
+
expect(report).to receive(:summary).and_return("stuff")
|
506
425
|
|
507
|
-
expect(
|
508
|
-
|
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(
|
515
|
-
|
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(
|
522
|
-
|
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(
|
529
|
-
|
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(
|
536
|
-
|
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(
|
543
|
-
|
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
|
-
|
552
|
-
|
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
|
-
|
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(
|
575
|
-
|
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
|
-
|
591
|
-
|
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
|
-
|
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
|
-
|
610
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
586
|
+
expects_cached_catalog_only(catalog)
|
677
587
|
|
678
|
-
|
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(
|
684
|
-
expect(
|
593
|
+
expects_cached_catalog_only(catalog)
|
594
|
+
expect(configurer).not_to receive(:download_plugins)
|
685
595
|
|
686
|
-
|
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(
|
692
|
-
expect(
|
601
|
+
expects_fallback_to_new_catalog(catalog)
|
602
|
+
expect(configurer).to receive(:download_plugins)
|
693
603
|
|
694
|
-
|
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(
|
608
|
+
expects_cached_catalog_only(catalog)
|
609
|
+
|
610
|
+
options = {}
|
611
|
+
configurer.run(options)
|
699
612
|
|
700
|
-
|
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
|
-
|
709
|
-
|
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(
|
623
|
+
expect(options[:report].cached_catalog_status).to eq('explicitly_requested')
|
716
624
|
end
|
717
625
|
|
718
|
-
it "should
|
719
|
-
expects_fallback_to_new_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
|
-
|
722
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
760
|
-
|
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(
|
712
|
+
expect(configurer.run).to be_nil
|
764
713
|
end
|
765
714
|
|
766
|
-
it "should
|
767
|
-
|
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(
|
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
|
-
|
780
|
-
|
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(
|
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
|
-
|
788
|
-
@agent.instance_variable_set(:@environment, 'production')
|
789
|
-
expects_cached_catalog_only(@catalog)
|
738
|
+
expects_cached_catalog_only(catalog)
|
790
739
|
|
791
|
-
expect(
|
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(
|
746
|
+
expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true)).and_return(catalog)
|
804
747
|
|
805
|
-
|
806
|
-
|
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
|
-
|
811
|
-
Puppet.
|
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
|
-
|
815
|
-
|
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
|
-
|
761
|
+
configurer.run
|
821
762
|
end
|
822
763
|
|
823
|
-
it "should log
|
824
|
-
expects_fallback_to_cached_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
|
-
|
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(
|
773
|
+
expects_fallback_to_cached_catalog(catalog)
|
832
774
|
|
833
|
-
|
834
|
-
|
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(
|
782
|
+
expects_new_catalog_only(catalog)
|
839
783
|
|
840
|
-
|
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(
|
789
|
+
expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_terminus: true)).and_return(catalog)
|
846
790
|
|
847
|
-
|
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(
|
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
|
-
|
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(
|
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
|
-
|
872
|
-
|
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(
|
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(
|
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
|
-
|
898
|
-
|
899
|
-
|
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
|
-
|
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
|
-
|
917
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
936
|
-
|
937
|
-
|
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
|
-
|
908
|
+
before :each do
|
909
|
+
apple.add_resource(resource)
|
910
|
+
banana.add_resource(resource)
|
940
911
|
end
|
941
912
|
|
942
|
-
|
943
|
-
|
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
|
-
|
946
|
-
expect(@agent.convert_catalog(catalog, 10)).to equal(ral_catalog)
|
920
|
+
configurer.run
|
947
921
|
end
|
948
922
|
|
949
|
-
it "
|
950
|
-
expect(
|
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
|
-
|
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
|
-
|
956
|
-
|
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
|
-
|
938
|
+
configurer.run(catalog: catalog)
|
959
939
|
end
|
960
940
|
|
961
|
-
it "
|
962
|
-
expect(
|
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
|
-
|
954
|
+
configurer.run
|
965
955
|
end
|
966
956
|
|
967
|
-
it "
|
968
|
-
expect(
|
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
|
-
|
962
|
+
expect(File.read(Puppet[:classfile]).chomp).to eq('settings')
|
971
963
|
end
|
972
964
|
|
973
|
-
it "
|
974
|
-
|
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
|
-
|
977
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1012
|
-
|
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
|
-
|
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
|
-
|
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] =
|
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
|
-
|
1046
|
-
|
1047
|
-
|
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
|
-
|
1055
|
-
|
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
|
-
|
1052
|
+
expect(node_request).to have_been_requested.once
|
1058
1053
|
end
|
1059
1054
|
end
|
1060
1055
|
end
|