diff --git a/logs.log b/logs.log new file mode 100644 index 0000000..a17a801 --- /dev/null +++ b/logs.log @@ -0,0 +1,12 @@ +2026-01-25 22:12:41,674 p=57299 u=rohit n=ansible INFO| ansible-playbook [core 2.19.4] + config file = None + configured module search path = ['/Users/rohit/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] + ansible python module location = /Users/rohit/venvs/ansible312/lib/python3.12/site-packages/ansible + ansible collection location = /Users/rohit/.ansible/collections:/usr/share/ansible/collections + executable location = /Users/rohit/venvs/ansible312/bin/ansible-playbook + python version = 3.12.12 (main, Oct 9 2025, 11:07:00) [Clang 17.0.0 (clang-1700.0.13.3)] (/Users/rohit/venvs/ansible312/bin/python3.12) + jinja version = 3.1.6 + pyyaml version = 6.0.3 (with libyaml v0.2.5) +2026-01-25 22:12:41,674 p=57299 u=rohit n=ansible INFO| No config file found; using defaults +2026-01-25 22:12:41,674 p=57299 u=rohit n=ansible ERROR| [ERROR]: the playbook: demo_backup_restore.yml could not be found + diff --git a/roles/backup/README.md b/roles/backup/README.md index 24fb5b7..e8a3355 100644 --- a/roles/backup/README.md +++ b/roles/backup/README.md @@ -17,6 +17,7 @@ This role supports full and differential backups, storing them locally or in a r - Backs up the configuration **only if** there are changes compared to the last saved version. - Works with both local and Git-based data stores. - Helps reduce storage and SCM noise by saving only when diff exists. +- **Ignores timestamps and metadata** - only detects actual configuration changes. --- @@ -34,8 +35,8 @@ This role supports full and differential backups, storing them locally or in a r | `data_store.scm.origin.path` | Directory path inside the repo to save backup | `str` | No | N/A | | `data_store.scm.origin.ssh_key_file` | Path to the SSH private key file for Git authentication | `str` | Yes (if using SCM SSH) | N/A | | `data_store.scm.origin.ssh_key_content` | The content of the SSH private key | `str` | Yes (if using SCM SSH) | N/A | +| `type` | Type of backup to perform. Options: `"full"`, `"incremental"`, or `"diff"` | `str` | No | `"full"` | -> Note: Either `data_store.local` or `data_store.scm` must be provided. --- @@ -136,6 +137,32 @@ This role supports full and differential backups, storing them locally or in a r path: "backups/{{ ansible_date_time.date }}/{{ inventory_hostname }}" ``` +### Create Differential Backup (Only Publish if Config Changed) + +```yaml +- name: Create Network Backup and Push to GitHub + hosts: network + gather_facts: false + tasks: + - name: Create Network Backup + ansible.builtin.include_role: + name: network.backup.backup + vars: + type: "diff" # Enable differential backup + data_store: + scm: + origin: + user: + name: "your_name" + email: "your_email@example.com" + url: "git@github.com:youruser/your-backup-repo.git" + ssh_key_file: "/path/to/ssh/key" + filename: "{{ ansible_date_time.date }}_{{ inventory_hostname }}.txt" + path: "backups/{{ ansible_date_time.date }}/{{ inventory_hostname }}" +``` + +> **Note**: With `type: "diff"`, the backup will only be published to SCM if actual configuration changes are detected. Timestamps and metadata differences are ignored. See [Differential Backup Documentation](Differential_Backup_Documentation.md) for more details. + ## License GNU General Public License v3.0 or later. @@ -144,4 +171,4 @@ See [LICENSE](https://www.gnu.org/licenses/gpl-3.0.txt) to see the full text. ## Author Information -- Ansible Network Content Team \ No newline at end of file +- Ansible Network Content Team diff --git a/roles/backup/meta/argument_specs.yml b/roles/backup/meta/argument_specs.yml index 04cee10..0b5d0d3 100644 --- a/roles/backup/meta/argument_specs.yml +++ b/roles/backup/meta/argument_specs.yml @@ -45,6 +45,13 @@ argument_specs: type: dict required: false options: + parent_directory: + type: str + required: false + description: + - Parent directory where the Git repository will be cloned (e.g., /tmp or role_path). + - If not specified, defaults to role_path. + - Best practice: Use temp directory (e.g., /tmp) for isolated operations. origin: type: dict required: true diff --git a/roles/backup/tasks/backup.yaml b/roles/backup/tasks/backup.yaml index 57cc04a..875fb3d 100644 --- a/roles/backup/tasks/backup.yaml +++ b/roles/backup/tasks/backup.yaml @@ -2,36 +2,69 @@ - name: Build Local Backup Dir Path ansible.builtin.include_tasks: path.yaml when: data_store.scm.origin is not defined + tags: always - name: Include retrieve tasks ansible.builtin.include_tasks: retrieve.yaml when: data_store['scm']['origin'] is defined run_once: true + tags: always -- name: Get scm url +- name: Get scm url - Use actual repo path from retrieve.yaml ansible.builtin.set_fact: - network_backup_path_root: "{{ role_path }}/{{ data_store.scm.origin.url.split('/')[-1] | regex_replace('\\.git$', '') }}" + network_backup_path_root: "{{ network_backup_path | default(role_path ~ '/' ~ (data_store.scm.origin.url.split('/')[-1] | regex_replace('\\.git$', ''))) }}" when: data_store['scm']['origin'] is defined + tags: always - name: Get file name ansible.builtin.set_fact: network_backup_path: "{{ network_backup_path_root }}/{{ data_store.scm.origin.path | default(role_path, true) }}" when: data_store['scm']['origin'] is defined + tags: always - name: Get timestamp ansible.builtin.set_fact: timestamp: "{{ lookup('pipe', 'date +%Y-%m-%d_%H-%M-%S') }}" + tags: always - name: Set default filename ansible.builtin.set_fact: network_backup_filename: >- {{ data_store.scm.origin.filename | default(inventory_hostname ~ '_' ~ timestamp ~ '.txt', true) }} when: network_backup_filename is undefined + tags: always + +- name: Read previous backup for differential comparison (before current backup is created) + ansible.builtin.include_tasks: differential_scm_read_previous.yaml + when: + - data_store['scm']['origin'] is defined + - type | default('full') == "diff" + tags: always - name: Include tasks ansible.builtin.include_tasks: network.yaml + tags: always + +- name: Check for differential backup (SCM only) + ansible.builtin.include_tasks: differential_scm.yaml + when: data_store['scm']['origin'] is defined + tags: always - name: Include build tasks ansible.builtin.include_tasks: publish.yaml - when: data_store.scm.origin is defined + when: + - data_store.scm.origin is defined + - backup_has_changes | default(true) + run_once: true + tags: always + +- name: Cleanup cloned repository when publish is skipped + ansible.builtin.file: + path: "{{ network_backup_path_root }}" + state: absent + when: + - data_store.scm.origin is defined + - not (backup_has_changes | default(true)) run_once: true + delegate_to: localhost + tags: always diff --git a/roles/backup/tasks/cli_backup.yaml b/roles/backup/tasks/cli_backup.yaml index 6f45e47..07651f3 100644 --- a/roles/backup/tasks/cli_backup.yaml +++ b/roles/backup/tasks/cli_backup.yaml @@ -4,3 +4,4 @@ dir_path: "{{ network_backup_path }}" filename: "{{ network_backup_filename | default(inventory_hostname) }}" register: network_backup + tags: always diff --git a/roles/backup/tasks/differential_scm.yaml b/roles/backup/tasks/differential_scm.yaml new file mode 100644 index 0000000..16f7afd --- /dev/null +++ b/roles/backup/tasks/differential_scm.yaml @@ -0,0 +1,99 @@ +--- +# Differential backup logic for SCM (Git) data stores +# Compares current backup with previous backup, normalizing timestamps/metadata +# Only publishes if there are actual configuration changes + +- name: Set default backup type to full if not specified + ansible.builtin.set_fact: + backup_type: "{{ type | default('full') }}" + tags: always + +# Previous backup was already read in differential_scm_read_previous.yaml +# before the current backup was created (to avoid overwriting the file) +# Check if previous backup exists (for conditional logic) +- name: Check if previous backup file exists + ansible.builtin.stat: + path: "{{ network_backup_path }}/{{ network_backup_filename }}" + register: previous_backup_stat + when: + - data_store['scm']['origin'] is defined + - backup_type == "diff" + tags: always + +- name: Debug normalized previous backup result (from pre-read) + ansible.builtin.debug: + msg: "Normalized previous backup result (read before current backup): {{ normalized_previous_backup | default('NOT SET - previous backup may not exist') }}" + when: + - data_store['scm']['origin'] is defined + - backup_type == "diff" + tags: always + +- name: Normalize current backup file (remove timestamps and metadata) + ansible.builtin.shell: | + sed -E \ + -e '/^!Command:/d' \ + -e '/^!Running configuration last done at:/d' \ + -e '/^! Last configuration change at /d' \ + -e '/^!Time:/d' \ + -e '/^!NVRAM config last updated at:/d' \ + -e '/^!No configuration change since last restart/d' \ + "{{ network_backup_path }}/{{ network_backup_filename }}" | grep -v '^[[:space:]]*$' + register: normalized_current_result + changed_when: false + when: + - data_store['scm']['origin'] is defined + - backup_type == "diff" + tags: always + +- name: Debug normalized current backup result + ansible.builtin.debug: + msg: "Normalized current backup result: {{ normalized_current_result.stdout }}" + when: + - data_store['scm']['origin'] is defined + - backup_type == "diff" + tags: always + +- name: Set normalized content facts (use pre-read previous backup) + ansible.builtin.set_fact: + normalized_previous: "{{ normalized_previous_backup | default('') }}" + normalized_current: "{{ normalized_current_result.stdout | default('') }}" + when: + - data_store['scm']['origin'] is defined + - backup_type == "diff" + tags: always + +- name: Compare normalized backups (using pre-read previous backup) + ansible.builtin.set_fact: + backup_has_changes: "{{ normalized_previous != normalized_current }}" + when: + - data_store['scm']['origin'] is defined + - backup_type == "diff" + - normalized_previous_backup is defined + - normalized_previous_backup != "" + tags: always + +- name: Set backup_has_changes to true if no previous backup exists + ansible.builtin.set_fact: + backup_has_changes: true + when: + - data_store['scm']['origin'] is defined + - backup_type == "diff" + - normalized_previous_backup is not defined or normalized_previous_backup == "" + tags: always + +- name: Set backup_has_changes to true for full backup type + ansible.builtin.set_fact: + backup_has_changes: true + when: + - data_store['scm']['origin'] is defined + - backup_type != "diff" + tags: always + +- name: Display differential backup result + ansible.builtin.debug: + msg: "Differential backup: {{ 'Changes detected - will publish' if backup_has_changes else 'No changes detected - skipping publish' }}" + when: + - data_store['scm']['origin'] is defined + - backup_type == "diff" + tags: always + diff --git a/roles/backup/tasks/differential_scm_read_previous.yaml b/roles/backup/tasks/differential_scm_read_previous.yaml new file mode 100644 index 0000000..c84cc5f --- /dev/null +++ b/roles/backup/tasks/differential_scm_read_previous.yaml @@ -0,0 +1,55 @@ +--- +# Read previous backup BEFORE current backup is created +# This prevents the current backup from overwriting the previous backup file +# before we can read it for comparison + +- name: Set default backup type to full if not specified + ansible.builtin.set_fact: + backup_type: "{{ type | default('full') }}" + tags: always + +- name: Check if previous backup file exists + ansible.builtin.stat: + path: "{{ network_backup_path }}/{{ network_backup_filename }}" + register: previous_backup_stat + when: + - data_store['scm']['origin'] is defined + - backup_type == "diff" + tags: always + +- name: Normalize previous backup file (remove timestamps and metadata) + ansible.builtin.shell: | + sed -E \ + -e '/^!Command:/d' \ + -e '/^!Running configuration last done at:/d' \ + -e '/^! Last configuration change at /d' \ + -e '/^!Time:/d' \ + -e '/^!NVRAM config last updated at:/d' \ + -e '/^!No configuration change since last restart/d' \ + "{{ network_backup_path }}/{{ network_backup_filename }}" | grep -v '^[[:space:]]*$' + register: normalized_previous_result + changed_when: false + failed_when: false + when: + - data_store['scm']['origin'] is defined + - backup_type == "diff" + - previous_backup_stat.stat.exists | default(false) + tags: always + +- name: Store normalized previous backup for later comparison + ansible.builtin.set_fact: + normalized_previous_backup: "{{ normalized_previous_result.stdout | default('') }}" + when: + - data_store['scm']['origin'] is defined + - backup_type == "diff" + - previous_backup_stat.stat.exists | default(false) + tags: always + +- name: Set normalized_previous to empty if no previous backup exists + ansible.builtin.set_fact: + normalized_previous_backup: "" + when: + - data_store['scm']['origin'] is defined + - backup_type == "diff" + - not (previous_backup_stat.stat.exists | default(false)) + tags: always diff --git a/roles/backup/tasks/main.yaml b/roles/backup/tasks/main.yaml index c2514ed..aef7987 100644 --- a/roles/backup/tasks/main.yaml +++ b/roles/backup/tasks/main.yaml @@ -1,6 +1,8 @@ --- - name: Include tasks ansible.builtin.include_tasks: validation.yaml + tags: always - name: Run the platform specific tasks ansible.builtin.include_tasks: "backup.yaml" + tags: always diff --git a/roles/backup/tasks/network.yaml b/roles/backup/tasks/network.yaml index 7464287..08434db 100644 --- a/roles/backup/tasks/network.yaml +++ b/roles/backup/tasks/network.yaml @@ -1,3 +1,4 @@ --- - name: Invoke backup task ansible.builtin.include_tasks: cli_backup.yaml + tags: always diff --git a/roles/backup/tasks/publish.yaml b/roles/backup/tasks/publish.yaml index 6fbc755..e2968d9 100644 --- a/roles/backup/tasks/publish.yaml +++ b/roles/backup/tasks/publish.yaml @@ -3,12 +3,14 @@ ansible.builtin.set_fact: time: "{{ lookup('pipe', 'date \"+%Y-%m-%d-%H-%M\"') }}" run_once: true + tags: always - name: Create default tag ansible.builtin.set_fact: default_tag: annotation: "{{ time }}" message: "backup_on: {{ time }}" + tags: always - name: Set default tag ansible.builtin.set_fact: @@ -16,10 +18,11 @@ when: - tag is defined - tag == "default" + tags: always - name: Publish the changes with tag ansible.scm.git_publish: - path: "{{ network_backup_path }}" + path: "{{ network_backup_path_root }}" token: "{{ data_store.scm.origin.get('token') if data_store.scm.origin.get('token') else omit }}" user: "{{ data_store['scm']['origin']['user'] | d({}) }}" tag: "{{ tag }}" @@ -27,18 +30,21 @@ ssh_key_file: "{{ data_store.scm.origin.get('ssh_key_file') if data_store.scm.origin.get('ssh_key_file') else omit }}" ssh_key_content: "{{ data_store.scm.origin.get('ssh_key_content') if data_store.scm.origin.get('ssh_key_content') else omit }}" when: tag is defined + tags: always - name: Publish the changes ansible.scm.git_publish: - path: "{{ network_backup_path }}" + path: "{{ network_backup_path_root }}" token: "{{ data_store.scm.origin.get('token') if data_store.scm.origin.get('token') else omit }}" user: "{{ data_store['scm']['origin']['user'] | d({}) }}" timeout: 120 ssh_key_file: "{{ data_store.scm.origin.get('ssh_key_file') if data_store.scm.origin.get('ssh_key_file') else omit }}" ssh_key_content: "{{ data_store.scm.origin.get('ssh_key_content') if data_store.scm.origin.get('ssh_key_content') else omit }}" when: tag is not defined + tags: always - name: Remove cloned repository directory ansible.builtin.file: path: "{{ network_backup_path_root }}" state: absent + tags: always diff --git a/roles/backup/tasks/retrieve.yaml b/roles/backup/tasks/retrieve.yaml index 4c02e0c..3e5a426 100644 --- a/roles/backup/tasks/retrieve.yaml +++ b/roles/backup/tasks/retrieve.yaml @@ -2,9 +2,11 @@ - name: Set Default Path ansible.builtin.set_fact: default_path: "{{ role_path }}" + tags: always - name: Perform retrieve with provided credentials when: data_store.scm.origin.token is defined + tags: always block: - name: Retrieve the host vars with provided token access ansible.scm.git_retrieve: @@ -13,14 +15,37 @@ token: "{{ data_store['scm']['origin']['token'] }}" parent_directory: "{{ data_store.scm.parent_directory | default(default_path) }}" register: resource_manager_result + tags: always - name: Update data store path ansible.builtin.set_fact: network_backup_repository: "{{ resource_manager_result }}" + tags: always - name: Perform retrieve with default settings or SSH key when: data_store.scm.origin.token is undefined + tags: always block: + - name: Set repository path + ansible.builtin.set_fact: + repo_local_path: "{{ data_store.scm.parent_directory | default(default_path) }}/{{ data_store['scm']['origin']['url'].split('/')[-1] | regex_replace('\\.git$', '') }}" + tags: always + + - name: Check if repository directory already exists + ansible.builtin.stat: + path: "{{ repo_local_path }}" + register: repo_dir_stat + tags: always + + - name: Pull latest changes if repository exists + ansible.builtin.command: + cmd: git -C {{ repo_local_path }} pull origin main + register: git_pull_result + changed_when: "'Already up to date' not in git_pull_result.stdout" + failed_when: false + when: repo_dir_stat.stat.exists | default(false) + tags: always + - name: Retrieve host vars with default access or SSH key ansible.scm.git_retrieve: origin: @@ -29,11 +54,29 @@ ssh_key_content: "{{ data_store['scm']['origin'].ssh_key_content | default(omit) }}" parent_directory: "{{ data_store.scm.parent_directory | default(default_path) }}" register: resource_manager_result + failed_when: false + when: not (repo_dir_stat.stat.exists | default(false)) + tags: always - - name: Update data store path + - name: Set repository path when directory already exists + ansible.builtin.set_fact: + network_backup_repository: + path: "{{ repo_local_path }}" + when: repo_dir_stat.stat.exists | default(false) + tags: always + + - name: Update data store path from git_retrieve result ansible.builtin.set_fact: network_backup_repository: "{{ resource_manager_result }}" + when: + - resource_manager_result is defined + - resource_manager_result.path is defined + - not (repo_dir_stat.stat.exists | default(false)) + tags: always - name: Update Inventory Path ansible.builtin.set_fact: + # Use the actual repository path from git_retrieve or existing repo + # This path is used by backup.yaml to set network_backup_path_root network_backup_path: "{{ network_backup_repository['path'] }}" + tags: always diff --git a/roles/backup/tasks/validation.yaml b/roles/backup/tasks/validation.yaml index 4598f4d..b05a844 100644 --- a/roles/backup/tasks/validation.yaml +++ b/roles/backup/tasks/validation.yaml @@ -8,7 +8,9 @@ - "nxos" - "iosxr" - "vyos" + tags: always - name: Conditional test ansible.builtin.include_tasks: "unsupported_platform.yaml" when: ansible_network_os.split('.')[-1] not in supported_platforms + tags: always diff --git a/roles/restore/tasks/cli_restore.yaml b/roles/restore/tasks/cli_restore.yaml index 6d2f280..fd0f080 100644 --- a/roles/restore/tasks/cli_restore.yaml +++ b/roles/restore/tasks/cli_restore.yaml @@ -2,6 +2,7 @@ - name: Get current timestamp ansible.builtin.set_fact: timestamp: "{{ lookup('pipe', 'date +%Y%m%d%H%M%S') }}" + tags: always - name: Set content specific facts ansible.builtin.set_fact: @@ -11,16 +12,18 @@ delete_path: "{{ role_path }}/tasks/delete" health_check_path: "{{ role_path }}/tasks/health_checks" delete_backup_from_dest: true + tags: always - name: Check if file copy is possible ansible.builtin.include_tasks: "{{ health_check_path }}/{{ network_os }}.yaml" + tags: always - name: Copy file from src to a network device ansible.netcommon.net_put: src: "{{ network_restore_backup_path }}/{{ network_backup_restore_filename }}" dest: "{{ file_name }}.txt" when: network_os in ['iosxr', 'nxos', 'eos', 'junos'] - + tags: always - name: Copy file using system SCP CLI as a workaround for ios quirk and libssh SCP ansible.builtin.command: > @@ -32,21 +35,31 @@ delegate_to: localhost when: network_os == "ios" changed_when: true + tags: always - name: Prepare appliance for a restore operation ansible.builtin.include_tasks: "{{ prepare_path }}/{{ network_os }}.yaml" + tags: always + +- name: Set default appliance_dir per network OS if not provided + ansible.builtin.set_fact: + appliance_dir: "{{ appliance_dir | default('flash://' if network_os == 'ios' else 'flash:' if network_os == 'iosxr' else '/var/tmp' if network_os == 'junos' else 'flash:' if network_os == 'nxos' else 'flash:' if network_os == 'eos' else 'flash:') }}" + tags: always - name: Restore operation for {{ network_os }} ansible.netcommon.cli_restore: filename: "{{ file_name }}.txt" path: "{{ appliance_dir }}" + tags: always - name: Delete backup from appliance ansible.builtin.include_tasks: "{{ delete_path }}/{{ network_os }}.yaml" when: delete_backup_from_dest + tags: always - name: Remove locally cloned repo ansible.builtin.file: path: "{{ network_restore_backup_repo }}" state: absent when: data_store.scm.origin.path is defined + tags: always \ No newline at end of file diff --git a/roles/restore/tasks/cli_restore_config.yaml b/roles/restore/tasks/cli_restore_config.yaml index 57f6824..432595f 100644 --- a/roles/restore/tasks/cli_restore_config.yaml +++ b/roles/restore/tasks/cli_restore_config.yaml @@ -2,6 +2,8 @@ - name: Set content specific facts ansible.builtin.set_fact: cli_restore_path: "{{ role_path }}/cli_restore" + tags: always - name: Invoke restore operation ansible.builtin.include_tasks: "{{ cli_restore_path }}/{{ network_os }}.yaml" + tags: always \ No newline at end of file diff --git a/roles/restore/tasks/common/validation.yaml b/roles/restore/tasks/common/validation.yaml index cd0bd2c..ac4ed7f 100644 --- a/roles/restore/tasks/common/validation.yaml +++ b/roles/restore/tasks/common/validation.yaml @@ -7,7 +7,9 @@ - "eos" - "nxos" - "iosxr" + tags: always - name: Conditional test ansible.builtin.include_tasks: "common/unsupported_platform.yaml" when: ansible_network_os.split('.')[-1] not in supported_platforms + tags: always \ No newline at end of file diff --git a/roles/restore/tasks/main.yaml b/roles/restore/tasks/main.yaml index f45aa21..720dd51 100644 --- a/roles/restore/tasks/main.yaml +++ b/roles/restore/tasks/main.yaml @@ -1,6 +1,8 @@ --- - name: Include tasks ansible.builtin.include_tasks: common/validation.yaml + tags: always - name: Run the platform specific tasks ansible.builtin.include_tasks: "restore.yaml" + tags: always \ No newline at end of file diff --git a/roles/restore/tasks/network.yaml b/roles/restore/tasks/network.yaml index cc87c5d..db03e3c 100644 --- a/roles/restore/tasks/network.yaml +++ b/roles/restore/tasks/network.yaml @@ -9,11 +9,14 @@ - "ios" - "junos" network_os: "{{ ansible_network_os.split('.')[2] }}" + tags: always - name: Invoke restore ansible.builtin.include_tasks: "cli_restore.yaml" when: network_os not in supported_cli_restore + tags: always - name: Invoke cli specific backup task ansible.builtin.include_tasks: "cli_restore_config.yaml" when: network_os not in supported_plugin_restore + tags: always \ No newline at end of file diff --git a/roles/restore/tasks/prepare/ios.yaml b/roles/restore/tasks/prepare/ios.yaml index be86349..75162e4 100644 --- a/roles/restore/tasks/prepare/ios.yaml +++ b/roles/restore/tasks/prepare/ios.yaml @@ -4,6 +4,10 @@ msg: - "Task to prepare appliance for restore operation" +- name: Set IOS directory for restore operation + ansible.builtin.set_fact: + appliance_dir: "flash://" + - name: Overwrite startup config - archive cisco.ios.ios_config: lines: diff --git a/roles/restore/tasks/restore.yaml b/roles/restore/tasks/restore.yaml index 5441e1d..12b57bd 100644 --- a/roles/restore/tasks/restore.yaml +++ b/roles/restore/tasks/restore.yaml @@ -3,30 +3,37 @@ ansible.builtin.set_fact: network_restore_backup_path: "./tmp_backup" when: data_store.local is not defined + tags: always - name: Set default host vars path ansible.builtin.set_fact: network_restore_backup_path: "{{ data_store['local']['path'] }}" when: data_store['local'] is defined + tags: always - name: Set default host vars filename ansible.builtin.set_fact: network_backup_restore_filename: "{{ data_store['local']['filename'] }}" when: data_store['local'] is defined + tags: always - name: Set default host vars path ansible.builtin.set_fact: - network_backup_restore_relative_path: "{{ data_store['scm']['origin']['path'] }}" + network_restore_backup_relative_path: "{{ data_store['scm']['origin']['path'] }}" when: data_store['scm'] is defined + tags: always - name: Set default host vars filename ansible.builtin.set_fact: network_backup_restore_filename: "{{ data_store['scm']['origin']['filename'] }}" when: data_store['scm'] is defined + tags: always - name: Retrieve a repository from a distant location and make it available locally ansible.builtin.include_tasks: retrieve.yaml when: data_store.scm is defined + tags: always - name: Include tasks ansible.builtin.include_tasks: network.yaml + tags: always \ No newline at end of file diff --git a/roles/restore/tasks/retrieve.yaml b/roles/restore/tasks/retrieve.yaml index 5c39f3b..92aa2fb 100644 --- a/roles/restore/tasks/retrieve.yaml +++ b/roles/restore/tasks/retrieve.yaml @@ -6,14 +6,18 @@ token: "{{ data_store.scm.origin.get('token') if data_store.scm.origin.get('token') else omit }}" ssh_key_file: "{{ data_store.scm.origin.get('ssh_key_file') if data_store.scm.origin.get('ssh_key_file') else omit }}" ssh_key_content: "{{ data_store.scm.origin.get('ssh_key_content') if data_store.scm.origin.get('ssh_key_content') else omit }}" - parent_directory: "{{ role_path }}/{{ network_restore_backup_path }}" + # Use parent_directory from data_store.scm if provided, otherwise default to role_path + parent_directory: "{{ data_store.scm.parent_directory | default(role_path ~ '/' ~ network_restore_backup_path) }}" changed_when: false register: resource_manager_result + tags: always - name: Update Inventory Path ansible.builtin.set_fact: network_restore_backup_repo: "{{ resource_manager_result['path'] }}" + tags: always - name: Update Inventory Path ansible.builtin.set_fact: network_restore_backup_path: "{{ resource_manager_result['path'] }}/{{ data_store['scm']['origin']['path'] }}" + tags: always \ No newline at end of file diff --git a/roles/restore/tmp_backup/network_automation_tools b/roles/restore/tmp_backup/network_automation_tools new file mode 160000 index 0000000..cce4a3d --- /dev/null +++ b/roles/restore/tmp_backup/network_automation_tools @@ -0,0 +1 @@ +Subproject commit cce4a3d4ff5f9fbc801aa8d747e2713f90e04cde