Skip to content

Commit 500e514

Browse files
authored
Merge pull request #8733 from GabrielNagy/PUP-11201/refine-last-used-env
(PUP-11201) Refine when the last used environment is used
2 parents a64d9e3 + 8392cb6 commit 500e514

File tree

5 files changed

+172
-31
lines changed

5 files changed

+172
-31
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
test_name "Agent should use set environment after running with specified environment" do
2+
require 'puppet/acceptance/environment_utils'
3+
extend Puppet::Acceptance::EnvironmentUtils
4+
5+
tag 'audit:high',
6+
'server'
7+
8+
# Remove all traces of the last used environment
9+
teardown do
10+
agents.each do |agent|
11+
on(agent, puppet('config print lastrunfile')) do |command_result|
12+
agent.rm_rf(command_result.stdout)
13+
end
14+
end
15+
end
16+
17+
tmp_environment = mk_tmp_environment_with_teardown(master, 'special')
18+
agents.each do |agent|
19+
on(agent, "puppet agent -t --environment #{tmp_environment}") do |result|
20+
assert_match(/Info: Using environment 'special_\w+'/, result.stdout)
21+
end
22+
23+
on(agent, "puppet agent -t") do |result|
24+
assert_match(/Info: Using environment 'production'/, result.stdout)
25+
end
26+
end
27+
end
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
test_name "Agent should use the last server-specified environment if server is authoritative" do
2+
require 'puppet/acceptance/environment_utils'
3+
extend Puppet::Acceptance::EnvironmentUtils
4+
5+
tag 'audit:high',
6+
'server'
7+
8+
# Remove all traces of the last used environment
9+
teardown do
10+
agents.each do |agent|
11+
on(agent, puppet('config print lastrunfile')) do |command_result|
12+
agent.rm_rf(command_result.stdout)
13+
end
14+
end
15+
end
16+
17+
testdir = create_tmpdir_for_user(master, 'use_enc_env')
18+
19+
create_remote_file(master, "#{testdir}/enc.rb", <<END)
20+
#!#{master['privatebindir'] || '/opt/puppetlabs/puppet/bin'}/ruby
21+
puts <<YAML
22+
parameters:
23+
environment: special
24+
YAML
25+
END
26+
on(master, "chmod 755 '#{testdir}/enc.rb'")
27+
28+
apply_manifest_on(master, <<-MANIFEST, :catch_failures => true)
29+
File {
30+
ensure => directory,
31+
mode => "0770",
32+
owner => #{master.puppet['user']},
33+
group => #{master.puppet['group']},
34+
}
35+
file {
36+
'#{testdir}/environments':;
37+
'#{testdir}/environments/production':;
38+
'#{testdir}/environments/production/manifests':;
39+
'#{testdir}/environments/special/':;
40+
'#{testdir}/environments/special/manifests':;
41+
}
42+
file { '#{testdir}/environments/production/manifests/site.pp':
43+
ensure => file,
44+
mode => "0640",
45+
content => 'notify { "production environment": }',
46+
}
47+
file { '#{testdir}/environments/special/manifests/different.pp':
48+
ensure => file,
49+
mode => "0640",
50+
content => 'notify { "special environment": }',
51+
}
52+
MANIFEST
53+
54+
master_opts = {
55+
'main' => {
56+
'environmentpath' => "#{testdir}/environments",
57+
},
58+
}
59+
master_opts['master'] = {
60+
'node_terminus' => 'exec',
61+
'external_nodes' => "#{testdir}/enc.rb",
62+
} if !master.is_pe?
63+
64+
with_puppet_running_on(master, master_opts, testdir) do
65+
agents.each do |agent|
66+
run_agent_on(agent, '--no-daemonize --onetime --verbose') do |result|
67+
assert_match(/Info: Using environment 'production'/, result.stdout)
68+
assert_match(/Local environment: 'production' doesn't match server specified environment 'special', restarting agent run with environment 'special'/, result.stdout)
69+
assert_match(/Notice: special environment/, result.stdout)
70+
end
71+
72+
run_agent_on(agent, '--no-daemonize --onetime --verbose') do |result|
73+
assert_match(/Info: Using environment 'special'/, result.stdout)
74+
assert_match(/Notice: special environment/, result.stdout)
75+
end
76+
end
77+
end
78+
end

lib/puppet/configurer.rb

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ def run(options = {})
257257

258258
def run_internal(options)
259259
report = options[:report]
260+
report.initial_environment = Puppet[:environment]
260261

261262
if options[:start_time]
262263
startup_time = Time.now - options[:start_time]
@@ -296,14 +297,18 @@ def run_internal(options)
296297
configured_environment = Puppet[:environment] if Puppet.settings.set_by_config?(:environment)
297298

298299
# We only need to find out the environment to run in if we don't already have a catalog
299-
unless (cached_catalog || options[:catalog] || configured_environment)
300-
Puppet.debug(_("No environment configured, attempting to find out the last used environment"))
301-
if last_agent_environment
302-
@environment = last_agent_environment
303-
report.environment = last_agent_environment
300+
unless (cached_catalog || options[:catalog] || Puppet.settings.set_by_cli?(:environment) || Puppet[:strict_environment_mode])
301+
Puppet.debug(_("Environment not passed via CLI and no catalog was given, attempting to find out the last server-specified environment"))
302+
if last_server_specified_environment
303+
@environment = last_server_specified_environment
304+
report.environment = last_server_specified_environment
305+
else
306+
Puppet.debug(_("Could not find a usable environment in the lastrunfile. Either the file does not exist, does not have the required keys, or the values of 'initial_environment' and 'converged_environment' are identical."))
304307
end
305308
end
306309

310+
Puppet.info _("Using environment '%{env}'") % { env: @environment }
311+
307312
# This is to maintain compatibility with anyone using this class
308313
# aside from agent, apply, device.
309314
unless Puppet.lookup(:loaders) { nil }
@@ -467,21 +472,23 @@ def find_functional_server
467472
end
468473
private :find_functional_server
469474

470-
def last_agent_environment
471-
return @last_agent_environment if @last_agent_environment
475+
def last_server_specified_environment
476+
return @last_server_specified_environment if @last_server_specified_environment
472477
if Puppet::FileSystem.exist?(Puppet[:lastrunfile])
473478
summary = Puppet::Util::Yaml.safe_load_file(Puppet[:lastrunfile])
474479
return unless summary.dig('application', 'run_mode') == 'agent'
475-
@last_agent_environment = summary.dig('application', 'environment')
480+
initial_environment = summary.dig('application', 'initial_environment')
481+
converged_environment = summary.dig('application', 'converged_environment')
482+
@last_server_specified_environment = converged_environment if initial_environment != converged_environment
476483
end
477484

478-
Puppet.debug(_("Found last used environment: %{environment}") % { environment: @last_agent_environment }) if @last_agent_environment
479-
@last_agent_environment
485+
Puppet.debug(_("Found last server-specified environment: %{environment}") % { environment: @last_server_specified_environment }) if @last_server_specified_environment
486+
@last_server_specified_environment
480487
rescue => detail
481-
Puppet.debug(_("Unable to get last used environment: %{detail}") % { detail: detail })
488+
Puppet.debug(_("Could not find last server-specified environment: %{detail}") % { detail: detail })
482489
nil
483490
end
484-
private :last_agent_environment
491+
private :last_server_specified_environment
485492

486493
def send_report(report)
487494
puts report.summary if Puppet[:summarize]

lib/puppet/transaction/report.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ class Puppet::Transaction::Report
7777
# @return [String] the environment name
7878
attr_accessor :environment
7979

80+
# The name of the environment the agent initially started in
81+
# @return [String] the environment name
82+
attr_accessor :initial_environment
83+
8084
# Whether there are changes that we decided not to apply because of noop
8185
# @return [Boolean]
8286
#
@@ -384,7 +388,8 @@ def raw_summary
384388
},
385389
"application" => {
386390
"run_mode" => Puppet.run_mode.name.to_s,
387-
"environment" => environment
391+
"initial_environment" => initial_environment,
392+
"converged_environment" => environment
388393
}
389394
}
390395

spec/unit/configurer_spec.rb

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,8 +1093,7 @@ def expects_neither_new_or_cached_catalog
10931093
include PuppetSpec::Settings
10941094

10951095
describe "when the last used environment is available" do
1096-
let(:last_used_environment) { 'development' }
1097-
let(:default_environment) { 'production' }
1096+
let(:last_server_specified_environment) { 'development' }
10981097

10991098
before do
11001099
Puppet[:lastrunfile] = file_containing('last_run_summary.yaml', <<~SUMMARY)
@@ -1103,7 +1102,8 @@ def expects_neither_new_or_cached_catalog
11031102
config: 1624882680
11041103
puppet: 6.24.0
11051104
application:
1106-
environment: development
1105+
initial_environment: #{Puppet[:environment]}
1106+
converged_environment: #{last_server_specified_environment}
11071107
run_mode: agent
11081108
SUMMARY
11091109
end
@@ -1128,64 +1128,88 @@ def expects_neither_new_or_cached_catalog
11281128
expect(configurer.environment).to eq('usethis')
11291129
end
11301130

1131-
it "uses the default environment if given a catalog" do
1131+
it "uses environment from Puppet[:environment] if given a catalog" do
11321132
configurer.run(catalog: catalog)
11331133

1134-
expect(configurer.environment).to eq(default_environment)
1134+
expect(configurer.environment).to eq(Puppet[:environment])
11351135
end
11361136

1137-
it "uses the default environment if use_cached_catalog = true" do
1137+
it "uses environment from Puppet[:environment] if use_cached_catalog = true" do
11381138
Puppet[:use_cached_catalog] = true
11391139
expects_cached_catalog_only(catalog)
11401140
configurer.run
11411141

1142-
expect(configurer.environment).to eq(default_environment)
1142+
expect(configurer.environment).to eq(Puppet[:environment])
11431143
end
11441144

1145-
describe "when the environment is not configured" do
1145+
describe "when the environment is not set via CLI" do
11461146
it "uses the environment found in lastrunfile if the key exists" do
11471147
configurer.run
11481148

1149-
expect(configurer.environment).to eq(last_used_environment)
1149+
expect(configurer.environment).to eq(last_server_specified_environment)
11501150
end
11511151

1152-
it "uses the default environment if the run mode doesn't match" do
1152+
it "uses environment from Puppet[:environment] if strict_environment_mode is set" do
1153+
Puppet[:strict_environment_mode] = true
1154+
configurer.run
1155+
1156+
expect(configurer.environment).to eq(Puppet[:environment])
1157+
end
1158+
1159+
it "uses environment from Puppet[:environment] if initial_environment is the same as converged_environment" do
1160+
Puppet[:lastrunfile] = file_containing('last_run_summary.yaml', <<~SUMMARY)
1161+
---
1162+
version:
1163+
config: 1624882680
1164+
puppet: 6.24.0
1165+
application:
1166+
initial_environment: development
1167+
converged_environment: development
1168+
run_mode: agent
1169+
SUMMARY
1170+
configurer.run
1171+
1172+
expect(configurer.environment).to eq(Puppet[:environment])
1173+
end
1174+
1175+
it "uses environment from Puppet[:environment] if the run mode doesn't match" do
11531176
Puppet[:lastrunfile] = file_containing('last_run_summary.yaml', <<~SUMMARY)
11541177
---
11551178
version:
11561179
config: 1624882680
11571180
puppet: 6.24.0
11581181
application:
1159-
environment: development
1182+
initial_environment: #{Puppet[:environment]}
1183+
converged_environment: #{last_server_specified_environment}
11601184
run_mode: user
11611185
SUMMARY
11621186
configurer.run
11631187

1164-
expect(configurer.environment).to eq(default_environment)
1188+
expect(configurer.environment).to eq(Puppet[:environment])
11651189
end
11661190

1167-
it "uses the default environment if lastrunfile is invalid YAML" do
1191+
it "uses environment from Puppet[:environment] if lastrunfile is invalid YAML" do
11681192
Puppet[:lastrunfile] = file_containing('last_run_summary.yaml', <<~SUMMARY)
11691193
Key: 'this is my very very very ' +
11701194
'long string'
11711195
SUMMARY
11721196
configurer.run
11731197

1174-
expect(configurer.environment).to eq(default_environment)
1198+
expect(configurer.environment).to eq(Puppet[:environment])
11751199
end
11761200

1177-
it "uses the default environment if lastrunfile exists but is empty" do
1201+
it "uses environment from Puppet[:environment] if lastrunfile exists but is empty" do
11781202
Puppet[:lastrunfile] = file_containing('last_run_summary.yaml', '')
11791203
configurer.run
11801204

1181-
expect(configurer.environment).to eq(default_environment)
1205+
expect(configurer.environment).to eq(Puppet[:environment])
11821206
end
11831207

1184-
it "uses the default environment if the last used one cannot be found" do
1208+
it "uses environment from Puppet[:environment] if the last used one cannot be found" do
11851209
Puppet[:lastrunfile] = tmpfile('last_run_summary.yaml')
11861210
configurer.run
11871211

1188-
expect(configurer.environment).to eq(default_environment)
1212+
expect(configurer.environment).to eq(Puppet[:environment])
11891213
end
11901214
end
11911215
end

0 commit comments

Comments
 (0)