Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add experimental backup plan #235

Merged
merged 3 commits into from
Apr 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"python.linting.pylintEnabled": true,
"python.linting.enabled": true
}
10 changes: 10 additions & 0 deletions functions/recovery_opts_default.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
function peadm::recovery_opts_default () {
{
'orchestrator' => true,
'puppetdb' => true,
'rbac' => true,
'activity' => true,
'ca' => false,
'classifier' => true,
}
}
127 changes: 84 additions & 43 deletions plans/backup.pp
Original file line number Diff line number Diff line change
@@ -1,77 +1,118 @@
# @summary Backup the core user settings for puppet infrastructure
#
# This plan can backup data as outlined at insert doc
# This plan can backup data as outlined at insert doc
#
plan peadm::backup (
Peadm::SingleTargetSpec $primary_host,
# This plan should be run on the primary server
Peadm::SingleTargetSpec $targets,

# Which data to backup
Boolean $backup_orchestrator = true,
Boolean $backup_rbac = true,
Boolean $backup_activity = true,
Boolean $backup_ca_ssl = true,
Boolean $backup_puppetdb = false,
Boolean $backup_classification = true,
String $output_directory = '/tmp',
Peadm::Recovery_opts $backup = {},

# Where to put the backup folder
String $output_directory = '/tmp',
) {
peadm::assert_supported_bolt_version()
$cluster = run_task('peadm::get_peadm_config', $primary_host).first

$recovery_opts = (peadm::recovery_opts_default() + $backup)
$cluster = run_task('peadm::get_peadm_config', $targets).first.value
$arch = peadm::assert_supported_architecture(
$primary_host,
$cluster['replica_host'],
$cluster['primary_postgresql_host'],
$cluster['replica_postgresql_host'],
$cluster['compiler_hosts'],
getvar('cluster.params.primary_host'),
getvar('cluster.params.replica_host'),
getvar('cluster.params.primary_postgresql_host'),
getvar('cluster.params.replica_postgresql_host'),
getvar('cluster.params.compiler_hosts'),
)

$timestamp = Timestamp.new().strftime('%F_%T')
$timestamp = Timestamp.new().strftime('%Y-%m-%dT%H%M%SZ')
$backup_directory = "${output_directory}/pe-backup-${timestamp}"

# Create backup folder
apply($primary_host){
$primary_target = getvar('cluster.params.primary_host')
$puppetdb_postgresql_target = getvar('cluster.params.primary_postgresql_host') ? {
undef => getvar('cluster.params.primary_host'),
default => getvar('cluster.params.primary_postgresql_host'),
}

$backup_databases = {
'orchestrator' => $primary_target,
'activity' => $primary_target,
'rbac' => $primary_target,
'puppetdb' => $puppetdb_postgresql_target,
}.filter |$key,$_| {
$recovery_opts[$key] == true
}

# Create backup folders
apply($primary_target) {
file { $backup_directory :
ensure => 'directory',
owner => 'root',
group => 'pe-postgres',
mode => '0770'
group => 'root',
mode => '0700'
}
}

# Create an array of the names of databases and whether they have to be backed up to use in a lambda later
$database_to_backup = [ $backup_orchestrator, $backup_activity, $backup_rbac, $backup_puppetdb]
$database_names = [ 'pe-orchestrator' , 'pe-activity' , 'pe-rbac' , 'pe-puppetdb' ]
# Create a subdir for each backup type selected
$recovery_opts.filter |$_,$val| { $val == true }.each |$dir,$_| {
file { "${backup_directory}/${dir}":
ensure => 'directory',
owner => 'root',
group => 'root',
mode => '0700'
}
}
}

if $backup_classification {
if getvar('recovery_opts.classifier') {
out::message('# Backing up classification')
run_task('peadm::backup_classification', $primary_host,
directory => $backup_directory,
run_task('peadm::backup_classification', $primary_target,
directory => "${backup_directory}/classifier",
)
}

if $backup_ca_ssl {
if getvar('recovery_opts.ca') {
out::message('# Backing up ca and ssl certificates')
run_command("/opt/puppetlabs/bin/puppet-backup create --dir=${backup_directory} --scope=certs", $primary_host)
run_command(@("CMD"), $primary_target)
/opt/puppetlabs/bin/puppet-backup create --dir=${shellquote($backup_directory)}/ca --scope=certs
| CMD
}

# Check if /etc/puppetlabs/console-services/conf.d/secrets/keys.json exists and if so back it up
out::message('# Backing up ldap secret key if it exists')
run_command("test -f /etc/puppetlabs/console-services/conf.d/secrets/keys.json && cp -rp /etc/puppetlabs/console-services/conf.d/secrets/keys.json ${backup_directory} || echo secret ldap key doesnt exist" , $primary_host) # lint:ignore:140chars
if getvar('recovery_opts.rbac') {
out::message('# Backing up ldap secret key if it exists')
run_command(@("CMD"/L), $primary_target)
test -f /etc/puppetlabs/console-services/conf.d/secrets/keys.json \
&& cp -rp /etc/puppetlabs/console-services/conf.d/secrets ${shellquote($backup_directory)}/rbac/ \
|| echo secret ldap key doesnt exist
| CMD
}

# IF backing up orchestrator back up the secrets too /etc/puppetlabs/orchestration-services/conf.d/secrets/
if $backup_orchestrator {
if getvar('recovery_opts.orchestrator') {
out::message('# Backing up orchestrator secret keys')
run_command("cp -rp /etc/puppetlabs/orchestration-services/conf.d/secrets ${backup_directory}/", $primary_host)
run_command(@("CMD"), $primary_target)
cp -rp /etc/puppetlabs/orchestration-services/conf.d/secrets ${shellquote($backup_directory)}/orchestrator/
| CMD
}

$database_to_backup.each |Integer $index, Boolean $value | {
if $value {
out::message("# Backing up database ${database_names[$index]}")
# If the primary postgresql host is set then pe-puppetdb needs to be remotely backed up to primary.
if $database_names[$index] == 'pe-puppetdb' and $cluster['primary_postgresql_host'] {
run_command("sudo -u pe-puppetdb /opt/puppetlabs/server/bin/pg_dump \"sslmode=verify-ca host=${cluster['primary_postgresql_host']} sslcert=/etc/puppetlabs/puppetdb/ssl/${primary_host}.cert.pem sslkey=/etc/puppetlabs/puppetdb/ssl/${primary_host}.private_key.pem sslrootcert=/etc/puppetlabs/puppet/ssl/certs/ca.pem dbname=pe-puppetdb\" -f /tmp/puppetdb_$(date +%F_%T).bin" , $primary_host) # lint:ignore:140chars
} else {
run_command("sudo -u pe-postgres /opt/puppetlabs/server/bin/pg_dump -Fc \"${database_names[$index]}\" -f \"${backup_directory}/${database_names[$index]}_$(date +%F_%T).bin\"" , $primary_host) # lint:ignore:140chars
}
}
$backup_databases.each |$name,$database_target| {
run_command(@("CMD"/L), $primary_target)
/opt/puppetlabs/server/bin/pg_dump -Fd -Z3 -j4 \
-f ${shellquote($backup_directory)}/${shellquote($name)}/pe-${shellquote($name)}.dump.d \
"sslmode=verify-ca \
host=${shellquote($database_target.peadm::certname())} \
user=pe-${shellquote($name)} \
sslcert=/etc/puppetlabs/puppetdb/ssl/${shellquote($primary_target.peadm::certname())}.cert.pem \
sslkey=/etc/puppetlabs/puppetdb/ssl/${shellquote($primary_target.peadm::certname())}.private_key.pem \
sslrootcert=/etc/puppetlabs/puppet/ssl/certs/ca.pem \
dbname=pe-${shellquote($name)}"
| CMD
}

run_command(@("CMD"/L), $primary_target)
umask 0077 \
&& tar -czf ${shellquote($backup_directory)}.tar.gz ${shellquote($backup_directory)} \
&& rm -rf ${shellquote($backup_directory)}
| CMD

return({'path' => "${backup_directory}.tar.gz"})
}
4 changes: 3 additions & 1 deletion spec/plans/backup_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@

it 'runs with default params' do
allow_apply
pending('a lack of support for functions requires a workaround to be written')
expect_task('peadm::get_peadm_config').always_return({ 'primary_postgresql_host' => 'postgres' })
expect_out_message.with_params('# Backing up ca and ssl certificates')
# The commands all have a timestamp in them and frankly its prooved to hard with bolt spec to work this out
# The commands all have a timestamp in them and frankly its proved to hard with bolt spec to work this out
allow_any_command
allow_apply
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')
Expand Down
8 changes: 8 additions & 0 deletions types/recovery_opts.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
type Peadm::Recovery_opts = Struct[{
'orchestrator' => Optional[Boolean],
'puppetdb' => Optional[Boolean],
'rbac' => Optional[Boolean],
'activity' => Optional[Boolean],
'ca' => Optional[Boolean[false]],
'classifier' => Optional[Boolean],
}]