๐Ÿ“— Ansible playbooks and roles for building an idempotent, interconnected and scalable infrastructure
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ansible-playbooks/roles/restic/tasks/main.yml

150 lines
6.3 KiB

2 years ago
- name: fail if backup parameters are missing
fail:
msg: backup parameters are missing or incorrect
when: (backup is not mapping) or (backup.dirs is not defined)
- name: install restic
include_tasks: tasks/install_packages.yml
vars:
package:
- restic
- name: add restic repo
include_role:
name: rest-server
vars:
function: add_repo
repo:
user: "{{ backup.user | d(host_name) }}"
password: "{{ backup.password }}"
name: "{{ backup.repo | d(None) }}"
retention: "{{ backup.retention | d(restic_default_backup_retention) | d({}) }}"
repo_password: "{{ backup.repo_password | d(None) }}"
server: "{{ backup.server | d(None) }}"
- name: set backup id
set_fact:
restic_backup_id: "{{ (backup.user | d(host_name)) ~ (('-' ~ backup.repo) if backup.repo is defined else '') }}"
- block:
- name: ensure work dir exists
file:
path: "{{ restic_dir.linux }}"
state: directory
mode: 0700
- name: set exclude file location
set_fact:
restic_exclude_file_path: "{{ restic_dir.linux ~ '/exclude-file-' ~ restic_backup_id }}"
- name: create exclude file
copy:
content: "{{ backup.filter | join('\n') }}"
dest: "{{ restic_exclude_file_path }}"
when: ansible_system != 'Win32NT' and (backup.filter | type_debug == 'list') and (backup.filter | length > 0)
- block:
- name: ensure work dir exists
win_file:
path: "{{ restic_dir.windows }}"
state: directory
- name: set exclude file location
set_fact:
restic_exclude_file_path: "{{ restic_dir.windows ~ '\\exclude-file-' ~ restic_backup_id }}"
restic_exclude_file_path_psh: "{{ restic_dir.windows_psh ~ '\\exclude-file-' ~ restic_backup_id }}"
- name: create exclude file
win_copy:
content: "{{ backup.filter | join('\r\n') }}"
dest: "{{ restic_exclude_file_path }}"
when: ansible_system == 'Win32NT' and (backup.filter | type_debug == 'list') and (backup.filter | length > 0)
- name: build restic args
set_fact:
restic_args: "{{ [
('--one-file-system' if (backup.fs_single | d(false) == true) else ''),
('--use-fs-snapshot' if (backup.fs_snapshot | d(false) == true) else ''),
(('--tag ' ~ (backup.tags | select() | list | join(',') | quote)) if (backup.tags | type_debug == 'list') else ''),
(('--tag ' ~ (backup.tags | quote)) if (backup.tags is string and backup.tags | length > 0) else ''),
(('--limit-download ' ~ (backup.download_limit | quote)) if (backup.download_limit is defined and backup.download_limit != 0) else ''),
(('--limit-upload ' ~ (backup.upload_limit | quote)) if (backup.upload_limit is defined and backup.upload_limit != 0) else ''),
(('--exclude-larger-than ' ~ (backup.max_size | quote)) if (backup.max_size is string and backup.max_size | length > 0) else ''),
(('--iexclude-file \"' ~ restic_exclude_file_path_psh ~ '\"') if ((backup.filter | type_debug == 'list') and (backup.filter | length > 0) and ansible_system == 'Win32NT') else ''),
(('--iexclude-file ' ~ (restic_exclude_file_path | quote)) if ((backup.filter | type_debug == 'list') and (backup.filter | length > 0) and ansible_system != 'Win32NT') else '')
] | select() | list | join(' ') }}"
restic_item_list: "{{ (backup.dirs if (backup.dirs | type_debug == 'list') else [backup.dirs]) | map('quote') | join(' ') }}"
- name: build env vars
set_fact:
restic_env_vars:
RESTIC_PASSWORD: "{{ backup.repo_password | d(backup.password) }}"
RESTIC_REPOSITORY: "{{ ('rest:' ~ (services.backup.protocol | d('https')) ~ '://' ~ (backup.user | d(host_name)) ~ ':' ~ backup.password ~ '@' ~
(backup.server | d(services.backup.hostname)) ~ '.' ~
(services.backup.tld | d(int_tld)) ~ ':' ~ (services.backup.port | d('443')) ~ '/' ~
(backup.user | d(host_name)) ~ (('/' ~ backup.repo) if backup.repo is defined else '')) }}"
- name: add backup job to cron
cron:
name: "{{ 'restic-backup-' ~ restic_backup_id }}"
minute: "{{ backup.minute | d(59 | random(seed=restic_backup_id)) }}"
hour: "{{ backup.hour | d(4 | random(start=1, seed=restic_backup_id)) }}"
day: "{{ backup.day | d('*') }}"
weekday: "{{ backup.weekday | d('*') }}"
month: "{{ backup.month | d('*') }}"
job: "{{ restic_env_vars.keys() | zip(restic_env_vars.values() | map('quote')) | map('join', '=') | list | join(' ') }} restic backup {{ restic_args }} {{ restic_item_list }}"
when: (ansible_system != 'Win32NT') and (backup.schedule | d(true) == true)
- block:
- name: template backup script to remote host
win_template:
src: win_script.j2
dest: "{{ restic_dir.windows ~ '\\backup-' ~ restic_backup_id ~ '.ps1' }}"
lstrip_blocks: yes
- name: add scheduled task
win_scheduled_task:
name: "{{ 'Restic Backup (' ~ restic_backup_id ~ ')' }}"
description: Initiate a Restic backup job
allow_demand_start: yes
allow_hard_terminate: yes
compatibility: 3
execution_time_limit: PT18H
disallow_start_if_on_batteries: no
enabled: yes
logon_type: service_account
multiple_instances: 2
username: SYSTEM
run_level: highest
start_when_available: yes
stop_if_going_on_batteries: no
wake_to_run: no
update_password: no
actions:
- path: powershell.exe
arguments: "{{ '-ExecutionPolicy Unrestricted -File \"' ~ restic_dir.windows ~ '\\backup-' ~ restic_backup_id ~ '.ps1\"' }}"
triggers:
- type: "{{ backup.interval }}"
enabled: yes
start_boundary: "2020-01-01T{{ '%02d' | format(backup.hour | d(4 | random(start=1, seed=restic_backup_id))) }}\
:{{ '%02d' | format(backup.minute | d(59 | random(seed=restic_backup_id))) }}:00"
random_delay: "{{ backup.random_delay | d(omit) }}"
days_of_week: "{{ backup.days_of_week | d(omit) }}"
days_of_month: "{{ backup.days_of_month | d(omit) }}"
weeks_interval: "{{ backup.weeks_interval | d(omit) }}"
when: (backup.schedule | d(true) == true)
when: ansible_system == 'Win32NT'