From 9c7586c7c3a235672ec6490d1a8bc44a222ce5d1 Mon Sep 17 00:00:00 2001 From: Colin Wilk Date: Tue, 1 Sep 2026 21:01:05 +0200 Subject: Add borg prune and compact jobs Run repository retention either after a successful backup or from a dedicated systemd timer. Clean up script generation with templates and expand molecule test coverage. BREAKING CHANGE: Aggregate backup scripts are no longer managed, and state=preset now requires at least one readable included directory. --- tasks/validate_present.yml | 104 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 tasks/validate_present.yml (limited to 'tasks/validate_present.yml') diff --git a/tasks/validate_present.yml b/tasks/validate_present.yml new file mode 100644 index 0000000..fafa807 --- /dev/null +++ b/tasks/validate_present.yml @@ -0,0 +1,104 @@ +--- +- name: Validate required present-state variables + ansible.builtin.assert: + that: + - borg_repo_name | length > 0 + - borg_server_user | length > 0 + - borg_server_user_home | length > 0 + - borg_backup_script_location | length > 0 + - borg_included_dirs | length > 0 + fail_msg: >- + Invalid configuration for state=present. Ensure borg_repo_name, + borg_server_user, borg_server_user_home, borg_backup_script_location are + set and borg_included_dirs is not empty. + +- name: Validate prune configuration + ansible.builtin.assert: + that: + - not borg_prune_enabled or not borg_mode_append_only + - not borg_prune_enabled or borg_prune_glob_archives | length > 0 + - not borg_prune_enabled or borg_prune_trigger in ['after_backup', 'timer'] + - not borg_prune_enabled or borg_compact_threshold >= 0 + - not borg_prune_enabled or borg_compact_threshold <= 100 + - not borg_prune_enabled or ( + borg_prune_keep_within | length > 0 or + borg_prune_keep_last | length > 0 or + borg_prune_keep_minutely | length > 0 or + borg_prune_keep_hourly | length > 0 or + borg_prune_keep_daily | length > 0 or + borg_prune_keep_weekly | length > 0 or + borg_prune_keep_monthly | length > 0 or + borg_prune_keep_13weekly | length > 0 or + borg_prune_keep_3monthly | length > 0 or + borg_prune_keep_yearly | length > 0 or + borg_prune_additional_arguments | length > 0 + ) + - not borg_prune_enabled or borg_prune_service_name | length > 0 + - not borg_prune_enabled or borg_prune_script_location | length > 0 + - borg_prune_trigger != 'timer' or borg_prune_timer_name | length > 0 + - borg_prune_trigger != 'timer' or borg_prune_systemd_oncalendar | length > 0 + - borg_prune_trigger != 'timer' or borg_prune_systemd_accuracysec | length > 0 + fail_msg: >- + Invalid prune configuration. Prune requires at least one retention rule + from borg_prune_keep_* / borg_prune_keep_within or + borg_prune_additional_arguments, a non-empty archive glob, compact + threshold between 0 and 100, and it is incompatible with + borg_mode_append_only. + +- name: Ensure borg_client_user exists + ansible.builtin.getent: + database: passwd + key: "{{ borg_client_user }}" + become: true + +- name: Compute borg_client_user_home if not set + ansible.builtin.set_fact: + borg_client_user_home: "{{ ansible_facts.getent_passwd[borg_client_user][4] }}" + when: borg_client_user_home is not defined + +- name: Validate borg_client_user home exists + ansible.builtin.stat: + path: "{{ borg_client_user_home }}" + register: user_home_stat + become: true + +- name: Fail if borg_client_user home missing + ansible.builtin.fail: + msg: | + Home directory {{ borg_client_user_home }} for user {{ borg_client_user }} does not exist. + Please ensure the user has a valid home directory before running this role. + when: not user_home_stat.stat.exists + +- name: Check readability of included paths + ansible.builtin.stat: + path: "{{ item }}" + loop: "{{ borg_included_dirs }}" + register: included_paths_stat + become: true + become_user: "{{ borg_client_user }}" + +- name: Fail if included path is unreadable or missing + ansible.builtin.fail: + msg: >- + Included path {{ item.item }} is missing or not accessible by + {{ borg_client_user }}. + when: + - not item.stat.exists or not item.stat.readable + loop: "{{ included_paths_stat.results }}" + +- name: Ensure borg_server_user exists when auto-create disabled + ansible.builtin.getent: + database: passwd + key: "{{ borg_server_user }}" + become: true + delegate_to: "{{ borg_server_host }}" + when: not borg_server_user_create + +- name: Fail if borg_server_user does not exist when auto-create disabled + ansible.builtin.fail: + msg: | + User {{ borg_server_user }} does not exist on {{ borg_server_host }}. + Please create the user before running this role or set borg_server_user_create: true. + when: + - not borg_server_user_create + - ansible_facts.getent_passwd[borg_server_user] is not defined -- cgit v1.2.3