Skip to content

Commit 5653b66

Browse files
authored
Merge pull request #101 from puppetlabs/upgrade-from-2018
Upgrade from 2018
2 parents b4439a0 + 9af145a commit 5653b66

File tree

8 files changed

+183
-69
lines changed

8 files changed

+183
-69
lines changed

documentation/upgrade.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,10 @@ The following steps apply _only_ if upgrading from 2019.5 or older
123123
**Phase 4: resume puppet service**
124124

125125
* Ensure the `puppet` service on all PE infrastructure nodes is running again
126+
127+
## Upgrade from 2018.1
128+
129+
To upgrade to PE 2019.7 or newer from PE 2018.1:
130+
131+
1. Run the peadm::convert plan with `configure_node_groups = false`
132+
2. Run the peadm::upgrade plan

manifests/setup/convert_pe2018.pp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# @summary Defines configuration needed for converting PE 2018
2+
#
3+
class peadm::setup::convert_pe2018 {
4+
5+
# This is needed so that compiler certs can be signed. It's included by
6+
# default in 2019.7 and newer, but isn't present in 2018.1. It would be
7+
# preferable to use the hocon_setting resource, but we can't because it
8+
# requires a gem not present by default. It would be preferable to use the
9+
# pe_hocon_setting resource, but we can't because there's no Forge module
10+
# that provides it for Bolt to use. So this is what we are reduced to.
11+
$caconf = @(EOF)
12+
# CA-related settings
13+
certificate-authority: {
14+
allow-subject-alt-names: true
15+
allow-authorization-extensions: true
16+
}
17+
| EOF
18+
19+
file { '/etc/puppetlabs/puppetserver/conf.d/ca.conf':
20+
ensure => file,
21+
content => $caconf,
22+
notify => Service['pe-puppetserver'],
23+
}
24+
25+
service { 'pe-puppetserver': }
26+
}

metadata.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,22 @@
3333
{
3434
"operatingsystem": "RedHat",
3535
"operatingsystemrelease": [
36-
"7"
36+
"7",
37+
"8"
3738
]
3839
},
3940
{
4041
"operatingsystem": "CentOS",
4142
"operatingsystemrelease": [
42-
"7"
43+
"7",
44+
"8"
4345
]
4446
},
4547
{
4648
"operatingsystem": "Ubuntu",
4749
"operatingsystemrelease": [
48-
"18.04"
50+
"18.04",
51+
"20.04"
4952
]
5053
}
5154
],

plans/convert.pp

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
# Common Configuration
1414
String $compiler_pool_address = $master_host,
1515
Array[String] $dns_alt_names = [ ],
16+
17+
# Options
18+
Boolean $configure_node_groups = true,
1619
) {
1720
# TODO: read and validate convertable PE version
1821

@@ -40,6 +43,11 @@
4043
$compiler_hosts,
4144
)
4245

46+
# Know what version of PE the current targets are
47+
$pe_version = run_task('peadm::read_file', $master_target,
48+
path => '/opt/puppetlabs/server/pe_version',
49+
)[0][content].chomp
50+
4351
# Get trusted fact information for all compilers. Use peadm::target_name() as
4452
# the hash key because the apply block below will break trying to parse the
4553
# $compiler_extensions variable if it has Target-type hash keys.
@@ -71,6 +79,12 @@
7179
$compiler_b_targets = []
7280
}
7381

82+
if $pe_version =~ /^2018/ {
83+
apply($master_target) {
84+
include peadm::setup::convert_pe2018
85+
}
86+
}
87+
7488
# Modify csr_attributes.yaml and insert the peadm-specific OIDs to identify
7589
# each server's role and availability group
7690

@@ -82,6 +96,14 @@
8296
},
8397
)
8498

99+
# If the orchestrator is in use, get certs fully straightened up before
100+
# proceeding
101+
if $all_targets.any |$target| { $target.protocol == 'pcp' } {
102+
run_task('peadm::puppet_runonce', $master_target)
103+
peadm::wait_until_service_ready('orchestrator-service', $master_target)
104+
wait_until_available($all_targets, wait_time => 120)
105+
}
106+
85107
run_plan('peadm::util::add_cert_extensions', $master_replica_target,
86108
master_host => $master_target,
87109
extensions => {
@@ -126,18 +148,20 @@
126148

127149
# Create the necessary node groups in the console
128150

129-
apply($master_target) {
130-
class { 'peadm::setup::node_manager_yaml':
131-
master_host => $master_target.peadm::target_name(),
132-
}
151+
if $configure_node_groups {
152+
apply($master_target) {
153+
class { 'peadm::setup::node_manager_yaml':
154+
master_host => $master_target.peadm::target_name(),
155+
}
133156

134-
class { 'peadm::setup::node_manager':
135-
master_host => $master_target.peadm::target_name(),
136-
master_replica_host => $master_replica_target.peadm::target_name(),
137-
puppetdb_database_host => $puppetdb_database_target.peadm::target_name(),
138-
puppetdb_database_replica_host => $puppetdb_database_replica_target.peadm::target_name(),
139-
compiler_pool_address => $compiler_pool_address,
140-
require => Class['peadm::setup::node_manager_yaml'],
157+
class { 'peadm::setup::node_manager':
158+
master_host => $master_target.peadm::target_name(),
159+
master_replica_host => $master_replica_target.peadm::target_name(),
160+
puppetdb_database_host => $puppetdb_database_target.peadm::target_name(),
161+
puppetdb_database_replica_host => $puppetdb_database_replica_target.peadm::target_name(),
162+
compiler_pool_address => $compiler_pool_address,
163+
require => Class['peadm::setup::node_manager_yaml'],
164+
}
141165
}
142166
}
143167

plans/upgrade.pp

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@
6666
).first['content']
6767

6868
# Ensure needed trusted facts are available
69-
if $cert_extensions.any |$t,$ext| { $ext[peadm::oid('peadm_role')] == undef } {
69+
if $cert_extensions.any |$_,$cert| {
70+
[peadm::oid('peadm_role'), 'pp_auth_role'].all |$ext| { $cert[$ext] == undef }
71+
} {
7072
fail_plan(@(HEREDOC/L))
7173
Required trusted facts are not present; upgrade cannot be completed. If \
7274
this infrastructure was provisioned with an old version of peadm, you may \
@@ -114,21 +116,18 @@
114116
)
115117
}
116118

117-
# Shut down Puppet on all infra targets
118-
run_task('service', $all_targets,
119-
action => 'stop',
120-
name => 'puppet',
121-
)
119+
# Shut down Puppet on all infra targets. Avoid using the built-in service
120+
# task for idempotency reasons. When the orchestrator has been upgraded but
121+
# not all pxp-agents have, the built-in service task does not work over pcp.
122+
run_command('systemctl stop puppet', $all_targets)
122123

123124
###########################################################################
124125
# UPGRADE MASTER SIDE
125126
###########################################################################
126127

127-
# Shut down PuppetDB on CMs that use the PM's PDB PG
128-
run_task('service', $compiler_m1_targets,
129-
action => 'stop',
130-
name => 'pe-puppetdb',
131-
)
128+
# Shut down PuppetDB on CMs that use the PM's PDB PG. Use run_command instead
129+
# of run_task(service, ...) so that upgrading from 2018.1 works over PCP.
130+
run_command('systemctl stop pe-puppetdb', $compiler_m1_targets)
132131

133132
run_task('peadm::pe_install', $puppetdb_database_target,
134133
tarball => $upload_tarball_path,
@@ -160,6 +159,31 @@
160159
wait_until_available($all_targets, wait_time => 120)
161160
}
162161

162+
# If necessary, add missing cert extensions to compilers
163+
run_plan('peadm::util::add_cert_extensions', $convert_targets,
164+
master_host => $master_target,
165+
extensions => {
166+
'pp_auth_role' => 'pe_compiler',
167+
},
168+
)
169+
170+
# Update classification. This needs to be done now because if we don't, and
171+
# the PE Compiler node groups are wrong, then the compilers won't be able to
172+
# successfully classify and update
173+
apply($master_target) {
174+
class { 'peadm::setup::node_manager_yaml':
175+
master_host => $master_target.peadm::target_name(),
176+
}
177+
178+
class { 'peadm::setup::node_manager':
179+
master_host => $master_target.peadm::target_name(),
180+
master_replica_host => $master_replica_target.peadm::target_name(),
181+
puppetdb_database_host => $puppetdb_database_target.peadm::target_name(),
182+
puppetdb_database_replica_host => $puppetdb_database_replica_target.peadm::target_name(),
183+
require => Class['peadm::setup::node_manager_yaml'],
184+
}
185+
}
186+
163187
# Upgrade the compiler group A targets
164188
run_task('peadm::puppet_infra_upgrade', $master_target,
165189
type => 'compiler',
@@ -170,11 +194,10 @@
170194
# UPGRADE REPLICA SIDE
171195
###########################################################################
172196

173-
# Shut down PuppetDB on compilers that use the replica's PDB PG
174-
run_task('service', $compiler_m2_targets,
175-
action => 'stop',
176-
name => 'pe-puppetdb',
177-
)
197+
# Shut down PuppetDB on CMs that use the replica's PDB PG. Use run_command
198+
# instead of run_task(service, ...) so that upgrading from 2018.1 works
199+
# over PCP.
200+
run_command('systemctl stop pe-puppetdb', $compiler_m2_targets)
178201

179202
run_task('peadm::pe_install', $puppetdb_database_replica_target,
180203
tarball => $upload_tarball_path,
@@ -208,27 +231,6 @@
208231
# FINALIZE UPGRADE
209232
###########################################################################
210233

211-
run_plan('peadm::util::add_cert_extensions', $convert_targets,
212-
master_host => $master_target,
213-
extensions => {
214-
'pp_auth_role' => 'pe_compiler',
215-
},
216-
)
217-
218-
apply($master_target) {
219-
class { 'peadm::setup::node_manager_yaml':
220-
master_host => $master_target.peadm::target_name(),
221-
}
222-
223-
class { 'peadm::setup::node_manager':
224-
master_host => $master_target.peadm::target_name(),
225-
master_replica_host => $master_replica_target.peadm::target_name(),
226-
puppetdb_database_host => $puppetdb_database_target.peadm::target_name(),
227-
puppetdb_database_replica_host => $puppetdb_database_replica_target.peadm::target_name(),
228-
require => Class['peadm::setup::node_manager_yaml'],
229-
}
230-
}
231-
232234
# Ensure Puppet running on all infrastructure targets
233235
run_task('service', $all_targets,
234236
action => 'start',

plans/util/add_cert_extensions.pp

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
# Loop through and recert each target one at at time, because Bolt lacks
4040
# real parallelism
4141
$all_targets.map |$target| {
42+
$certname = $certdata[$target]['certname']
4243

4344
# This will be the new trusted fact data for this node
4445
$extension_requests = $certdata[$target]['extensions'] + $extensions
@@ -49,25 +50,34 @@
4950
merge => false,
5051
)
5152

52-
# Everything starts the same; we always revoke the existing cert
53-
run_command("${pserver} ca clean --certname ${certdata[$target]['certname']}", $master_target)
53+
# Everything starts the same; we always stop the agent and revoke the
54+
# existing cert. We use `run_command` in case the master is 2019.x but
55+
# the agent is only 2018.x. In that scenario `run_task(service, ...)`
56+
# doesn't work.
57+
$was_running = run_command('systemctl is-active puppet.service', $target, _catch_errors => true)[0].ok
58+
if ($was_running) { run_command('systemctl stop puppet.service', $target) }
59+
run_command("${pserver} ca clean --certname ${certname}", $master_target)
5460

5561
# Then things get crazy...
5662

57-
# The procedure for regenerating an agent's cert
58-
if ($certdata[$target]['certname'] != $master_certname) {
59-
run_command("${puppet} ssl clean --certname ${certdata[$target]['certname']}", $target)
60-
run_command("${puppet} ssl submit_request --certname ${certdata[$target]['certname']}", $target)
63+
if ($certname != $master_certname) {
64+
# AGENT cert regeneration
65+
run_task('peadm::ssl_clean', $target, certname => $certname)
66+
run_task('peadm::submit_csr', $target)
6167
ctrl::sleep(2) # some lag sometimes before the cert is available to sign
62-
run_command(@("HEREDOC"/L), $master_target)
63-
${pserver} ca sign --certname ${certdata[$target]['certname']} || \
64-
${pserver} ca list --certname ${certdata[$target]['certname']} \
68+
run_task('peadm::sign_csr', $master_target, certnames => [$certname])
69+
70+
# Use a command instead of a task so that this works for Puppet 5 agents
71+
# w/ PCP transport. If using a task, we run into problems downloading
72+
# the task file at this point, because there is no longer a cert file
73+
# present on the agent.
74+
run_command(@("HEREDOC"/L), $target)
75+
${puppet} ssl download_cert --certname ${certname} || \
76+
${puppet} certificate find --ca-location remote ${certname}
6577
| HEREDOC
66-
run_command("${puppet} ssl download_cert --certname ${certdata[$target]['certname']}", $target)
6778
}
68-
69-
# The procedure for regenerating the master's cert
7079
else {
80+
# MASTER cert regeneration
7181
# Store the node's current dns-alt-names, for use as a flag restoring
7282
# them later
7383
$alt_names_flag = $certdata[$target]['dns-alt-names'] ? {
@@ -76,22 +86,25 @@
7686
}
7787

7888
# The docs are broken, and the process is unclean. Sadface.
89+
run_task('service', $target, {action => 'stop', name => 'pe-puppetserver'})
7990
run_command(@("HEREDOC"/L), $target)
8091
rm -f \
81-
/etc/puppetlabs/puppet/ssl/certs/${certdata[$target]['certname']}.pem \
82-
/etc/puppetlabs/puppet/ssl/private_keys/${certdata[$target]['certname']}.pem \
83-
/etc/puppetlabs/puppet/ssl/public_keys/${certdata[$target]['certname']}.pem \
84-
/etc/puppetlabs/puppet/ssl/certificate_requests/${certdata[$target]['certname']}.pem \
92+
/etc/puppetlabs/puppet/ssl/certs/${certname}.pem \
93+
/etc/puppetlabs/puppet/ssl/private_keys/${certname}.pem \
94+
/etc/puppetlabs/puppet/ssl/public_keys/${certname}.pem \
95+
/etc/puppetlabs/puppet/ssl/certificate_requests/${certname}.pem \
8596
| HEREDOC
86-
run_task('service', $target, {action => 'stop', name => 'pe-puppetserver'})
8797
run_command(@("HEREDOC"/L), $target)
8898
${pserver} ca generate \
89-
--certname ${certdata[$target]['certname']} \
99+
--certname ${certname} \
90100
${alt_names_flag} \
91101
--ca-client \
92102
| HEREDOC
93103
run_task('service', $target, {action => 'start', name => 'pe-puppetserver'})
94104
}
105+
106+
# Fire puppet back up when done
107+
if ($was_running) { run_command('systemctl start puppet.service', $target) }
95108
}
96109

97110
run_command("${puppet} facts upload", $all_targets)

tasks/ssl_clean.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"description": "Clean an agent's certificate",
3+
"parameters": {
4+
"certname": {
5+
"type": "String",
6+
"description": "The certname to clean"
7+
}
8+
},
9+
"input_method": "stdin"
10+
}

tasks/ssl_clean.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/opt/puppetlabs/puppet/bin/ruby
2+
# frozen_string_literal: true
3+
4+
require 'puppet'
5+
require 'open3'
6+
7+
def main
8+
certname = JSON.parse(STDIN.read)['certname']
9+
majver = Gem::Version.new(Puppet.version).segments.first
10+
if majver < 6
11+
puts "Deleting #{certname}.pem files..."
12+
Dir.glob("/etc/puppetlabs/puppet/ssl/**/#{certname}.pem").each do |file|
13+
File.delete(file)
14+
end
15+
puts 'Done'
16+
exit 0
17+
else
18+
cmd = ['/opt/puppetlabs/bin/puppet', 'ssl', 'clean', '--certname', certname]
19+
stdout, status = Open3.capture2(*cmd)
20+
puts stdout
21+
if status.success?
22+
exit 0
23+
else
24+
exit 1
25+
end
26+
end
27+
end
28+
29+
main

0 commit comments

Comments
 (0)