From f385bfcb733bcfd8cadc740533365cdcbb91f12b Mon Sep 17 00:00:00 2001 From: L3D Date: Tue, 15 Jun 2021 19:48:23 +0200 Subject: [PATCH 1/4] Start improving systemd --- README.md | 5 +++-- defaults/main.yml | 4 ++++ tasks/configure.yml | 2 +- tasks/timer.yml | 17 ----------------- templates/restic.timer.j2 | 4 ++-- 5 files changed, 10 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 2e732d3..16905f1 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,8 @@ Available variables: | `keep_within` | no | If set, only keeps snapshots in this time period. | | `keep_tag` | no | If set, keep snapshots with this tags. Make sure to specify a list. | | `prune` | no (`false`) | If `true`, the `restic forget` command in the script has the [`--prune` option](https://restic.readthedocs.io/en/stable/060_forget.html#removing-backup-snapshots) appended. | -| `scheduled` | no (`false`) | If `restic_create_cron` is set to `true`, this backup is scheduled. | +| `scheduled` | no (`false`) | If `restic_create_cron` is set to `true`, this backup is scheduled and tries to create a systemd timer unit. If it fails, it is creating a cronjob. | +| `schedule_oncalendar` | ``'*-*-* 02:00:00'`` | The time for the systemd timer. Please notice the randomDelaySec option. By Default the backup is done every night at 2 am (+0-4h). But only if scheduled is true. | | `schedule_minute` | no (`*`) | Minute when the job is run. ( 0-59, *, */2, etc ) | | `schedule_hour` | no (`*`) | Hour when the job is run. ( 0-23, *, */2, etc ) | | `schedule_weekday` | no (`*`) | Weekday when the job is run. ( 0-6 for Sunday-Saturday, *, etc ) | @@ -151,7 +152,7 @@ restic_backups: repo: remove src: /path/to/data scheduled: true - schedule_hour: 3 + schedule_oncalendar: '*-*-* 01:00:00' ``` > You can also specify restic_backups as an array, which is a legacy feature and diff --git a/defaults/main.yml b/defaults/main.yml index b9af5df..01d4385 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -13,5 +13,9 @@ restic_create_cron: false restic_dir_owner: '{{ ansible_user | default(ansible_user_id) }}' restic_dir_group: '{{ ansible_user | default(ansible_user_id) }}' +# timer defaults +restic_systemd_timer_randomizeddelaysec: '4h' +restic_systemd_timer_default_OnCalendar: '*-*-* 02:00:00' + # perform simple version check for this role? (true is recomended) submodules_versioncheck: false diff --git a/tasks/configure.yml b/tasks/configure.yml index 9e09609..d3d7049 100644 --- a/tasks/configure.yml +++ b/tasks/configure.yml @@ -23,4 +23,4 @@ loop: "{{ restic_repos|dict2items }}" when: - item.value.init is defined - - item.value.init + - item.value.init|bool diff --git a/tasks/timer.yml b/tasks/timer.yml index 90f71db..cf3b48d 100644 --- a/tasks/timer.yml +++ b/tasks/timer.yml @@ -1,21 +1,4 @@ --- -- name: cleanup old CRON jobs from migration - ansible.builtin.cron: - name: 'arillso.restic backup {{ item.name }}' - job: 'CRON=true {{ restic_script_dir }}/backup-{{ item.name }}.sh' - minute: '{{ item.schedule_minute | default("*") }}' - hour: '{{ item.schedule_hour | default("*") }}' - weekday: '{{ item.schedule_weekday | default("*") }}' - month: '{{ item.schedule_month | default("*") }}' - state: absent - become: true - no_log: true - with_items: '{{ restic_backups }}' - when: - - restic_create_cron - - item.name is defined - - item.scheduled | default(false) - - name: create systemd timer block: - name: copy systemd timer diff --git a/templates/restic.timer.j2 b/templates/restic.timer.j2 index 79d80a4..00feded 100644 --- a/templates/restic.timer.j2 +++ b/templates/restic.timer.j2 @@ -2,8 +2,8 @@ Description=Run restic backup {{ item.name }} every night [Timer] -OnCalendar=*-*-* 02:00:00 -RandomizedDelaySec=3h +OnCalendar=*-*-* 02:00:00 {{ restic_systemd_timer_default_OnCalendar }} +RandomizedDelaySec={{ restic_systemd_timer_randomizeddelaysec }} Persistent=yes [Install] From 9b8d0fe5999f23856b96e2663706755340787109 Mon Sep 17 00:00:00 2001 From: L3D Date: Mon, 5 Jul 2021 14:51:27 +0200 Subject: [PATCH 2/4] adding mail on error feature --- CHANGELOG.md | 19 ------- HISTORY.md | 97 -------------------------------- README.md | 35 ++++++------ templates/restic_script_Linux.j2 | 7 +++ vars/main.yml | 2 +- 5 files changed, 27 insertions(+), 133 deletions(-) delete mode 100644 CHANGELOG.md delete mode 100644 HISTORY.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 98d100e..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,19 +0,0 @@ - -> @ changelog /Users/mleutenegger/Desktop/Syntro/Ansible/ansible.restic -> git-chglog 0.2.8.. - - -## [Unreleased] - -### 🍰 Added -- git-chglog -- github workflows ([#25](https://github.com/syntro-opensource/ansible.silverstripe/issues/25)) -- example for backup syntax ([#24](https://github.com/syntro-opensource/ansible.silverstripe/issues/24)) - - - -## [0.2.8] - 2020-09-08 -## History -For versions before 0.2.9, see [HISTORY.md](HISTORY.md) -[Unreleased]: https://github.com/syntro-opensource/ansible.silverstripe/compare/0.2.8...HEAD -[0.2.8]: https://github.com/syntro-opensource/ansible.silverstripe/compare/0.2.7...0.2.8 diff --git a/HISTORY.md b/HISTORY.md deleted file mode 100644 index 1e89da2..0000000 --- a/HISTORY.md +++ /dev/null @@ -1,97 +0,0 @@ -# Changelog - -This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) -and [human-readable changelog](https://keepachangelog.com/en/1.0.0/). - -## Unreleased - -## [0.2.8] 2020-09-08 -### Added -* Sanity check for restic binary -* Support for the Backblaze B2 backend - -## [0.2.7] 2020-08-05 -### Added -* Config option to exclude files -* Contributing guide - -## [0.2.6] 2020-06-05 -### Changed -* Password now use `regex_escape()` filter in templates - -## [0.2.5] - 2020-06-02 -### Fixed: -* AWS credentials are now supplied to the initialising step -* Cronjob step does not fail if `scheduled` parameter is not set on repo -* init respects `'config already initialized'` string - -## [0.2.4] - 2020-06-01 -### Added -* `aws_default_region` for repos -## 0.2.3 - 2020-05-18 -### Fixed -* extraction path is actually generated -## [0.2.2] -### Changed -* Updated default Restic version to `'0.9.6'` -### Fixed -* Backup scripts use bash (@maciekmm) -* SFTP Link correctly renders in MD - -## [0.2.1] -### Fixed -* Crontab entries are now created correctly (@dnmvisser) -* Molecule now correctly runs lint (@mleutenegger) - -## [0.2.0] -### Added -* S3 Support - -## [0.1.5] -### Changed -* Path generation for `forget` task now checks if `src` is actually filled and not only defined. - -### Added -* `prune` option for automatic pruning during forget - - -## [0.1.4] -### Changed -* `--keep-tags` tags are correctly applied to the forget command -* Backup policies now also check if the respective variable actually contains a value - -### Added -* Added a template which only adds credentials for use with `source` on linux distros - -## [0.1.3] -### Changed -* Creating script dir before templating out scripts - -## [0.1.2] -### Changed -* build sucessfully completes - -## [0.1.1] -### Changed -* `restic_url` is now set in defaults - -## 0.1.0 -### Added -* initial release - - -[Unreleased]: https://github.com/arillso/ansible.restic/compare/0.2.8...HEAD -[0.2.8]: https://github.com/arillso/ansible.restic/compare/0.2.7...0.2.8 -[0.2.7]: https://github.com/arillso/ansible.restic/compare/0.2.6...0.2.7 -[0.2.6]: https://github.com/arillso/ansible.restic/compare/0.2.5...0.2.6 -[0.2.5]: https://github.com/arillso/ansible.restic/compare/0.2.4...0.2.5 -[0.2.4]: https://github.com/arillso/ansible.restic/compare/0.2.3...0.2.4 -[0.2.3]: https://github.com/arillso/ansible.restic/compare/0.2.2...0.2.3 -[0.2.2]: https://github.com/arillso/ansible.restic/compare/0.2.1...0.2.2 -[0.2.1]: https://github.com/arillso/ansible.restic/compare/0.2.0...0.2.1 -[0.2.0]: https://github.com/arillso/ansible.restic/compare/0.1.5...0.2.0 -[0.1.5]: https://github.com/arillso/ansible.restic/compare/0.1.4...0.1.5 -[0.1.4]: https://github.com/arillso/ansible.restic/compare/0.1.3...0.1.4 -[0.1.3]: https://github.com/arillso/ansible.restic/compare/0.1.2...0.1.3 -[0.1.2]: https://github.com/arillso/ansible.restic/compare/0.1.1...0.1.2 -[0.1.1]: https://github.com/arillso/ansible.restic/compare/0.1.0...0.1.1 diff --git a/README.md b/README.md index 16905f1..4fd62ce 100644 --- a/README.md +++ b/README.md @@ -118,16 +118,16 @@ Repository defined in `restic_repos`. Available variables: -| Name | Required (Default) | Description | -| ------------------ |:-----------------------------:| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `name` | yes | The name of this backup. Used together with pruning and scheduling and needs to be unique. | -| `repo` | yes | The name of the repository to backup to. | -| `src` | yes | The source directory or file | -| `stdin` | no | Is this backup created from a [stdin](https://restic.readthedocs.io/en/stable/040_backup.html#reading-data-from-stdin)? | -| `stdin_cmd` | no (yes if `stdin` == `true`) | The command to produce the stdin. | -| `stdin_filename` | no | The filename used in the repository. | -| `tags` | no | Array of default tags | -| `keep_last` | no | If set, only keeps the last n snapshots. | +| Name | Required (Default) | Description | +| ------------------ |:-----------------------------:| ------------ | +| `name` | yes | The name of this backup. Used together with pruning and scheduling and needs to be unique. | +| `repo` | yes | The name of the repository to backup to. | +| `src` | yes | The source directory or file | +| `stdin` | no | Is this backup created from a [stdin](https://restic.readthedocs.io/en/stable/040_backup.html#reading-data-from-stdin)? | +| `stdin_cmd` | no (yes if `stdin` == `true`) | The command to produce the stdin. | +| `stdin_filename` | no | The filename used in the repository. | +| `tags` | no | Array of default tags | +| `keep_last` | no | If set, only keeps the last n snapshots. | | `keep_hourly` | no | If set, only keeps the last n hourly snapshots. | | `keep_daily` | no | If set, only keeps the last n daily snapshots. | | `keep_weekly ` | no | If set, only keeps the last n weekly snapshots. | @@ -136,13 +136,16 @@ Available variables: | `keep_within` | no | If set, only keeps snapshots in this time period. | | `keep_tag` | no | If set, keep snapshots with this tags. Make sure to specify a list. | | `prune` | no (`false`) | If `true`, the `restic forget` command in the script has the [`--prune` option](https://restic.readthedocs.io/en/stable/060_forget.html#removing-backup-snapshots) appended. | -| `scheduled` | no (`false`) | If `restic_create_cron` is set to `true`, this backup is scheduled and tries to create a systemd timer unit. If it fails, it is creating a cronjob. | +| `scheduled` | no (`false`) | If `restic_create_cron` is set to `true`, this backup is scheduled and tries to create a systemd timer unit. If it fails, it is creating a cronjob. | | `schedule_oncalendar` | ``'*-*-* 02:00:00'`` | The time for the systemd timer. Please notice the randomDelaySec option. By Default the backup is done every night at 2 am (+0-4h). But only if scheduled is true. | -| `schedule_minute` | no (`*`) | Minute when the job is run. ( 0-59, *, */2, etc ) | -| `schedule_hour` | no (`*`) | Hour when the job is run. ( 0-23, *, */2, etc ) | -| `schedule_weekday` | no (`*`) | Weekday when the job is run. ( 0-6 for Sunday-Saturday, *, etc ) | -| `schedule_month` | no (`*`) | Month when the job is run. ( 1-12, *, */2, etc ) | -| `exclude` | no (`{}`) | Allows you to specify files to exclude. See [Exclude](#exclude) for reference. | +| `schedule_minute` | no (`*`) | Minute when the job is run. ( 0-59, *, */2, etc ) | +| `schedule_hour` | no (`*`) | Hour when the job is run. ( 0-23, *, */2, etc ) | +| `schedule_weekday` | no (`*`) | Weekday when the job is run. ( 0-6 for Sunday-Saturday, *, etc ) | +| `schedule_month` | no (`*`) | Month when the job is run. ( 1-12, *, */2, etc ) | +| `exclude` | no (`{}`) | Allows you to specify files to exclude. See [Exclude](#exclude) for reference. | +| `disable_logging` | no | Optionally disable logging | +| `mail_on_error` | no | Optionally send a mail if the backupjob will fail *(mailx is required)* | +| `mail_address` | if `mail_on_error` is true | The mail addressto recive mails if you enabled ``mail_on_error``. | Example: ```yaml diff --git a/templates/restic_script_Linux.j2 b/templates/restic_script_Linux.j2 index 412f37e..7355176 100644 --- a/templates/restic_script_Linux.j2 +++ b/templates/restic_script_Linux.j2 @@ -32,6 +32,8 @@ export B2_ACCOUNT_KEY={{ restic_repos[item.repo].b2_account_key }} {% if item.src is defined %} BACKUP_SOURCE={{ item.src }} {% endif %} + + set -uxo pipefail {# Define Tags @@ -131,6 +133,8 @@ else echo "$(date -u '+%Y-%m-%d %H:%M:%S') ERROR" >> {{ backup_result_log }} fi + + {# Define stdin forget commands #} @@ -140,4 +144,7 @@ then echo "$(date -u '+%Y-%m-%d %H:%M:%S') OK" >> {{ forget_result_log }} else echo "$(date -u '+%Y-%m-%d %H:%M:%S') ERROR" >> {{ forget_result_log }} + {% if item.mail_on_error is defined and item.mail_on_error == true %} + mail -s "restic backup failed on {{ ansible_hostname }}" {{ item.mail_address }} <<< 'Something went wrong while running restic backup script at {{ ansible_hostname }}' + {% endif %} fi diff --git a/vars/main.yml b/vars/main.yml index 7373467..b633b76 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -10,5 +10,5 @@ restic_os_variables: paths: - 'vars' -playbook_version_number: 8 # should be int +playbook_version_number: 9 # should be int playbook_version_path: 'do1jlr.restic.version' From a7df28bce96d8f370f1e9c17ecc8af7ec50ab2ca Mon Sep 17 00:00:00 2001 From: L3D Date: Mon, 5 Jul 2021 15:26:33 +0200 Subject: [PATCH 3/4] improve template error --- templates/restic.timer.j2 | 2 +- vars/main.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/restic.timer.j2 b/templates/restic.timer.j2 index 00feded..69ea2c8 100644 --- a/templates/restic.timer.j2 +++ b/templates/restic.timer.j2 @@ -2,7 +2,7 @@ Description=Run restic backup {{ item.name }} every night [Timer] -OnCalendar=*-*-* 02:00:00 {{ restic_systemd_timer_default_OnCalendar }} +OnCalendar={{ restic_systemd_timer_default_OnCalendar }} RandomizedDelaySec={{ restic_systemd_timer_randomizeddelaysec }} Persistent=yes diff --git a/vars/main.yml b/vars/main.yml index b633b76..a45ce99 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -10,5 +10,5 @@ restic_os_variables: paths: - 'vars' -playbook_version_number: 9 # should be int +playbook_version_number: 10 # should be int playbook_version_path: 'do1jlr.restic.version' From 94aae0e3b970626b5f41df1044728ce1b0d86d01 Mon Sep 17 00:00:00 2001 From: L3D Date: Mon, 5 Jul 2021 16:18:46 +0200 Subject: [PATCH 4/4] improve error message --- README.md | 2 +- tasks/timer.yml | 23 +++++++++++++++++++++-- templates/restic_script_Linux.j2 | 6 +++++- vars/main.yml | 2 +- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4fd62ce..ee4e5e1 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ Available variables: | `scheduled` | no (`false`) | If `restic_create_cron` is set to `true`, this backup is scheduled and tries to create a systemd timer unit. If it fails, it is creating a cronjob. | | `schedule_oncalendar` | ``'*-*-* 02:00:00'`` | The time for the systemd timer. Please notice the randomDelaySec option. By Default the backup is done every night at 2 am (+0-4h). But only if scheduled is true. | | `schedule_minute` | no (`*`) | Minute when the job is run. ( 0-59, *, */2, etc ) | -| `schedule_hour` | no (`*`) | Hour when the job is run. ( 0-23, *, */2, etc ) | +| `schedule_hour` | no (`2`) | Hour when the job is run. ( 0-23, *, */2, etc ) | | `schedule_weekday` | no (`*`) | Weekday when the job is run. ( 0-6 for Sunday-Saturday, *, etc ) | | `schedule_month` | no (`*`) | Month when the job is run. ( 1-12, *, */2, etc ) | | `exclude` | no (`{}`) | Allows you to specify files to exclude. See [Exclude](#exclude) for reference. | diff --git a/tasks/timer.yml b/tasks/timer.yml index cf3b48d..695b4a7 100644 --- a/tasks/timer.yml +++ b/tasks/timer.yml @@ -70,9 +70,28 @@ - restic_create_cron - item.name is defined - item.scheduled | default(false) + + - name: delete old cronjob entry if available + ansible.builtin.cron: + name: "do1jlr.restic backup {{ item.name }}" + job: "CRON=true {{ restic_script_dir }}/backup-{{ item.name | replace(' ', '') }}.sh" + minute: '{{ item.schedule_minute | default("*") }}' + hour: '{{ item.schedule_hour | default("2") }}' + weekday: '{{ item.schedule_weekday | default("*") }}' + month: '{{ item.schedule_month | default("*") }}' + state: absent + cron_file: '/etc/crontab' + user: 'root' + become: true + no_log: true + with_items: '{{ restic_backups }}' + when: + - restic_create_cron + - item.name is defined + - item.scheduled | default(false) when: ansible_service_mgr == 'systemd' rescue: - - name: set ceonjo intead of systemd + - name: set cronjob intead of systemd set_fact: restic_force_cron: true @@ -82,7 +101,7 @@ name: "do1jlr.restic backup {{ item.name }}" job: "CRON=true {{ restic_script_dir }}/backup-{{ item.name | replace(' ', '') }}.sh" minute: '{{ item.schedule_minute | default("*") }}' - hour: '{{ item.schedule_hour | default("*") }}' + hour: '{{ item.schedule_hour | default("2") }}' weekday: '{{ item.schedule_weekday | default("*") }}' month: '{{ item.schedule_month | default("*") }}' state: present diff --git a/templates/restic_script_Linux.j2 b/templates/restic_script_Linux.j2 index 7355176..f1ab0c3 100644 --- a/templates/restic_script_Linux.j2 +++ b/templates/restic_script_Linux.j2 @@ -145,6 +145,10 @@ then else echo "$(date -u '+%Y-%m-%d %H:%M:%S') ERROR" >> {{ forget_result_log }} {% if item.mail_on_error is defined and item.mail_on_error == true %} - mail -s "restic backup failed on {{ ansible_hostname }}" {{ item.mail_address }} <<< 'Something went wrong while running restic backup script at {{ ansible_hostname }}' + mail -s "restic backup failed on {{ ansible_hostname }}" {{ item.mail_address }} <<< "Something went wrong while running restic backup script running at {{ ansible_hostname }} at $(date -u '+%Y-%m-%d %H:%M:%S'). + {%- if item.src is defined -%} + {{ ' ' }}We tried to backup '{{ item.src }}'. + {%- endif -%} + {{ ' ' }}Please repair the restic-{{ item.name | replace(' ', '') }} job." {% endif %} fi diff --git a/vars/main.yml b/vars/main.yml index a45ce99..5d48ccb 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -10,5 +10,5 @@ restic_os_variables: paths: - 'vars' -playbook_version_number: 10 # should be int +playbook_version_number: 11 # should be int playbook_version_path: 'do1jlr.restic.version'