diff --git a/manifests/backup/mysqldump.pp b/manifests/backup/mysqldump.pp index 5c57a50..29c68d3 100644 --- a/manifests/backup/mysqldump.pp +++ b/manifests/backup/mysqldump.pp @@ -1,108 +1,110 @@ # @summary # "Provider" for mysqldump # @api private # class mysql::backup::mysqldump ( $backupuser = '', $backuppassword = '', $backupdir = '', $maxallowedpacket = '1M', $backupdirmode = '0700', $backupdirowner = 'root', $backupdirgroup = $mysql::params::root_group, $backupcompress = true, $backuprotate = 30, $backupmethod = 'mysqldump', $backup_success_file_path = undef, $ignore_events = true, $delete_before_dump = false, $backupdatabases = [], $file_per_database = false, $include_triggers = false, $include_routines = false, $ensure = 'present', $time = ['23', '5'], $prescript = false, $postscript = false, $execpath = '/usr/bin:/usr/sbin:/bin:/sbin', $optional_args = [], $mysqlbackupdir_ensure = 'directory', $mysqlbackupdir_target = undef, $incremental_backups = false, $install_cron = true, + $compression_command = 'bzcat -zc', + $compression_extension = '.bz2' ) inherits mysql::params { unless $::osfamily == 'FreeBSD' { - if $backupcompress { + if $backupcompress and $compression_command == 'bzcat -zc' { ensure_packages(['bzip2']) Package['bzip2'] -> File['mysqlbackup.sh'] } } mysql_user { "${backupuser}@localhost": ensure => $ensure, password_hash => mysql::password($backuppassword), require => Class['mysql::server::root_password'], } if $include_triggers { $privs = ['SELECT', 'RELOAD', 'LOCK TABLES', 'SHOW VIEW', 'PROCESS', 'TRIGGER'] } else { $privs = ['SELECT', 'RELOAD', 'LOCK TABLES', 'SHOW VIEW', 'PROCESS'] } mysql_grant { "${backupuser}@localhost/*.*": ensure => $ensure, user => "${backupuser}@localhost", table => '*.*', privileges => $privs, require => Mysql_user["${backupuser}@localhost"], } if $install_cron { if $::osfamily == 'RedHat' and $::operatingsystemmajrelease == '5' { ensure_packages('crontabs') } elsif $::osfamily == 'RedHat' { ensure_packages('cronie') } elsif $::osfamily != 'FreeBSD' { ensure_packages('cron') } } cron { 'mysql-backup': ensure => $ensure, command => '/usr/local/sbin/mysqlbackup.sh', user => 'root', hour => $time[0], minute => $time[1], monthday => $time[2], month => $time[3], weekday => $time[4], require => File['mysqlbackup.sh'], } file { 'mysqlbackup.sh': ensure => $ensure, path => '/usr/local/sbin/mysqlbackup.sh', mode => '0700', owner => 'root', group => $mysql::params::root_group, content => template('mysql/mysqlbackup.sh.erb'), } if $mysqlbackupdir_target { file { $backupdir: ensure => $mysqlbackupdir_ensure, target => $mysqlbackupdir_target, mode => $backupdirmode, owner => $backupdirowner, group => $backupdirgroup, } } else { file { $backupdir: ensure => $mysqlbackupdir_ensure, mode => $backupdirmode, owner => $backupdirowner, group => $backupdirgroup, } } } diff --git a/manifests/server/backup.pp b/manifests/server/backup.pp index f89063a..222d5c3 100644 --- a/manifests/server/backup.pp +++ b/manifests/server/backup.pp @@ -1,132 +1,140 @@ # @summary # Create and manage a MySQL backup. # # @example Create a basic MySQL backup: # class { 'mysql::server': # root_password => 'password' # } # class { 'mysql::server::backup': # backupuser => 'myuser', # backuppassword => 'mypassword', # backupdir => '/tmp/backups', # } # class { 'mysql::server::backup': # backupmethod => 'mariabackup', # provider => 'xtrabackup', # backupdir => '/tmp/backups', # } # # @param backupuser # MySQL user to create with backup administrator privileges. # @param backuppassword # Password to create for `backupuser`. # @param backupdir # Directory to store backup. # @param backupdirmode # Permissions applied to the backup directory. This parameter is passed directly to the file resource. # @param backupdirowner # Owner for the backup directory. This parameter is passed directly to the file resource. # @param backupdirgroup # Group owner for the backup directory. This parameter is passed directly to the file resource. # @param backupcompress # Whether or not to compress the backup (when using the mysqldump or xtrabackup provider) # @param backupmethod # The execution binary for backing up. ex. mysqldump, xtrabackup, mariabackup # @param backup_success_file_path # Specify a path where upon successfull backup a file should be created for checking purposes. # @param backuprotate # Backup rotation interval in 24 hour periods. # @param ignore_events # Ignore the mysql.event table. # @param delete_before_dump # Whether to delete old .sql files before backing up. Setting to true deletes old files before backing up, while setting to false deletes them after backup. # @param backupdatabases # Databases to backup (required if using xtrabackup provider). By default `[]` will back up all databases. # @param file_per_database # Use file per database mode creating one file per database backup. # @param include_routines # Dump stored routines (procedures and functions) from dumped databases when doing a `file_per_database` backup. # @param include_triggers # Dump triggers for each dumped table when doing a `file_per_database` backup. # @param incremental_backups # A flag to activate/deactivate incremental backups. Currently only supported by the xtrabackup provider. # @param ensure # @param time # An array of two elements to set the backup time. Allows ['23', '5'] (i.e., 23:05) or ['3', '45'] (i.e., 03:45) for HH:MM times. # @param prescript # A script that is executed before the backup begins. # @param postscript # A script that is executed when the backup is finished. This could be used to sync the backup to a central store. This script can be either a single line that is directly executed or a number of lines supplied as an array. It could also be one or more externally managed (executable) files. # @param execpath # Allows you to set a custom PATH should your MySQL installation be non-standard places. Defaults to `/usr/bin:/usr/sbin:/bin:/sbin`. # @param provider # Sets the server backup implementation. Valid values are: # @param maxallowedpacket # Defines the maximum SQL statement size for the backup dump script. The default value is 1MB, as this is the default MySQL Server value. # @param optional_args # Specifies an array of optional arguments which should be passed through to the backup tool. (Supported by the xtrabackup and mysqldump providers.) # @param install_cron # Manage installation of cron package +# @param compression_command +# Configure the command used to compress the backup (when using the mysqldump provider) +# @param compression_extension +# Configure the file extension for the compressed backup (when using the mysqldump provider) class mysql::server::backup ( $backupuser = undef, $backuppassword = undef, $backupdir = undef, $backupdirmode = '0700', $backupdirowner = 'root', $backupdirgroup = $mysql::params::root_group, $backupcompress = true, $backuprotate = 30, $backupmethod = undef, $backup_success_file_path = '/tmp/mysqlbackup_success', $ignore_events = true, $delete_before_dump = false, $backupdatabases = [], $file_per_database = false, $include_routines = false, $include_triggers = false, $ensure = 'present', $time = ['23', '5'], $prescript = false, $postscript = false, $execpath = '/usr/bin:/usr/sbin:/bin:/sbin', $provider = 'mysqldump', $maxallowedpacket = '1M', $optional_args = [], $incremental_backups = true, $install_cron = true, + $compression_command = undef, + $compression_extension = undef ) inherits mysql::params { if $prescript and $provider =~ /(mysqldump|mysqlbackup)/ { warning(translate("The 'prescript' option is not currently implemented for the %{provider} backup provider.", { 'provider' => $provider })) } create_resources('class', { "mysql::backup::${provider}" => { 'backupuser' => $backupuser, 'backuppassword' => $backuppassword, 'backupdir' => $backupdir, 'backupdirmode' => $backupdirmode, 'backupdirowner' => $backupdirowner, 'backupdirgroup' => $backupdirgroup, 'backupcompress' => $backupcompress, 'backuprotate' => $backuprotate, 'backupmethod' => $backupmethod, 'backup_success_file_path' => $backup_success_file_path, 'ignore_events' => $ignore_events, 'delete_before_dump' => $delete_before_dump, 'backupdatabases' => $backupdatabases, 'file_per_database' => $file_per_database, 'include_routines' => $include_routines, 'include_triggers' => $include_triggers, 'ensure' => $ensure, 'time' => $time, 'prescript' => $prescript, 'postscript' => $postscript, 'execpath' => $execpath, 'maxallowedpacket' => $maxallowedpacket, 'optional_args' => $optional_args, 'incremental_backups' => $incremental_backups, 'install_cron' => $install_cron, + 'compression_command' => $compression_command, + 'compression_extension' => $compression_extension, } }) } diff --git a/spec/classes/mysql_backup_mysqldump_spec.rb b/spec/classes/mysql_backup_mysqldump_spec.rb index b9dfbcf..4e97ad9 100644 --- a/spec/classes/mysql_backup_mysqldump_spec.rb +++ b/spec/classes/mysql_backup_mysqldump_spec.rb @@ -1,58 +1,76 @@ # frozen_string_literal: true require 'spec_helper' describe 'mysql::backup::mysqldump' do on_supported_os.each do |os, facts| context "on #{os}" do let(:pre_condition) do <<-EOF class { 'mysql::server': } EOF end let(:facts) do facts.merge(root_home: '/root') end let(:default_params) do { 'backupuser' => 'testuser', 'backuppassword' => 'testpass', 'backupdir' => '/tmp/mysql-backup', 'backuprotate' => '25', 'delete_before_dump' => true, 'execpath' => '/usr/bin:/usr/sbin:/bin:/sbin:/opt/zimbra/bin', 'maxallowedpacket' => '1M' } end context 'with time included' do let(:params) do { time: [23, 59, 30, 12, 6] }.merge(default_params) end it { is_expected.to contain_cron('mysql-backup').with( hour: 23, minute: 59, monthday: 30, month: 12, weekday: 6, ) } end context 'with defaults' do let(:params) { default_params } it { is_expected.to contain_cron('mysql-backup').with( command: '/usr/local/sbin/mysqlbackup.sh', ensure: 'present', hour: 23, minute: 5, ) } end + + context 'with compression_command' do + let(:params) do + { + compression_command: "TEST -TEST", + compression_extension: ".TEST" + }.merge(default_params) + end + it { + is_expected.to contain_file('mysqlbackup.sh').with_content( + %r{(\| TEST -TEST)}, + ) + is_expected.to contain_file('mysqlbackup.sh').with_content( + %r{(\.TEST)}, + ) + is_expected.to_not contain_package('bzip2') + } + end end end # rubocop:enable RSpec/NestedGroups end diff --git a/templates/mysqlbackup.sh.erb b/templates/mysqlbackup.sh.erb index 19706fb..aea8cae 100755 --- a/templates/mysqlbackup.sh.erb +++ b/templates/mysqlbackup.sh.erb @@ -1,125 +1,125 @@ <%- if @kernel == 'Linux' -%> #!/bin/bash <%- else -%> #!/bin/sh <%- end -%> # # MySQL Backup Script # Dumps mysql databases to a file for another backup tool to pick up. # # MySQL code: # GRANT SELECT, RELOAD, LOCK TABLES ON *.* TO 'user'@'localhost' # IDENTIFIED BY 'password'; # FLUSH PRIVILEGES; # ##### START CONFIG ################################################### USER=<%= @backupuser %> PASS='<%= @backuppassword %>' MAX_ALLOWED_PACKET=<%= @maxallowedpacket %> DIR=<%= @backupdir %> ROTATE=<%= [ Integer(@backuprotate) - 1, 0 ].max %> # Create temporary mysql cnf file. TMPFILE=`mktemp /tmp/backup.XXXXXX` || exit 1 <%- if @kernel == 'SunOS' -%> echo "[client]\npassword=$PASS\nuser=$USER\nmax_allowed_packet=$MAX_ALLOWED_PACKET" > $TMPFILE <%- else -%> echo -e "[client]\npassword=$PASS\nuser=$USER\nmax_allowed_packet=$MAX_ALLOWED_PACKET" > $TMPFILE <%- end -%> <% if @prescript -%> <%- [@prescript].flatten.compact.each do |script|%> <%= script %> <%- end -%> <% end -%> # Ensure backup directory exist. mkdir -p $DIR PREFIX=mysql_backup_ <% if @ignore_events %> ADDITIONAL_OPTIONS="--ignore-table=mysql.event" <% else %> ADDITIONAL_OPTIONS="--events" <% end %> <%# Only include routines or triggers if we're doing a file per database -%> <%# backup. This happens if we named databases, or if we explicitly set -%> <%# file per database mode -%> <% if !@backupdatabases.empty? || @file_per_database -%> <% if @include_triggers -%> ADDITIONAL_OPTIONS="$ADDITIONAL_OPTIONS --triggers" <% else -%> ADDITIONAL_OPTIONS="$ADDITIONAL_OPTIONS --skip-triggers" <% end -%> <% if @include_routines -%> ADDITIONAL_OPTIONS="$ADDITIONAL_OPTIONS --routines" <% else -%> ADDITIONAL_OPTIONS="$ADDITIONAL_OPTIONS --skip-routines" <% end -%> <% end -%> <%- if @optional_args and @optional_args.is_a?(Array) -%> <%- @optional_args.each do |arg| -%> ADDITIONAL_OPTIONS="$ADDITIONAL_OPTIONS <%= arg %>" <%- end -%> <%- end -%> ##### STOP CONFIG #################################################### PATH=<%= @execpath %> <%- if @kernel == 'Linux' -%> set -o pipefail <%- end -%> cleanup() { <%- if @kernel == 'SunOS' -%> gfind "${DIR}/" -maxdepth 1 -type f -name "${PREFIX}*.sql*" -mtime +${ROTATE} -print0 | gxargs -0 -r rm -f <%- else -%> find "${DIR}/" -maxdepth 1 -type f -name "${PREFIX}*.sql*" -mtime +${ROTATE} -print0 | xargs -0 -r rm -f <%- end -%> } <% if @delete_before_dump -%> cleanup <% end -%> <% if @backupdatabases.empty? -%> <% if @file_per_database -%> mysql --defaults-extra-file=$TMPFILE -s -r -N -e 'SHOW DATABASES' | while read dbname do <%= @backupmethod -%> --defaults-extra-file=$TMPFILE --opt --flush-logs --single-transaction \ ${ADDITIONAL_OPTIONS} \ - ${dbname} <% if @backupcompress %>| bzcat -zc <% end %>> ${DIR}/${PREFIX}${dbname}_`date +%Y%m%d-%H%M%S`.sql<% if @backupcompress %>.bz2<% end %> + ${dbname} <% if @backupcompress %>| <%= @compression_command %> <% end %>> ${DIR}/${PREFIX}${dbname}_`date +%Y%m%d-%H%M%S`.sql<% if @backupcompress %><%= @compression_extension %><% end %> done <% else -%> <%= @backupmethod -%> --defaults-extra-file=$TMPFILE --opt --flush-logs --single-transaction \ ${ADDITIONAL_OPTIONS} \ - --all-databases <% if @backupcompress %>| bzcat -zc <% end %>> ${DIR}/${PREFIX}`date +%Y%m%d-%H%M%S`.sql<% if @backupcompress %>.bz2<% end %> + --all-databases <% if @backupcompress %>| <%= @compression_command %> <% end %>> ${DIR}/${PREFIX}`date +%Y%m%d-%H%M%S`.sql<% if @backupcompress %><%= @compression_extension %><% end %> <% end -%> <% else -%> <% @backupdatabases.each do |db| -%> <%= @backupmethod -%> --defaults-extra-file=$TMPFILE --opt --flush-logs --single-transaction \ ${ADDITIONAL_OPTIONS} \ - <%= db %><% if @backupcompress %>| bzcat -zc <% end %>> ${DIR}/${PREFIX}<%= db %>_`date +%Y%m%d-%H%M%S`.sql<% if @backupcompress %>.bz2<% end %> + <%= db %><% if @backupcompress %>| <%= @compression_command %> <% end %>> ${DIR}/${PREFIX}<%= db %>_`date +%Y%m%d-%H%M%S`.sql<% if @backupcompress %><%= @compression_extension %><% end %> <% end -%> <% end -%> <% unless @delete_before_dump -%> if [ $? -eq 0 ] ; then cleanup touch <%= @backup_success_file_path %> fi <% end -%> <% if @postscript -%> <%- [@postscript].flatten.compact.each do |script|%> <%= script %> <%- end -%> <% end -%> # Remove temporary file rm -f $TMPFILE