Skip to content

Commit dab3f8e

Browse files
authored
Merge pull request #152 from reidmv/fix-installer-exit-handling
Fix installer exit handling
2 parents de0961f + 69b0d04 commit dab3f8e

19 files changed

+105
-68
lines changed

CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# PEADM module
22

3+
## Unreleased
4+
### Summary
5+
6+
Unreleased
7+
8+
### Changes
9+
10+
- Improve error handling during early installation of PE
11+
- Implement concurrency in peadm::action::install to increase speed of installation process
12+
313
## 2.5.0
414
### Summary
515

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ The normal usage pattern for peadm is as follows.
5050
### Requirements
5151

5252
* Puppet Enterprise 2019.8.1 or newer (tested with PE 2021.0)
53-
* Bolt 2.27.0 or newer (tested with Bolt 3.5)
53+
* Bolt 2.42.0 or newer (tested with Bolt 3.5.0)
5454
* EL 7, EL 8, Ubuntu 18.04, or Ubuntu 20.04
5555
* Classifier Data enabled. This PE feature is enabled by default on new installs, but can be disabled by users if they remove the relevant configuration from their global hiera.yaml file. See the [PE docs](https://puppet.com/docs/pe/latest/config_console.html#task-5039) for more information.
5656

plans/action/install.pp

+23-28
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
# Common Configuration
3434
String $console_password,
35-
String $version = '2019.7.0',
35+
String $version = '2019.8.5',
3636
Array[String] $dns_alt_names = [ ],
3737
Hash $pe_conf_data = { },
3838

@@ -235,21 +235,15 @@
235235
}
236236
}
237237

238-
# Get the master installation up and running. The installer will
239-
# "fail" because PuppetDB can't start, if puppetdb_database_target
240-
# is set. That's expected.
241-
$shortcircuit_puppetdb = !($puppetdb_database_target.empty)
242-
without_default_logging() || {
243-
out::message("Starting: task peadm::pe_install on ${master_target[0].name}")
244-
run_task('peadm::pe_install', $master_target,
245-
_catch_errors => $shortcircuit_puppetdb,
246-
tarball => $upload_tarball_path,
247-
peconf => '/tmp/pe.conf',
248-
puppet_service_ensure => 'stopped',
249-
shortcircuit_puppetdb => $shortcircuit_puppetdb,
250-
)
251-
out::message("Finished: task peadm::pe_install on ${master_target[0].name}")
252-
}
238+
# Get the master installation up and running. The installer will "fail"
239+
# because PuppetDB can't start, if puppetdb_database_target is set. That's
240+
# expected, and handled by the task's install_extra_large parameter.
241+
run_task('peadm::pe_install', $master_target,
242+
tarball => $upload_tarball_path,
243+
peconf => '/tmp/pe.conf',
244+
puppet_service_ensure => 'stopped',
245+
install_extra_large => ($arch['architecture'] == 'extra-large'),
246+
)
253247

254248
parallelize($master_targets) |$target| {
255249
if $r10k_private_key {
@@ -312,14 +306,19 @@
312306
action => 'file-sync commit',
313307
)
314308

315-
parallelize($agent_installer_targets) |$target| {
309+
parallelize($agent_installer_targets + $database_targets) |$target| {
316310
$common_install_flags = [
317311
'--puppet-service-ensure', 'stopped',
318312
"main:dns_alt_names=${dns_alt_names_csv}",
319313
"main:certname=${target.peadm::target_name()}",
320314
]
321315

322-
if ($target in $compiler_a_targets) {
316+
# Database targets don't need agent installed, they just need to run Puppet
317+
if ($target in $database_targets) {
318+
run_task('peadm::puppet_runonce', $target)
319+
}
320+
# Everything else needs an agent installed and cert signed
321+
elsif ($target in $compiler_a_targets) {
323322
run_task('peadm::agent_install', $target,
324323
server => $master_target.peadm::target_name(),
325324
install_flags => $common_install_flags + [
@@ -347,18 +346,14 @@
347346
)
348347
}
349348

350-
# Ensure certificate requests have been submitted
351-
run_task('peadm::submit_csr', $target)
352-
# TODO: come up with an intelligent way to validate that the expected CSRs
353-
# have been submitted and are available for signing, prior to signing them.
354-
# For now, waiting a short period of time is necessary to avoid a small race.
355-
ctrl::sleep(5)
356-
run_task('peadm::sign_csr', $master_target, { 'certnames' => [$target.name] } )
357-
run_task('peadm::puppet_runonce', $target)
349+
# Ensure certificate requests have been submitted, then run Puppet
350+
unless ($target in $database_targets) {
351+
run_task('peadm::submit_csr', $target)
352+
run_task('peadm::sign_csr', $master_target, { 'certnames' => [$target.name] } )
353+
run_task('peadm::puppet_runonce', $target)
354+
}
358355
}
359356

360-
run_task('peadm::puppet_runonce', $database_targets )
361-
362357
# The puppetserver might be in the middle of a restart after the Puppet run,
363358
# so we check the status by calling the api and ensuring the puppetserver is
364359
# taking requests before proceeding. It takes two runs to fully finish

plans/provision.pp

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
# Common Configuration
3030
String $console_password,
31-
String $version = '2019.8.1',
31+
String $version = '2019.8.5',
3232
Optional[Array[String]] $dns_alt_names = undef,
3333
Optional[String] $compiler_pool_address = undef,
3434
Optional[String] $internal_compiler_a_pool_address = undef,

spec/docker/extra-large-ha/params.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
"compiler_hosts": ["pe-xl-compiler-0.puppet.vm"],
77
"console_password": "puppetlabs",
88
"dns_alt_names": [ "puppet", "pe-xl-core-0.puppet.vm", "puppet-xl.vm" ],
9-
"version": "2019.8.0",
9+
"version": "2019.8.5",
1010
"compiler_pool_address": "puppet-xl.vm"
1111
}

spec/docker/extra-large-ha/upgrade_params.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
"puppetdb_database_replica_host": "pe-xl-db-1.puppet.vm",
55
"master_replica_host": "pe-xl-core-1.puppet.vm",
66
"compiler_hosts": ["pe-xl-compiler-0.puppet.vm"],
7-
"version": "2019.8.0"
7+
"version": "2019.8.5"
88
}

spec/docker/extra-large/params.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
"compiler_hosts": ["pe-xl-compiler-0.puppet.vm"],
55
"console_password": "puppetlabs",
66
"dns_alt_names": [ "puppet", "pe-xl-core-0.puppet.vm" ],
7-
"version": "2019.8.0"
8-
}
7+
"version": "2019.8.5"
8+
}

spec/docker/extra-large/upgrade_params.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"master_host": "pe-xl-core-0.puppet.vm",
33
"puppetdb_database_host": "pe-xl-db-0.puppet.vm",
44
"compiler_hosts": ["pe-xl-compiler-0.puppet.vm"],
5-
"version": "2019.8.0"
5+
"version": "2019.8.5"
66
}

spec/docker/large-ha/params.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
"compiler_hosts": ["pe-lg-compiler-0.puppet.vm"],
55
"console_password": "puppetlabs",
66
"dns_alt_names": [ "puppet", "pe-lg.puppet.vm" ],
7-
"version": "2019.8.0"
7+
"version": "2019.8.5"
88
}

spec/docker/large-ha/upgrade_params.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
"master_host": "pe-lg.puppet.vm",
33
"master_replica_host": "pe-lg-replica.puppet.vm",
44
"compiler_hosts": ["pe-lg-compiler-0.puppet.vm"],
5-
"version": "2019.8.0"
5+
"version": "2019.8.5"
66
}
77

spec/docker/large/params.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
"compiler_hosts": ["pe-lg-compiler-0.puppet.vm"],
44
"console_password": "puppetlabs",
55
"dns_alt_names": [ "puppet", "pe-lg.puppet.vm" ],
6-
"version": "2019.8.0"
6+
"version": "2019.8.5"
77
}

spec/docker/large/upgrade_params.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"master_host": "pe-lg.puppet.vm",
33
"compiler_hosts": ["pe-lg-compiler-0.puppet.vm"],
4-
"version": "2019.8.0"
4+
"version": "2019.8.5"
55
}
66

spec/docker/standard-ha/params.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
"master_replica_host": "pe-std-replica.puppet.vm",
44
"console_password": "puppetlabs",
55
"dns_alt_names": [ "puppet", "pe-std.puppet.vm" ],
6-
"version": "2019.8.0"
6+
"version": "2019.8.5"
77
}
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"master_host": "pe-std.puppet.vm",
33
"master_replica_host": "pe-std-replica.puppet.vm",
4-
"version": "2019.8.0"
4+
"version": "2019.8.5"
55
}
66

spec/docker/standard/params.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
"master_host": "pe-std.puppet.vm",
33
"console_password": "puppetlabs",
44
"dns_alt_names": [ "puppet", "pe-std.puppet.vm" ],
5-
"version": "2019.8.0",
5+
"version": "2019.8.5",
66
"r10k_remote": "https://gitlab.com/nwops/control-repo.git"
77
}
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"master_host": "pe-std.puppet.vm",
3-
"version": "2019.8.0"
3+
"version": "2019.8.5"
44
}
55

tasks/pe_install.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
"type": "Optional[String]",
1010
"description": "The path to the pe.conf file"
1111
},
12-
"shortcircuit_puppetdb": {
12+
"install_extra_large": {
1313
"type": "Optional[Boolean]",
14-
"description": "If true, during install, configure PuppetDB to short-circuit its startup"
14+
"description": "If true, optimize task for known manual issues with extra-large installs. Do not use for upgrades"
1515
},
1616
"puppet_service_ensure": {
1717
"type": "Optional[Enum['stopped']]",

tasks/pe_install.sh

+15-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# in situations where PuppetDB WILL fail, such as when PostgreSQL is not yet
55
# configured, and we don't want to let PuppetDB wait five minutes before
66
# giving up on it.
7-
if [ "$PT_shortcircuit_puppetdb" = "true" ]; then
7+
if [ "$PT_install_extra_large" = "true" ]; then
88
mkdir /etc/systemd/system/pe-puppetdb.service.d
99
cat > /etc/systemd/system/pe-puppetdb.service.d/10-shortcircuit.conf <<-EOF
1010
[Service]
@@ -33,7 +33,7 @@ fi
3333
# The exit code of the installer script will be the exit code of the task
3434
exit_code=$?
3535

36-
if [ "$PT_shortcircuit_puppetdb" = "true" ]; then
36+
if [ "$PT_install_extra_large" = "true" ]; then
3737
systemctl stop pe-puppetdb.service
3838
rm /etc/systemd/system/pe-puppetdb.service.d/10-shortcircuit.conf
3939
systemctl daemon-reload
@@ -43,5 +43,16 @@ if [ "$PT_puppet_service_ensure" = "stopped" ]; then
4343
systemctl stop puppet.service
4444
fi
4545

46-
# Exit with the installer script's exit code
47-
exit $exit_code
46+
# In an extra large install, the installer is known to exit with code 1, even
47+
# on an otherwise successful install, because PuppetDB cannot start yet. The
48+
# task should indicate successful completion even if the exit code is 1, as
49+
# long as some basic "did it install?" health checks pass.
50+
if [ "$PT_install_extra_large" = "true" ]; then
51+
for svc in pe-puppetserver pe-orchestration-services pe-console-services; do
52+
systemctl is-active --quiet $svc.service || exit $exit_code
53+
done
54+
exit 0
55+
else
56+
# Exit with the installer script's exit code
57+
exit $exit_code
58+
fi

tasks/sign_csr.rb

+40-19
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,54 @@
11
#!/opt/puppetlabs/puppet/bin/ruby
22
# frozen_string_literal: true
33

4-
#
54
require 'json'
65
require 'open3'
76
require 'puppet'
87

9-
def csr_signed?(certname)
10-
!File.exist?(File.join(Puppet.settings[:csrdir], "#{certname}.pem")) &&
11-
File.exist?(File.join(Puppet.settings[:cadir], 'signed', "#{certname}.pem"))
12-
end
8+
# Class to run and execute the `puppetserver ca sign` command as a task.
9+
class SignCSR
10+
class SigningError; end
1311

14-
def main
15-
Puppet.initialize_settings
16-
params = JSON.parse(STDIN.read)
17-
unsigned = params['certnames'].reject { |name| csr_signed?(name) }
12+
def initialize(params)
13+
Puppet.initialize_settings
14+
@certnames = params['certnames']
15+
end
1816

19-
exit 0 if unsigned.empty?
17+
def execute!
18+
attempts = 0
2019

21-
cmd = ['/opt/puppetlabs/bin/puppetserver', 'ca', 'sign',
22-
'--certname', unsigned.join(',')]
20+
begin
21+
unsigned = @certnames.reject { |name| csr_signed?(name) }
22+
exit 0 if unsigned.empty?
23+
sign(unsigned)
24+
rescue SigningError
25+
exit 1 if attempts > 5
26+
attempts += 1
27+
puts "Signing attempt #{attempts} failed; waiting 1s and trying again"
28+
sleep 1
29+
retry
30+
end
31+
end
2332

24-
stdout, status = Open3.capture2(*cmd)
25-
puts stdout
26-
if status.success?
27-
exit 0
28-
else
29-
exit 1
33+
def csr_signed?(certname)
34+
!File.exist?(File.join(Puppet.settings[:csrdir], "#{certname}.pem")) &&
35+
File.exist?(File.join(Puppet.settings[:cadir], 'signed', "#{certname}.pem"))
36+
end
37+
38+
def sign(certnames)
39+
cmd = ['/opt/puppetlabs/bin/puppetserver', 'ca', 'sign',
40+
'--certname', certnames.join(',')]
41+
42+
stdout, status = Open3.capture2(*cmd)
43+
puts stdout
44+
raise SigningError unless status.success?
3045
end
3146
end
3247

33-
main
48+
# Run the task unless an environment flag has been set, signaling not to. The
49+
# environment flag is used to disable auto-execution and enable Ruby unit
50+
# testing of this task.
51+
unless ENV['RSPEC_UNIT_TEST_MODE']
52+
task = SignCSR.new(JSON.parse(STDIN.read))
53+
task.execute!
54+
end

0 commit comments

Comments
 (0)