Changeset - 35140b3eb5b8
[Not reviewed]
0 4 0
Branko Majic (branko) - 22 months ago 2024-02-14 22:49:37
branko@majic.rs
MAR-198: Implement removal of expired backups via backup_client role:

- In addition to expired backup removals, ensure that the backup
does not proceed if previous execution step has failed. This means
that pre-scripts now have to run without errors for the main backup
to kick-in.
- Could not use full _and_ chaining of duply. For example, if we have
A_and_B_and_C (where A/B/C are duply backup commands), if A
fails, B will be skipped, but C will still run because B has ran
without_errors.
4 files changed with 16 insertions and 3 deletions:
0 comments (0 inline, 0 general)
docs/releasenotes.rst
Show inline comments
 
@@ -4,24 +4,34 @@ Release notes
 

	
 
x.y.z
 
-----
 

	
 
Dropped support for Debian 10 (Buster).
 

	
 
**Breaking changes:**
 

	
 
* All roles
 

	
 
  * Dropped support for Debian 10 (Buster).
 

	
 
* ``backup_client`` role
 

	
 
  * Previously the backup would run even if pre-backup scripts would
 
    fail. This is no longer the case, and all pre-backup scripts must
 
    exit with non-zero exit code in order for backup process to
 
    kick-in.
 
  * Old backups are now automatically purged after successful
 
    backup. This could lead to longer runtimes for entire backup
 
    process, as well as higher CPU usage.
 

	
 
* ``common`` role
 

	
 
  * Dropped support for Python 2.7 pip requirements upgrade
 
    checks. Only Python 3 is supported now.
 

	
 
    Requirements (input) files for Python 3 are now put under the
 
    ``/etc/pip_check_requirements_upgrades`` directory instead of
 
    ``/etc/pip_check_requirements_upgrades-py3``.
 

	
 
    The ``pip_check_requirements_py3`` /
 
    ``pip_check_requirements_py3_in`` role parameters have been
 
    renamed to ``pip_check_requirements`` /
docs/rolereference.rst
Show inline comments
 
@@ -2271,24 +2271,27 @@ Duply is configured as follows:
 
  location ``/etc/duply/main/ssh/known_hosts``.
 
* Base directory for back-ups is root (``/``), but *all* files are excluded by
 
  default to prevent huge back-ups. Ansible roles that want to utilise the
 
  backup client role can specify which patterns should be included in the backup
 
  when including the ``backup`` role. Include pattern file is assembled and
 
  stored in location ``/etc/duply/main/include``.
 
* Backups are encrypted and signed with the specified encryption key.
 
* Maximum age for old backups is set to 6 months.
 
* Maximum age for full backups is set to 1 month.
 
* Volume size is set to 1GB.
 
* Pre-backup scripts are run via ``/etc/duply/main/pre`` handler that tries to
 
  execute scripts/binaries from directory ``/etc/duply/main/pre.d/``.
 
* Pre-backup scripts must run successfully for the actual backup
 
  process to proceed.
 
* Old backups are automatically purged in case of successful run.
 

	
 
.. note::
 
   Since at time of this writing there are no lookup plugins for extracting key
 
   material/information from GnuPG keyring, you may want to resort to extraction
 
   of keys on the controller machine via lookups similar to::
 

	
 
     lookup('pipe', 'gpg2 --homedir /path/to/your/keyring --armor --export some_identifier')
 
     lookup('pipe', 'gpg2 --homedir /path/to/your/keyring --armor --export-secret-keys some_identifier')
 

	
 
   This may not be the most elegant solution, but for now it offers better
 
   flexibility (theoretically, you could store all those keys etc as plaintext
 
   files instead).
roles/backup_client/molecule/default/tests/test_default.py
Show inline comments
 
@@ -164,25 +164,25 @@ def test_pre_backup_script(host):
 

	
 
def test_cron_entry(host):
 
    """
 
    Tests if cron job has been correctly set-up for running backups.
 
    """
 

	
 
    cron = host.file('/etc/cron.d/backup')
 

	
 
    assert cron.is_file
 
    assert cron.user == 'root'
 
    assert cron.group == 'root'
 
    assert cron.mode == 0o644
 
    assert cron.content_string == "#Ansible: backup\n0 2 * * * root /usr/bin/duply main backup\n"
 
    assert cron.content_string == "#Ansible: backup\n0 2 * * * root /usr/bin/duply main pre_and_bkp && /usr/bin/duply main post_and_purge --force\n"
 

	
 

	
 
def test_duply_include_file(host):
 
    """
 
    Tests include file existence and permissions.
 
    """
 

	
 
    with host.sudo():
 

	
 
        include = host.file('/etc/duply/main/include')
 

	
 
        assert include.is_file
 
@@ -193,24 +193,24 @@ def test_duply_include_file(host):
 

	
 
def test_backup_and_restore(host):
 
    """
 
    Tests a simple backup and restore to a directory. Includes tests for
 
    checking if the pre-backup handles are run correctly.
 
    """
 

	
 
    with host.sudo():
 

	
 
        # Remove this file so we can be sure the pre-backup script has been run.
 
        host.ansible("file", "path=/var/lib/pre-backup-test state=absent")
 

	
 
        backup_run = host.run('duply main backup')
 
        backup_run = host.run('duply main pre_and_bkp')
 

	
 
        assert backup_run.rc == 0
 
        assert host.file('/var/lib/pre-backup-test').is_file
 

	
 
        # Remove restore directory in order to make sure restore has worked
 
        # correctly.
 
        host.ansible("file", "path=/root/restore state=absent")
 

	
 
        restore_run = host.run('duply main restore /root/restore')
 
        assert restore_run.rc == 0
 
        assert host.file('/root/restore').is_directory
roles/backup_client/tasks/main.yml
Show inline comments
 
@@ -122,25 +122,25 @@
 
    src: "duply_pre"
 
    dest: "/etc/duply/main/pre"
 
    owner: root
 
    group: root
 
    mode: 0700
 

	
 
- name: Deploy crontab entry for running backups
 
  cron:
 
    name: backup
 
    cron_file: backup
 
    hour: "2"
 
    minute: "0"
 
    job: "/usr/bin/duply main backup"
 
    job: "/usr/bin/duply main pre_and_bkp && /usr/bin/duply main post_and_purge --force"
 
    state: present
 
    user: root
 

	
 
- name: Ensure the file with include patterns exists (but do not overwrite)
 
  copy:
 
    content: ""
 
    dest: /etc/duply/main/include
 
    force: false
 
    group: root
 
    owner: root
 
    mode: 0600
 

	
0 comments (0 inline, 0 general)