diff --git a/REFERENCE.md b/REFERENCE.md
index 2951060f..b8735c23 100644
--- a/REFERENCE.md
+++ b/REFERENCE.md
@@ -16,6 +16,7 @@
### Functions
+* [`peadm::amend_recovery_defaults_by_pe_version`](#peadm--amend_recovery_defaults_by_pe_version)
* [`peadm::assert_supported_architecture`](#peadm--assert_supported_architecture): Assert that the architecture given is a supported one
* [`peadm::assert_supported_bolt_version`](#peadm--assert_supported_bolt_version): Assert that the Bolt executable running PEAdm is a supported version
* [`peadm::assert_supported_pe_version`](#peadm--assert_supported_pe_version): Assert that the PE version given is supported by PEAdm
@@ -39,6 +40,7 @@
* [`peadm::recovery_opts_all`](#peadm--recovery_opts_all)
* [`peadm::recovery_opts_default`](#peadm--recovery_opts_default)
* [`peadm::update_pe_conf`](#peadm--update_pe_conf): Update the pe.conf file on a target with the provided hash
+* [`peadm::validated_pe_version_for_backup_restore`](#peadm--validated_pe_version_for_backup_restore): Verify that *pe_version* string is a valid SemVer. If not, warn, and return "0.0.0" as a permissive default.
* [`peadm::wait_until_service_ready`](#peadm--wait_until_service_ready): A convenience function to help remember port numbers for services and handle running the wait_until_service_ready task
### Data types
@@ -139,6 +141,36 @@ Supported use cases:
## Functions
+### `peadm::amend_recovery_defaults_by_pe_version`
+
+Type: Puppet Language
+
+The peadm::amend_recovery_defaults_by_pe_version function.
+
+#### `peadm::amend_recovery_defaults_by_pe_version(Hash $base_opts, Peadm::Pe_version $pe_version, Boolean $opt_value)`
+
+The peadm::amend_recovery_defaults_by_pe_version function.
+
+Returns: `Any`
+
+##### `base_opts`
+
+Data type: `Hash`
+
+
+
+##### `pe_version`
+
+Data type: `Peadm::Pe_version`
+
+
+
+##### `opt_value`
+
+Data type: `Boolean`
+
+
+
### `peadm::assert_supported_architecture`
Type: Puppet Language
@@ -787,12 +819,18 @@ Type: Puppet Language
The peadm::migration_opts_default function.
-#### `peadm::migration_opts_default()`
+#### `peadm::migration_opts_default(Peadm::Pe_version $pe_version)`
The peadm::migration_opts_default function.
Returns: `Any`
+##### `pe_version`
+
+Data type: `Peadm::Pe_version`
+
+
+
### `peadm::node_manager_yaml_location`
Type: Ruby 4.x API
@@ -853,24 +891,36 @@ Type: Puppet Language
The peadm::recovery_opts_all function.
-#### `peadm::recovery_opts_all()`
+#### `peadm::recovery_opts_all(Peadm::Pe_version $pe_version)`
The peadm::recovery_opts_all function.
Returns: `Any`
+##### `pe_version`
+
+Data type: `Peadm::Pe_version`
+
+
+
### `peadm::recovery_opts_default`
Type: Puppet Language
The peadm::recovery_opts_default function.
-#### `peadm::recovery_opts_default()`
+#### `peadm::recovery_opts_default(Peadm::Pe_version $pe_version)`
The peadm::recovery_opts_default function.
Returns: `Any`
+##### `pe_version`
+
+Data type: `Peadm::Pe_version`
+
+
+
### `peadm::update_pe_conf`
Type: Puppet Language
@@ -895,6 +945,26 @@ Data type: `Hash`
The hash to update the pe.conf file with
+### `peadm::validated_pe_version_for_backup_restore`
+
+Type: Puppet Language
+
+Verify that *pe_version* string is a valid SemVer.
+If not, warn, and return "0.0.0" as a permissive default.
+
+#### `peadm::validated_pe_version_for_backup_restore(Optional[String] $pe_version)`
+
+Verify that *pe_version* string is a valid SemVer.
+If not, warn, and return "0.0.0" as a permissive default.
+
+Returns: `Any`
+
+##### `pe_version`
+
+Data type: `Optional[String]`
+
+
+
### `peadm::wait_until_service_ready`
Type: Puppet Language
@@ -1014,6 +1084,8 @@ Struct[{
'orchestrator' => Optional[Boolean],
'puppetdb' => Optional[Boolean],
'rbac' => Optional[Boolean],
+ 'hac' => Optional[Boolean],
+ 'patching' => Optional[Boolean],
}]
```
diff --git a/functions/amend_recovery_defaults_by_pe_version.pp b/functions/amend_recovery_defaults_by_pe_version.pp
new file mode 100644
index 00000000..d6de2cb1
--- /dev/null
+++ b/functions/amend_recovery_defaults_by_pe_version.pp
@@ -0,0 +1,25 @@
+function peadm::amend_recovery_defaults_by_pe_version (
+ Hash $base_opts,
+ Peadm::Pe_version $pe_version,
+ Boolean $opt_value,
+) {
+ # work around puppet-lint check_unquoted_string_in_case
+ $pe_2025_0 = SemVerRange('>= 2025.0')
+ $pe_2023_7 = SemVerRange('>= 2023.7')
+ case $pe_version {
+ $pe_2025_0: {
+ $base_opts + {
+ 'hac' => $opt_value,
+ 'patching' => $opt_value,
+ }
+ }
+ $pe_2023_7: {
+ $base_opts + {
+ 'hac' => $opt_value,
+ }
+ }
+ default: {
+ $base_opts
+ }
+ }
+}
diff --git a/functions/migration_opts_default.pp b/functions/migration_opts_default.pp
index 99b57e55..2b770a40 100644
--- a/functions/migration_opts_default.pp
+++ b/functions/migration_opts_default.pp
@@ -1,5 +1,7 @@
-function peadm::migration_opts_default () {
- {
+function peadm::migration_opts_default (
+ Peadm::Pe_version $pe_version,
+) {
+ $base_opts = {
'activity' => true,
'ca' => true,
'classifier' => true,
@@ -9,4 +11,5 @@ function peadm::migration_opts_default () {
'puppetdb' => true,
'rbac' => true,
}
+ peadm::amend_recovery_defaults_by_pe_version($base_opts, $pe_version, true)
}
diff --git a/functions/recovery_opts_all.pp b/functions/recovery_opts_all.pp
index e738ab5e..6f6f59c0 100644
--- a/functions/recovery_opts_all.pp
+++ b/functions/recovery_opts_all.pp
@@ -1,5 +1,7 @@
-function peadm::recovery_opts_all () {
- {
+function peadm::recovery_opts_all (
+ Peadm::Pe_version $pe_version,
+) {
+ $base_opts = {
'activity' => true,
'ca' => true,
'classifier' => true,
@@ -9,4 +11,5 @@ function peadm::recovery_opts_all () {
'puppetdb' => true,
'rbac' => true,
}
+ peadm::amend_recovery_defaults_by_pe_version($base_opts, $pe_version, true)
}
diff --git a/functions/recovery_opts_default.pp b/functions/recovery_opts_default.pp
index 5e4b2f4d..5c9bf57c 100644
--- a/functions/recovery_opts_default.pp
+++ b/functions/recovery_opts_default.pp
@@ -1,5 +1,7 @@
-function peadm::recovery_opts_default () {
- {
+function peadm::recovery_opts_default (
+ Peadm::Pe_version $pe_version,
+) {
+ $base_opts = {
'activity' => false,
'ca' => true,
'classifier' => false,
@@ -9,4 +11,5 @@ function peadm::recovery_opts_default () {
'puppetdb' => true,
'rbac' => false,
}
+ peadm::amend_recovery_defaults_by_pe_version($base_opts, $pe_version, false)
}
diff --git a/functions/validated_pe_version_for_backup_restore.pp b/functions/validated_pe_version_for_backup_restore.pp
new file mode 100644
index 00000000..73efc781
--- /dev/null
+++ b/functions/validated_pe_version_for_backup_restore.pp
@@ -0,0 +1,23 @@
+# Verify that *pe_version* string is a valid SemVer.
+# If not, warn, and return "0.0.0" as a permissive default.
+function peadm::validated_pe_version_for_backup_restore(
+ Optional[String] $pe_version,
+) {
+ # work around puppet-lint check_unquoted_string_in_case
+ $semverrange = SemVerRange('>=0.0.0')
+ case $pe_version {
+ # Validate that the value is a SemVer value.
+ $semverrange: {
+ $pe_version
+ }
+ default: {
+ $msg = @("WARN")
+ WARNING: Retrieved a missing or unparseable PE version of '${pe_version}'.
+ Newer service databases released in 2023.7+ will be skipped from defaults.
+ (host-action-collector, patching)
+ |-WARN
+ out::message($msg)
+ '0.0.0'
+ }
+ }
+}
diff --git a/plans/backup.pp b/plans/backup.pp
index 80835eb0..4e3e15a6 100644
--- a/plans/backup.pp
+++ b/plans/backup.pp
@@ -35,10 +35,12 @@
getvar('cluster.params.compiler_hosts'),
)
+ $pe_version = peadm::validated_pe_version_for_backup_restore(getvar('cluster.pe_version'))
+
$recovery_opts = $backup_type? {
- 'recovery' => peadm::recovery_opts_default(),
- 'migration' => peadm::migration_opts_default(),
- 'custom' => peadm::recovery_opts_all() + $backup,
+ 'recovery' => peadm::recovery_opts_default($pe_version),
+ 'migration' => peadm::migration_opts_default($pe_version),
+ 'custom' => peadm::recovery_opts_all($pe_version) + $backup,
}
$timestamp = Timestamp.new().strftime('%Y-%m-%dT%H%M%SZ')
@@ -55,6 +57,10 @@
'activity' => $primary_target,
'rbac' => $primary_target,
'puppetdb' => $puppetdb_postgresql_target,
+ # (host-action-collector db will be filtered for pe version by recovery_opts)
+ 'hac' => $primary_target,
+ # (patching db will be filtered for pe version by recovery_opts)
+ 'patching' => $primary_target,
}.filter |$key,$_| {
$recovery_opts[$key] == true
}
diff --git a/plans/restore.pp b/plans/restore.pp
index 453bf8e5..8e8975f6 100644
--- a/plans/restore.pp
+++ b/plans/restore.pp
@@ -34,7 +34,7 @@
# try to load the cluster configuration by running peadm::get_peadm_config, but allow for errors to happen
$_cluster = run_task('peadm::get_peadm_config', $targets, { '_catch_errors' => true }).first.value
- if $_cluster == undef or getvar('_cluster.params') == undef {
+ if $_cluster == undef or getvar('_cluster.params') == undef or getvar('_cluster.pe_version') == undef {
# failed to get cluster config, load from backup
out::message('Failed to get cluster configuration, loading from backup...')
$result = download_file("${recovery_directory}/peadm/peadm_config.json", 'peadm_config.json', $targets).first.value
@@ -59,11 +59,13 @@
getvar('cluster.params.compiler_hosts'),
)
+ $pe_version = peadm::validated_pe_version_for_backup_restore(getvar('cluster.pe_version'))
+
$recovery_opts = $restore_type? {
- 'recovery' => peadm::recovery_opts_default(),
+ 'recovery' => peadm::recovery_opts_default($pe_version),
'recovery-db' => { 'puppetdb' => true, },
- 'migration' => peadm::migration_opts_default(),
- 'custom' => peadm::recovery_opts_all() + $restore,
+ 'migration' => peadm::migration_opts_default($pe_version),
+ 'custom' => peadm::recovery_opts_all($pe_version) + $restore,
}
$primary_target = peadm::get_targets(getvar('cluster.params.primary_host'), 1)
@@ -97,6 +99,10 @@
'activity' => [$primary_target],
'rbac' => [$primary_target],
'puppetdb' => $puppetdb_postgresql_targets,
+ # (host-action-collector db will be filtered for pe version by recovery_opts)
+ 'hac' => $primary_target,
+ # (patching db will be filtered for pe version by recovery_opts)
+ 'patching' => $primary_target,
}.filter |$key,$_| {
$recovery_opts[$key] == true
}
@@ -203,7 +209,7 @@
if getvar('recovery_opts.orchestrator') {
out::message('# Restoring orchestrator secret keys')
run_command(@("CMD"/L), $primary_target)
- cp -rp ${shellquote($recovery_directory)}/orchestrator/secrets/* /etc/puppetlabs/orchestration-services/conf.d/secrets/
+ cp -rp ${shellquote($recovery_directory)}/orchestrator/secrets/* /etc/puppetlabs/orchestration-services/conf.d/secrets/
| CMD
}
# lint:endignore
diff --git a/spec/fixtures/peadm_config.json b/spec/fixtures/peadm_config.json
index cbd5db76..de2c0a5a 100644
--- a/spec/fixtures/peadm_config.json
+++ b/spec/fixtures/peadm_config.json
@@ -1,3 +1,4 @@
{
+ "pe_version" : "2023.7.0",
"params": { "primary_host": "primary", "primary_postgresql_host": "postgres" }
}
diff --git a/spec/fixtures/peadm_config.no_pe_version.json b/spec/fixtures/peadm_config.no_pe_version.json
new file mode 100644
index 00000000..cbd5db76
--- /dev/null
+++ b/spec/fixtures/peadm_config.no_pe_version.json
@@ -0,0 +1,3 @@
+{
+ "params": { "primary_host": "primary", "primary_postgresql_host": "postgres" }
+}
diff --git a/spec/functions/amend_recovery_defaults_by_pe_version_spec.rb b/spec/functions/amend_recovery_defaults_by_pe_version_spec.rb
new file mode 100644
index 00000000..6bd5d418
--- /dev/null
+++ b/spec/functions/amend_recovery_defaults_by_pe_version_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe 'peadm::amend_recovery_defaults_by_pe_version' do
+ it 'just returns the base opts if version < 2023.7' do
+ is_expected.to run.with_params({}, '2023.6.0', true).and_return({})
+ end
+
+ it 'adds hac if version >= 2023.7' do
+ is_expected.to run.with_params({}, '2023.7.0', true).and_return({ 'hac' => true })
+ end
+
+ it 'adds hac false based on opt_value' do
+ is_expected.to run.with_params({}, '2023.7.0', false).and_return({ 'hac' => false })
+ end
+end
diff --git a/spec/functions/migration_opts_default_spec.rb b/spec/functions/migration_opts_default_spec.rb
new file mode 100644
index 00000000..c9df7743
--- /dev/null
+++ b/spec/functions/migration_opts_default_spec.rb
@@ -0,0 +1,51 @@
+require 'spec_helper'
+
+describe 'peadm::migration_opts_default' do
+ it 'returns pre 2023.7 defaults' do
+ is_expected.to run.with_params('2023.6.0').and_return(
+ {
+ 'activity' => true,
+ 'ca' => true,
+ 'classifier' => true,
+ 'code' => false,
+ 'config' => false,
+ 'orchestrator' => true,
+ 'puppetdb' => true,
+ 'rbac' => true,
+ },
+ )
+ end
+
+ it 'returns 2023.7+ defaults with hac' do
+ is_expected.to run.with_params('2023.7.0').and_return(
+ {
+ 'activity' => true,
+ 'ca' => true,
+ 'classifier' => true,
+ 'code' => false,
+ 'config' => false,
+ 'orchestrator' => true,
+ 'puppetdb' => true,
+ 'rbac' => true,
+ 'hac' => true,
+ },
+ )
+ end
+
+ it 'returns 2025.0+ defaults with hac and patching' do
+ is_expected.to run.with_params('2025.0.0').and_return(
+ {
+ 'activity' => true,
+ 'ca' => true,
+ 'classifier' => true,
+ 'code' => false,
+ 'config' => false,
+ 'orchestrator' => true,
+ 'puppetdb' => true,
+ 'rbac' => true,
+ 'hac' => true,
+ 'patching' => true,
+ },
+ )
+ end
+end
diff --git a/spec/functions/recovery_opts_all_spec.rb b/spec/functions/recovery_opts_all_spec.rb
new file mode 100644
index 00000000..7d12ebda
--- /dev/null
+++ b/spec/functions/recovery_opts_all_spec.rb
@@ -0,0 +1,67 @@
+require 'spec_helper'
+
+describe 'peadm::recovery_opts_all' do
+ it 'returns pre 2023.7 defaults' do
+ is_expected.to run.with_params('2023.6.0').and_return(
+ {
+ 'activity' => true,
+ 'ca' => true,
+ 'classifier' => true,
+ 'code' => true,
+ 'config' => true,
+ 'orchestrator' => true,
+ 'puppetdb' => true,
+ 'rbac' => true,
+ },
+ )
+ end
+
+ it 'returns 2023.7+ defaults with hac' do
+ is_expected.to run.with_params('2023.7.0').and_return(
+ {
+ 'activity' => true,
+ 'ca' => true,
+ 'classifier' => true,
+ 'code' => true,
+ 'config' => true,
+ 'orchestrator' => true,
+ 'puppetdb' => true,
+ 'rbac' => true,
+ 'hac' => true,
+ },
+ )
+ end
+
+ it 'returns 2023.7+ defaults with hac if >2023.7 <2025.0' do
+ is_expected.to run.with_params('2024.9999.0').and_return(
+ {
+ 'activity' => true,
+ 'ca' => true,
+ 'classifier' => true,
+ 'code' => true,
+ 'config' => true,
+ 'orchestrator' => true,
+ 'puppetdb' => true,
+ 'rbac' => true,
+ 'hac' => true,
+ },
+ )
+ end
+
+ it 'returns 2025.0+ defaults with hac and patching' do
+ is_expected.to run.with_params('2025.0.0').and_return(
+ {
+ 'activity' => true,
+ 'ca' => true,
+ 'classifier' => true,
+ 'code' => true,
+ 'config' => true,
+ 'orchestrator' => true,
+ 'puppetdb' => true,
+ 'rbac' => true,
+ 'hac' => true,
+ 'patching' => true,
+ },
+ )
+ end
+end
diff --git a/spec/functions/recovery_opts_default_spec.rb b/spec/functions/recovery_opts_default_spec.rb
new file mode 100644
index 00000000..7a775456
--- /dev/null
+++ b/spec/functions/recovery_opts_default_spec.rb
@@ -0,0 +1,51 @@
+require 'spec_helper'
+
+describe 'peadm::recovery_opts_default' do
+ it 'returns pre 2023.7 defaults' do
+ is_expected.to run.with_params('2023.6.0').and_return(
+ {
+ 'activity' => false,
+ 'ca' => true,
+ 'classifier' => false,
+ 'code' => true,
+ 'config' => true,
+ 'orchestrator' => false,
+ 'puppetdb' => true,
+ 'rbac' => false,
+ },
+ )
+ end
+
+ it 'returns 2023.7+ defaults with hac' do
+ is_expected.to run.with_params('2023.7.0').and_return(
+ {
+ 'activity' => false,
+ 'ca' => true,
+ 'classifier' => false,
+ 'code' => true,
+ 'config' => true,
+ 'orchestrator' => false,
+ 'puppetdb' => true,
+ 'rbac' => false,
+ 'hac' => false,
+ },
+ )
+ end
+
+ it 'returns 2025.0+ defaults with hac and patching' do
+ is_expected.to run.with_params('2025.0.0').and_return(
+ {
+ 'activity' => false,
+ 'ca' => true,
+ 'classifier' => false,
+ 'code' => true,
+ 'config' => true,
+ 'orchestrator' => false,
+ 'puppetdb' => true,
+ 'rbac' => false,
+ 'hac' => false,
+ 'patching' => false,
+ },
+ )
+ end
+end
diff --git a/spec/plans/backup_spec.rb b/spec/plans/backup_spec.rb
index d6b2ff75..20243f45 100644
--- a/spec/plans/backup_spec.rb
+++ b/spec/plans/backup_spec.rb
@@ -20,6 +20,8 @@
'orchestrator' => false,
'puppetdb' => false,
'rbac' => false,
+ 'hac' => false,
+ 'patching' => false,
}
}
end
@@ -30,6 +32,16 @@
'backup' => {} # set all to true
}
end
+ let(:pe_version) { '2023.7.0' }
+ let(:cluster) do
+ {
+ 'pe_version' => pe_version,
+ 'params' => {
+ 'primary_host' => 'primary',
+ 'primary_postgresql_host' => 'postgres',
+ }
+ }
+ end
before(:each) do
# define a zero timestamp
@@ -40,12 +52,7 @@
allow_apply
- expect_task('peadm::get_peadm_config').always_return({
- 'params' => {
- 'primary_host' => 'primary',
- 'primary_postgresql_host' => 'postgres',
- }
- })
+ expect_task('peadm::get_peadm_config').always_return(cluster)
end
it 'runs with backup type recovery' do
@@ -89,27 +96,83 @@
expect(run_plan('peadm::backup', classifier_only)).to be_ok
end
- it 'runs with backup type custom, all backup params set to true' do
- expect_task('peadm::backup_classification').with_params({ 'directory' => '/tmp/pe-backup-1970-01-01T000000Z/classifier' })
+ shared_context('all 2023.6.0 backups') do
+ before(:each) do
+ expect_task('peadm::backup_classification').with_params({ 'directory' => '/tmp/pe-backup-1970-01-01T000000Z/classifier' })
+
+ expect_out_message.with_params('# Backing up classification')
+ expect_out_message.with_params('# Backing up database pe-orchestrator')
+ expect_out_message.with_params('# Backing up database pe-activity')
+ expect_out_message.with_params('# Backing up database pe-rbac')
+ expect_out_message.with_params('# Backing up database pe-puppetdb')
+
+ expect_command("/opt/puppetlabs/bin/puppet-backup create --dir=/tmp/pe-backup-1970-01-01T000000Z/ca --scope=certs\n")
+ expect_command("/opt/puppetlabs/bin/puppet-backup create --dir=/tmp/pe-backup-1970-01-01T000000Z/code --scope=code\n")
+ expect_command('chown pe-postgres /tmp/pe-backup-1970-01-01T000000Z/config')
+ expect_command("/opt/puppetlabs/bin/puppet-backup create --dir=/tmp/pe-backup-1970-01-01T000000Z/config --scope=config\n")
+ expect_command("test -f /etc/puppetlabs/console-services/conf.d/secrets/keys.json && cp -rp /etc/puppetlabs/console-services/conf.d/secrets /tmp/pe-backup-1970-01-01T000000Z/rbac/ || echo secret ldap key doesnt exist\n")
+ expect_command("cp -rp /etc/puppetlabs/orchestration-services/conf.d/secrets /tmp/pe-backup-1970-01-01T000000Z/orchestrator/\n")
+ expect_command('/opt/puppetlabs/server/bin/pg_dump -Fd -Z3 -j4 -f /tmp/pe-backup-1970-01-01T000000Z/orchestrator/pe-orchestrator.dump.d "sslmode=verify-ca host=primary user=pe-orchestrator sslcert=/etc/puppetlabs/puppetdb/ssl/primary.cert.pem sslkey=/etc/puppetlabs/puppetdb/ssl/primary.private_key.pem sslrootcert=/etc/puppetlabs/puppet/ssl/certs/ca.pem dbname=pe-orchestrator"' + "\n")
+ expect_command('/opt/puppetlabs/server/bin/pg_dump -Fd -Z3 -j4 -f /tmp/pe-backup-1970-01-01T000000Z/activity/pe-activity.dump.d "sslmode=verify-ca host=primary user=pe-activity sslcert=/etc/puppetlabs/puppetdb/ssl/primary.cert.pem sslkey=/etc/puppetlabs/puppetdb/ssl/primary.private_key.pem sslrootcert=/etc/puppetlabs/puppet/ssl/certs/ca.pem dbname=pe-activity"' + "\n")
+ expect_command('/opt/puppetlabs/server/bin/pg_dump -Fd -Z3 -j4 -f /tmp/pe-backup-1970-01-01T000000Z/rbac/pe-rbac.dump.d "sslmode=verify-ca host=primary user=pe-rbac sslcert=/etc/puppetlabs/puppetdb/ssl/primary.cert.pem sslkey=/etc/puppetlabs/puppetdb/ssl/primary.private_key.pem sslrootcert=/etc/puppetlabs/puppet/ssl/certs/ca.pem dbname=pe-rbac"' + "\n")
+ expect_command('/opt/puppetlabs/server/bin/pg_dump -Fd -Z3 -j4 -f /tmp/pe-backup-1970-01-01T000000Z/puppetdb/pe-puppetdb.dump.d "sslmode=verify-ca host=postgres user=pe-puppetdb sslcert=/etc/puppetlabs/puppetdb/ssl/primary.cert.pem sslkey=/etc/puppetlabs/puppetdb/ssl/primary.private_key.pem sslrootcert=/etc/puppetlabs/puppet/ssl/certs/ca.pem dbname=pe-puppetdb"' + "\n")
+ expect_command('umask 0077 && cd /tmp && tar -czf /tmp/pe-backup-1970-01-01T000000Z.tar.gz pe-backup-1970-01-01T000000Z && rm -rf /tmp/pe-backup-1970-01-01T000000Z' + "\n")
+ end
+ end
- expect_out_message.with_params('# Backing up classification')
- expect_out_message.with_params('# Backing up database pe-orchestrator')
- expect_out_message.with_params('# Backing up database pe-activity')
- expect_out_message.with_params('# Backing up database pe-rbac')
- expect_out_message.with_params('# Backing up database pe-puppetdb')
+ context '>= 2025.0.0' do
+ let(:pe_version) { '2025.0.0' }
- expect_command("/opt/puppetlabs/bin/puppet-backup create --dir=/tmp/pe-backup-1970-01-01T000000Z/ca --scope=certs\n")
- expect_command("/opt/puppetlabs/bin/puppet-backup create --dir=/tmp/pe-backup-1970-01-01T000000Z/code --scope=code\n")
- expect_command('chown pe-postgres /tmp/pe-backup-1970-01-01T000000Z/config')
- expect_command("/opt/puppetlabs/bin/puppet-backup create --dir=/tmp/pe-backup-1970-01-01T000000Z/config --scope=config\n")
- expect_command("test -f /etc/puppetlabs/console-services/conf.d/secrets/keys.json && cp -rp /etc/puppetlabs/console-services/conf.d/secrets /tmp/pe-backup-1970-01-01T000000Z/rbac/ || echo secret ldap key doesnt exist\n")
- expect_command("cp -rp /etc/puppetlabs/orchestration-services/conf.d/secrets /tmp/pe-backup-1970-01-01T000000Z/orchestrator/\n")
- expect_command('/opt/puppetlabs/server/bin/pg_dump -Fd -Z3 -j4 -f /tmp/pe-backup-1970-01-01T000000Z/orchestrator/pe-orchestrator.dump.d "sslmode=verify-ca host=primary user=pe-orchestrator sslcert=/etc/puppetlabs/puppetdb/ssl/primary.cert.pem sslkey=/etc/puppetlabs/puppetdb/ssl/primary.private_key.pem sslrootcert=/etc/puppetlabs/puppet/ssl/certs/ca.pem dbname=pe-orchestrator"' + "\n")
- expect_command('/opt/puppetlabs/server/bin/pg_dump -Fd -Z3 -j4 -f /tmp/pe-backup-1970-01-01T000000Z/activity/pe-activity.dump.d "sslmode=verify-ca host=primary user=pe-activity sslcert=/etc/puppetlabs/puppetdb/ssl/primary.cert.pem sslkey=/etc/puppetlabs/puppetdb/ssl/primary.private_key.pem sslrootcert=/etc/puppetlabs/puppet/ssl/certs/ca.pem dbname=pe-activity"' + "\n")
- expect_command('/opt/puppetlabs/server/bin/pg_dump -Fd -Z3 -j4 -f /tmp/pe-backup-1970-01-01T000000Z/rbac/pe-rbac.dump.d "sslmode=verify-ca host=primary user=pe-rbac sslcert=/etc/puppetlabs/puppetdb/ssl/primary.cert.pem sslkey=/etc/puppetlabs/puppetdb/ssl/primary.private_key.pem sslrootcert=/etc/puppetlabs/puppet/ssl/certs/ca.pem dbname=pe-rbac"' + "\n")
- expect_command('/opt/puppetlabs/server/bin/pg_dump -Fd -Z3 -j4 -f /tmp/pe-backup-1970-01-01T000000Z/puppetdb/pe-puppetdb.dump.d "sslmode=verify-ca host=postgres user=pe-puppetdb sslcert=/etc/puppetlabs/puppetdb/ssl/primary.cert.pem sslkey=/etc/puppetlabs/puppetdb/ssl/primary.private_key.pem sslrootcert=/etc/puppetlabs/puppet/ssl/certs/ca.pem dbname=pe-puppetdb"' + "\n")
- expect_command('umask 0077 && cd /tmp && tar -czf /tmp/pe-backup-1970-01-01T000000Z.tar.gz pe-backup-1970-01-01T000000Z && rm -rf /tmp/pe-backup-1970-01-01T000000Z' + "\n")
+ include_context('all 2023.6.0 backups')
+
+ it 'runs with backup type custom, all backup params set to true' do
+ expect_out_message.with_params('# Backing up database pe-hac')
+ expect_out_message.with_params('# Backing up database pe-patching')
+
+ expect_command('/opt/puppetlabs/server/bin/pg_dump -Fd -Z3 -j4 -f /tmp/pe-backup-1970-01-01T000000Z/hac/pe-hac.dump.d "sslmode=verify-ca host=primary user=pe-hac sslcert=/etc/puppetlabs/puppetdb/ssl/primary.cert.pem sslkey=/etc/puppetlabs/puppetdb/ssl/primary.private_key.pem sslrootcert=/etc/puppetlabs/puppet/ssl/certs/ca.pem dbname=pe-hac"' + "\n")
+ expect_command('/opt/puppetlabs/server/bin/pg_dump -Fd -Z3 -j4 -f /tmp/pe-backup-1970-01-01T000000Z/patching/pe-patching.dump.d "sslmode=verify-ca host=primary user=pe-patching sslcert=/etc/puppetlabs/puppetdb/ssl/primary.cert.pem sslkey=/etc/puppetlabs/puppetdb/ssl/primary.private_key.pem sslrootcert=/etc/puppetlabs/puppet/ssl/certs/ca.pem dbname=pe-patching"' + "\n")
+
+ expect(run_plan('peadm::backup', all_backup_options)).to be_ok
+ end
+ end
+
+ context '>= 2023.7.0 < 2025.0' do
+ let(:pe_version) { '2023.7.0' }
+
+ include_context('all 2023.6.0 backups')
+
+ it 'runs with backup type custom, all backup params set to true' do
+ expect_out_message.with_params('# Backing up database pe-hac')
+
+ expect_command('/opt/puppetlabs/server/bin/pg_dump -Fd -Z3 -j4 -f /tmp/pe-backup-1970-01-01T000000Z/hac/pe-hac.dump.d "sslmode=verify-ca host=primary user=pe-hac sslcert=/etc/puppetlabs/puppetdb/ssl/primary.cert.pem sslkey=/etc/puppetlabs/puppetdb/ssl/primary.private_key.pem sslrootcert=/etc/puppetlabs/puppet/ssl/certs/ca.pem dbname=pe-hac"' + "\n")
+
+ expect(run_plan('peadm::backup', all_backup_options)).to be_ok
+ end
+ end
+
+ context '< 2023.7.0' do
+ let(:pe_version) { '2023.6.0' }
+
+ include_context('all 2023.6.0 backups')
+
+ it 'ignores hac' do
+ expect(run_plan('peadm::backup', all_backup_options)).to be_ok
+ end
+ end
+
+ context 'pe_version unknown' do
+ let(:pe_version) { nil }
+
+ include_context('all 2023.6.0 backups')
+
+ it 'warns that hac is ignored' do
+ expect_out_message.with_params(<<~MSG.strip)
+ WARNING: Retrieved a missing or unparseable PE version of ''.
+ Newer service databases released in 2023.7+ will be skipped from defaults.
+ (host-action-collector, patching)
+ MSG
- expect(run_plan('peadm::backup', all_backup_options)).to be_ok
+ expect(run_plan('peadm::backup', all_backup_options)).to be_ok
+ end
end
end
diff --git a/spec/plans/restore_spec.rb b/spec/plans/restore_spec.rb
index 52754b8e..960e49f0 100644
--- a/spec/plans/restore_spec.rb
+++ b/spec/plans/restore_spec.rb
@@ -24,6 +24,13 @@
'restore_type' => 'recovery-db'
}
end
+ let(:all_recovery_options) do
+ {
+ 'targets' => 'primary',
+ 'input_file' => backup_tarball,
+ 'restore_type' => 'custom', # defaults to all
+ }
+ end
let(:classifier_only_params) do
{
'targets' => 'primary',
@@ -38,11 +45,22 @@
'orchestrator' => false,
'puppetdb' => false,
'rbac' => false,
+ 'hac' => false,
+ 'patching' => false,
}
}
end
- let(:cluster) { { 'params' => { 'primary_host' => 'primary', 'primary_postgresql_host' => 'postgres' } } }
+ let(:pe_version) { '2023.7.0' }
+ let(:cluster) do
+ {
+ 'pe_version' => pe_version,
+ 'params' => {
+ 'primary_host' => 'primary',
+ 'primary_postgresql_host' => 'postgres',
+ },
+ }
+ end
before(:each) do
allow_apply
@@ -57,20 +75,26 @@
expect_task('peadm::get_peadm_config').always_return(cluster)
end
+ def expect_restore_for_db(name, server)
+ database = "pe-#{name}"
+ expect_out_message.with_params("# Restoring database #{database}")
+
+ expect_command(%(su - pe-postgres -s /bin/bash -c "/opt/puppetlabs/server/bin/psql --tuples-only -d '#{database}' -c 'DROP SCHEMA IF EXISTS pglogical CASCADE;'"\n)).be_called_times(2)
+ expect_command(%(su - pe-postgres -s /bin/bash -c "/opt/puppetlabs/server/bin/psql -d '#{database}' -c 'DROP SCHEMA public CASCADE; CREATE SCHEMA public;'"\n))
+ expect_command(%(su - pe-postgres -s /bin/bash -c "/opt/puppetlabs/server/bin/psql -d '#{database}' -c 'ALTER USER \\"#{database}\\" WITH SUPERUSER;'"\n))
+ expect_command(%(/opt/puppetlabs/server/bin/pg_restore -j 4 -d "sslmode=verify-ca host=#{server} sslcert=/etc/puppetlabs/puppetdb/ssl/primary.cert.pem sslkey=/etc/puppetlabs/puppetdb/ssl/primary.private_key.pem sslrootcert=/etc/puppetlabs/puppet/ssl/certs/ca.pem dbname=#{database} user=#{database}" -Fd /input/file/#{name}/#{database}.dump.d\n))
+ expect_command(%(su - pe-postgres -s /bin/bash -c "/opt/puppetlabs/server/bin/psql -d '#{database}' -c 'ALTER USER \\"#{database}\\" WITH NOSUPERUSER;'"\n))
+ expect_command(%(su - pe-postgres -s /bin/bash -c "/opt/puppetlabs/server/bin/psql -d '#{database}' -c 'DROP EXTENSION IF EXISTS pglogical CASCADE;'"\n))
+ end
+
it 'runs with recovery params', valid_cluster: true do
- expect_out_message.with_params('# Restoring database pe-puppetdb')
expect_out_message.with_params('# Restoring ca, certs, code and config for recovery')
expect_command("umask 0077 && cd /input && tar -xzf /input/file.tar.gz\n")
expect_command("/opt/puppetlabs/bin/puppet-backup restore --scope=certs,code,config --tempdir=/input/file --force /input/file/recovery/pe_backup-*tgz\n")
expect_command("systemctl stop pe-console-services pe-nginx pxp-agent pe-puppetserver pe-orchestration-services puppet pe-puppetdb\n")
expect_command("test -f /input/file/rbac/keys.json && cp -rp /input/file/keys.json /etc/puppetlabs/console-services/conf.d/secrets/ || echo secret ldap key doesnt exist\n")
- expect_command("su - pe-postgres -s /bin/bash -c \"/opt/puppetlabs/server/bin/psql --tuples-only -d 'pe-puppetdb' -c 'DROP SCHEMA IF EXISTS pglogical CASCADE;'\"\n").be_called_times(2)
- expect_command("su - pe-postgres -s /bin/bash -c \"/opt/puppetlabs/server/bin/psql -d 'pe-puppetdb' -c 'DROP SCHEMA public CASCADE; CREATE SCHEMA public;'\"\n")
- expect_command('su - pe-postgres -s /bin/bash -c "/opt/puppetlabs/server/bin/psql -d \'pe-puppetdb\' -c \'ALTER USER \\"pe-puppetdb\\" WITH SUPERUSER;\'"' + "\n")
- expect_command('/opt/puppetlabs/server/bin/pg_restore -j 4 -d "sslmode=verify-ca host=postgres sslcert=/etc/puppetlabs/puppetdb/ssl/primary.cert.pem sslkey=/etc/puppetlabs/puppetdb/ssl/primary.private_key.pem sslrootcert=/etc/puppetlabs/puppet/ssl/certs/ca.pem dbname=pe-puppetdb user=pe-puppetdb" -Fd /input/file/puppetdb/pe-puppetdb.dump.d' + "\n")
- expect_command('su - pe-postgres -s /bin/bash -c "/opt/puppetlabs/server/bin/psql -d \'pe-puppetdb\' -c \'ALTER USER \\"pe-puppetdb\\" WITH NOSUPERUSER;\'"' + "\n")
- expect_command('su - pe-postgres -s /bin/bash -c "/opt/puppetlabs/server/bin/psql -d \'pe-puppetdb\' -c \'DROP EXTENSION IF EXISTS pglogical CASCADE;\'"' + "\n")
+ expect_restore_for_db('puppetdb', 'postgres')
expect_command("/opt/puppetlabs/bin/puppet-infrastructure configure --no-recover\n")
expect(run_plan('peadm::restore', recovery_params)).to be_ok
@@ -104,21 +128,113 @@
expect(run_plan('peadm::restore', classifier_only_params)).to be_ok
end
- it 'runs with recovery params, no valid cluster', valid_cluster: false do
- allow_any_command
-
+ def expect_peadm_config_fallback(backup_dir, file)
# simulate a failure to get the cluster configuration
expect_task('peadm::get_peadm_config').always_return({})
expect_out_message.with_params('Failed to get cluster configuration, loading from backup...')
- # download mocked to return the path to the file fixtures/peadm_config.json
+ # download mocked to return the path to a fixtures file
expect_download("#{backup_dir}/peadm/peadm_config.json").return do |targets, _source, _destination, _params|
results = targets.map do |target|
- Bolt::Result.new(target, value: { 'path' => File.expand_path(File.join(fixtures, 'peadm_config.json')) })
+ Bolt::Result.new(target, value: { 'path' => File.expand_path(File.join(fixtures, file)) })
end
Bolt::ResultSet.new(results)
end
+ end
+
+ it 'runs with recovery params, no valid cluster', valid_cluster: false do
+ allow_any_command
+
+ expect_peadm_config_fallback(backup_dir, 'peadm_config.json')
+
expect(run_plan('peadm::restore', recovery_params)).to be_ok
end
+
+ shared_context('all 2023.6.0 backups') do
+ before(:each) do
+ expect_out_message.with_params('# Restoring ca and ssl certificates')
+ expect_out_message.with_params('# Restoring code')
+ expect_out_message.with_params('# Restoring config')
+
+ expect_command("umask 0077 && cd /input && tar -xzf /input/file.tar.gz\n")
+ expect_task('peadm::restore_classification').with_params(
+ {
+ 'classification_file' => "#{backup_dir}/classifier/classification_backup.json",
+ },
+ )
+ expect_command("/opt/puppetlabs/bin/puppet-backup restore --scope=certs --tempdir=/input/file --force /input/file/ca/pe_backup-*tgz\n")
+ expect_command("/opt/puppetlabs/bin/puppet-backup restore --scope=code --tempdir=/input/file --force /input/file/code/pe_backup-*tgz\n")
+ expect_command("/opt/puppetlabs/bin/puppet-backup restore --scope=config --tempdir=/input/file --force /input/file/config/pe_backup-*tgz\n")
+ expect_command("systemctl stop pe-console-services pe-nginx pxp-agent pe-puppetserver pe-orchestration-services puppet pe-puppetdb\n")
+ expect_command("cp -rp /input/file/orchestrator/secrets/* /etc/puppetlabs/orchestration-services/conf.d/secrets/\n")
+ expect_command("test -f /input/file/rbac/keys.json && cp -rp /input/file/keys.json /etc/puppetlabs/console-services/conf.d/secrets/ || echo secret ldap key doesnt exist\n")
+ expect_restore_for_db('activity', 'primary')
+ expect_restore_for_db('orchestrator', 'primary')
+ expect_restore_for_db('puppetdb', 'postgres')
+ expect_restore_for_db('rbac', 'primary')
+ expect_command("/opt/puppetlabs/bin/puppet-infrastructure configure --no-recover\n")
+ end
+ end
+
+ context '>= 2025.0.0' do
+ let(:pe_version) { '2025.0.0' }
+
+ include_context('all 2023.6.0 backups')
+
+ it 'runs with backup type custom, all params set to true', valid_cluster: true do
+ expect_restore_for_db('hac', 'primary')
+ expect_restore_for_db('patching', 'primary')
+
+ expect(run_plan('peadm::restore', all_recovery_options)).to be_ok
+ end
+ end
+
+ context '>= 2023.7.0 < 2025.0' do
+ let(:pe_version) { '2023.7.0' }
+
+ include_context('all 2023.6.0 backups')
+
+ it 'runs with backup type custom, all params set to true', valid_cluster: true do
+ expect_restore_for_db('hac', 'primary')
+
+ expect(run_plan('peadm::restore', all_recovery_options)).to be_ok
+ end
+ end
+
+ context '< 2023.7.0' do
+ let(:pe_version) { '2023.6.0' }
+
+ include_context('all 2023.6.0 backups')
+
+ it 'ignores hac', valid_cluster: true do
+ expect(run_plan('peadm::restore', all_recovery_options)).to be_ok
+ end
+ end
+
+ # restoring an older backup that does not have the pe_version in it
+ context 'no valid cluster, pe_version missing from recovery params (older backup)' do
+ let(:cluster) do
+ {
+ 'params' => {
+ 'primary_host' => 'primary',
+ 'primary_postgresql_host' => 'postgres',
+ },
+ }
+ end
+
+ include_context('all 2023.6.0 backups')
+
+ it 'warns that hac is ignored', valid_cluster: false do
+ expect_out_message.with_params(<<~MSG.strip)
+ WARNING: Retrieved a missing or unparseable PE version of ''.
+ Newer service databases released in 2023.7+ will be skipped from defaults.
+ (host-action-collector, patching)
+ MSG
+
+ expect_peadm_config_fallback(backup_dir, 'peadm_config.no_pe_version.json')
+
+ expect(run_plan('peadm::restore', all_recovery_options)).to be_ok
+ end
+ end
end
diff --git a/types/recovery_opts.pp b/types/recovery_opts.pp
index eb392752..eacfd532 100644
--- a/types/recovery_opts.pp
+++ b/types/recovery_opts.pp
@@ -7,4 +7,6 @@
'orchestrator' => Optional[Boolean],
'puppetdb' => Optional[Boolean],
'rbac' => Optional[Boolean],
+ 'hac' => Optional[Boolean],
+ 'patching' => Optional[Boolean],
}]