diff --git a/roles/ansible/tasks/update_local_facts.yml b/roles/ansible/tasks/update_local_facts.yml index baed31b..334a79b 100644 --- a/roles/ansible/tasks/update_local_facts.yml +++ b/roles/ansible/tasks/update_local_facts.yml @@ -21,8 +21,8 @@ vars: recurse_strategy: "{{ ansible__local_fact_combine_recursive | default(true) | bool }}" list_merge_strategy: "{{ ansible__local_fact_combine_list_merge | default('prepend') }}" - host_local_facts: "{{ ansible_local[ansible__local_fact_name] | default({'init': now().utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ')}) | - combine(ansible__local_fact_updates, recursive=recurse_strategy, list_merge=list_merge_strategy) }}" + host_local_facts: "{{ ansible_local[ansible__local_fact_name] | default({'created_at': now().utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ')}) | + combine(ansible__local_fact_updates, {'updated_at': now().utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ')}, recursive=recurse_strategy, list_merge=list_merge_strategy) }}" register: ansible__settle_local_facts when: - ansible__role_enabled | bool diff --git a/roles/package_manager/defaults/main.yml b/roles/package_manager/defaults/main.yml index e373f96..a0240f5 100644 --- a/roles/package_manager/defaults/main.yml +++ b/roles/package_manager/defaults/main.yml @@ -17,6 +17,8 @@ package_manager__upgrade_strategy: once # Available options for DNF: full, clean_full # Clean options temproarily removes all repos other than OS default repos before upgrade package_manager__upgrade_mode: clean_full +# This option removes the backup repo list files in clean upgrade mode after upgrade +package_manager__clean_upgrade_post_remove_backups: true # Shared Options: package_manager__repo_list_disabled_template: common/repo_list_disabled.j2 diff --git a/roles/package_manager/files/dummy-apt-source.list b/roles/package_manager/files/dummy-apt-source.list new file mode 100644 index 0000000..f7055f7 --- /dev/null +++ b/roles/package_manager/files/dummy-apt-source.list @@ -0,0 +1 @@ +# Dummy repo list as default \ No newline at end of file diff --git a/roles/package_manager/handlers/main.yml b/roles/package_manager/handlers/main.yml index 502e830..3dd5e87 100644 --- a/roles/package_manager/handlers/main.yml +++ b/roles/package_manager/handlers/main.yml @@ -18,7 +18,7 @@ ansible.builtin.apt: update_cache: true register: package_manager__deb_update_repo_cache - listen: "package_manager__deb_update_repo_cache" + listen: "package_manager__update_repo_cache" when: - ansible_os_family | lower == 'debian' @@ -27,7 +27,7 @@ ansible.builtin.command: cmd: yum clean metadata register: package_manager__rpm_clean_metadata_cache - listen: "package_manager__rpm_clean_metadata_cache" + listen: "package_manager__update_repo_cache" when: - ansible_os_family | lower == 'redhat' diff --git a/roles/package_manager/tasks/main.yml b/roles/package_manager/tasks/main.yml index a883a77..73398c4 100644 --- a/roles/package_manager/tasks/main.yml +++ b/roles/package_manager/tasks/main.yml @@ -41,7 +41,6 @@ ansible_callback_diy_runner_on_skipped_msg: | skipping: [{{ inventory_hostname }}] msg: {{ __package_manager__upgrade_execute.reason }} - ansible_callback_diy_runner_on_skipped_msg_color: green # FIXME: Commented out for testing. Uncomment after testing. # - name: Import DEB package tasks (APT) diff --git a/roles/package_manager/tasks/upgrade.yml b/roles/package_manager/tasks/upgrade.yml index 2c374f6..c57cb8c 100644 --- a/roles/package_manager/tasks/upgrade.yml +++ b/roles/package_manager/tasks/upgrade.yml @@ -1,194 +1,142 @@ --- -- name: Find repo list files (Clean Upgrade) - become: true - ansible.builtin.find: - paths: "{{ package_manager__repo_list_dir }}" - patterns: "{{ package_manager__repo_list_patterns }}" - use_regex: "{{ package_manager__repo_list_use_regex | bool }}" - register: package_manager__upgrade_clean_find_repo_list_files - when: - - __package_manager__upgrade_clean | default(false) | bool +- name: Perform upgrade with rescue options + block: + - name: Find repo list files (Clean Upgrade) + become: true + ansible.builtin.find: + paths: "{{ package_manager__repo_list_dir }}" + patterns: "{{ package_manager__repo_list_patterns }}" + use_regex: "{{ package_manager__repo_list_use_regex | bool }}" + register: package_manager__upgrade_clean_find_repo_list_files + when: + - __package_manager__upgrade_clean | default(false) | bool -- name: Deploy default repo lists by copy (Clean Upgrade) - become: true - ansible.builtin.copy: - src: "{{ item.src }}" - dest: "{{ item.dest }}" - backup: true - loop: "{{ __package_manager__repo_list_defaults_copy }}" - register: package_manager__upgrade_clean_default_repo_list_copies - when: - - __package_manager__upgrade_clean | default(false) | bool - - __package_manager__repo_list_defaults_copy | length > 0 + - name: Deploy default repo lists by copy with backups (Clean Upgrade) + become: true + ansible.builtin.copy: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + backup: true + loop: "{{ __package_manager__repo_list_defaults_copy }}" + register: package_manager__upgrade_clean_default_repo_list_copies + notify: "package_manager__update_repo_cache" + when: + - __package_manager__upgrade_clean | default(false) | bool + - __package_manager__repo_list_defaults_copy | length > 0 -# TODO: Gather backup file paths -- name: Deploy default repo lists by template (Clean Upgrade) - become: true - ansible.builtin.template: - src: "{{ item.src }}" - dest: "{{ item.dest }}" - backup: true - loop: "{{ repo_list_templates }}" - vars: - repo_lists_default: "{{ __package_manager__repo_list_defaults_template | default([]) }}" - repo_list_additonals_src: "{{ package_manager__upgrade_clean_find_repo_list_files.files | map(attribute='path') | default([]) }}" - repo_lists_additional: "{{ (repo_list_additonals_src | length > 0) | - ternary( - {'dest': repo_list_additonals_src} | aybarsm.helper.to_list_of_dicts(defaults={'src': package_manager__repo_list_disabled_template}), - []) }}" - repo_list_templates: "{{ repo_lists_default + repo_lists_additional }}" - register: package_manager__upgrade_clean_default_repo_list_templates - when: - - __package_manager__upgrade_clean | default(false) | bool - - (__package_manager__repo_list_defaults_template | length > 0) or (package_manager__upgrade_clean_find_repo_list_files.files | default([]) | length > 0) + - name: Deploy default repo lists by template with backups (Clean Upgrade) + become: true + ansible.builtin.template: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + backup: true + loop: "{{ repo_list_templates }}" + vars: + repo_lists_default: "{{ __package_manager__repo_list_defaults_template | default([]) }}" + repo_list_additonals_src: "{{ package_manager__upgrade_clean_find_repo_list_files.files | map(attribute='path') | default([]) }}" + repo_lists_additional: "{{ (repo_list_additonals_src | length > 0) | + ternary( + {'dest': repo_list_additonals_src} | aybarsm.helper.to_list_of_dicts(defaults={'src': package_manager__repo_list_disabled_template}), + []) | + rejectattr('dest', 'in', (__package_manager__repo_list_defaults | map(attribute='dest'))) }}" + repo_list_templates: "{{ repo_lists_default + repo_lists_additional }}" + register: package_manager__upgrade_clean_default_repo_list_templates + notify: "package_manager__update_repo_cache" + when: + - __package_manager__upgrade_clean | default(false) | bool + - repo_list_templates | length > 0 -- name: Debug found files - ansible.builtin.debug: - msg: - list_templates: "{{ package_manager__upgrade_clean_default_repo_list_templates }}" - # repo_lists_default: "{{ repo_lists_default }}" - # repo_lists_additional: "{{ repo_lists_additional }}" - # repo_list_additonals_src: "{{ repo_list_additonals_src }}" - # repo_list_templates: "{{ repo_list_templates }}" - # vars: - # repo_lists_default: "{{ __package_manager__repo_list_defaults_template | default([]) }}" - # repo_list_additonals_src: "{{ package_manager__upgrade_clean_find_repo_list_files.files | map(attribute='path') | default([]) }}" - # repo_lists_additional: "{{ (repo_list_additonals_src | length > 0) | - # ternary( - # {'dest': repo_list_additonals_src} | aybarsm.helper.to_list_of_dicts(defaults={'src': package_manager__repo_list_disabled_template}), - # []) }}" - # repo_list_templates: "{{ repo_lists_default + repo_lists_additional }}" - when: - - __package_manager__upgrade_clean | default(false) | bool - # - (__package_manager__repo_list_defaults_template | length > 0) or (package_manager__upgrade_clean_find_repo_list_files.files | default([]) | length > 0) - - -# register: package_manager__upgrade_clean_default_repo_list_templates -# when: -# - __package_manager__upgrade_clean | default(false) | bool -# - (__package_manager__repo_list_defaults_template | length > 0) or (package_manager__upgrade_clean_find_repo_list_files.files | default([]) | length > 0) + - name: Update package manager cache after repo list changes (Clean Upgrade) + ansible.builtin.meta: 'flush_handlers' + when: package_manager__upgrade_clean_default_repo_list_copies.changed or package_manager__upgrade_clean_default_repo_list_templates.changed + + - name: Perform DEB package upgrade via APT + become: true + ansible.builtin.apt: + update_cache: "{{ update_repo_cache }}" + upgrade: "{{ __package_manager__upgrade_mode }}" + dpkg_options: "{{ package_manager__upgrade_dpkg_options | default(omit) }}" + register: package_manager__upgrade_deb + vars: + handler_triggered: "{{ package_manager__upgrade_clean_default_repo_list_copies.changed or package_manager__upgrade_clean_default_repo_list_templates.changed }}" + update_repo_cache: "{{ false if handler_triggered else package_manager__upgrade_update_repo_cache }}" + when: + - ansible_os_family | lower == 'debian' -# - name: Set facts for backup and restore (Clean Upgrade) -# ansible.builtin.set_fact: -# __package_manager__clean_upgrade_backup: "{{ {'src': backup_src, 'dest': backup_dest} | aybarsm.helper.to_list_of_dicts }}" -# __package_manager__clean_upgrade_restore: "{{ {'src': backup_dest, 'dest': backup_src} | aybarsm.helper.to_list_of_dicts }}" -# vars: -# main_repo_list: "{{ -# (package_manager__upgrade_main_repo_list_stat.stat.exist is defined and package_manager__upgrade_main_repo_list_stat.stat.exist is truthy ) | -# ternary( -# [package_manager__upgrade_main_repo_list_stat.stat.path], -# [] -# ) -# }}" -# repo_lists: "{{ (package_manager__upgrade_find_repo_list_files.files.length > 0) | -# ternary( -# (package_manager__upgrade_find_repo_list_files.files | map(attribute='path') | list), -# [] -# ) -# }}" -# backup_src: "{{ main_repo_list + repo_lists }}" -# backup_dest: "{{ backup_src | map('regex_replace', '^(.*)$', '\\1.' + now().utcnow().strftime('%Y%m%dT%H%M%S.%fZ') + '.disabled') }}" -# register: package_manager__upgrade_set_facts_backup_restore -# when: -# - __package_manager__upgrade_clean | default(false) | bool -# - package_manager__upgrade_main_repo_list_stat.stat.exist is defined + - name: Clean RPM repo metadata cache before upgrade, if not already via clean upgrade + become: true + ansible.builtin.command: + cmd: yum clean metadata + vars: + handler_triggered: "{{ package_manager__upgrade_clean_default_repo_list_copies.changed or package_manager__upgrade_clean_default_repo_list_templates.changed }}" + update_repo_cache: "{{ false if handler_triggered else package_manager__upgrade_update_repo_cache }}" + register: package_manager__rpm_upgrade_clean_cache_pre + when: + - ansible_os_family | lower == 'redhat' + - update_repo_cache -# - name: Copy (Backup) repo list files and directory (Clean Upgrade) -# become: true -# ansible.builtin.copy: -# src: "{{ item.src }}" -# dest: "{{ item.dest }}" -# remote_src: true -# loop: "{{ __package_manager__clean_upgrade_backup }}" -# register: package_manager__upgrade_repo_list_backup -# when: -# - __package_manager__upgrade_clean | default(false) | bool -# - __package_manager__clean_upgrade_backup is defined -# - __package_manager__clean_upgrade_backup | length > 0 + - name: Perform RPM package upgrade via DNF + become: true + ansible.builtin.dnf: + name: "*" + state: latest + register: package_manager__rpm_upgrade + when: ansible_os_family | lower == 'redhat' -# - name: Temproarily remove repo list files and directory (Clean Upgrade) -# become: true -# ansible.builtin.file: -# path: "{{ item.src }}" -# state: absent -# loop: "{{ __package_manager__clean_upgrade_backup }}" -# register: package_manager__upgrade_repo_list_remove -# when: -# - __package_manager__upgrade_clean | default(false) | bool -# - __package_manager__clean_upgrade_backup is defined -# - __package_manager__clean_upgrade_backup | length > 0 + - name: Include update local facts tasks + ansible.builtin.include_role: + name: aybarsm.linux.ansible + tasks_from: update_local_facts.yml + vars: + ansible__local_fact_updates: + package_manager: + upgrade: ["{{ now().utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ') }}"] + when: + - __package_manager__upgrade_once + - package_manager__upgrade_deb.success or package_manager__rpm_upgrade.success + rescue: + - name: Inform when errors + ansible.builtin.debug: + msg: 'Upgrade process failed. Any changes will be reverted back.' + always: + - name: Restore (copy) repo list files and directory (Clean Upgrade) + become: true + ansible.builtin.copy: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + remote_src: true + backup: false + loop: "{{ restore_files }}" + vars: + repo_list_copies: "{{ package_manager__upgrade_clean_default_repo_list_copies.results | default([]) | + selectattr('backup_file', 'defined') | selectattr('dest', 'defined') }}" + repo_list_templates: "{{ package_manager__upgrade_clean_default_repo_list_templates.results | default([]) | + selectattr('backup_file', 'defined') | selectattr('dest', 'defined') }}" + restore_src: "{{ (repo_list_copies | map(attribute='backup_file') | default([])) + (repo_list_templates | map(attribute='backup_file') | default([])) }}" + restore_dest: "{{ (repo_list_copies | map(attribute='dest') | default([])) + (repo_list_templates | map(attribute='dest') | default([])) }}" + restore_files: "{{ (restore_src | length > 0) | + ternary( + {'src': restore_src, 'dest': restore_dest} | aybarsm.helper.to_list_of_dicts, + [] + ) }}" + register: package_manager__upgrade_clean_restore_repo_lists + notify: "package_manager__update_repo_cache" + when: + - __package_manager__upgrade_clean | default(false) | bool + - restore_files | length > 0 -# - name: Perform DEB package upgrade via APT -# become: true -# ansible.builtin.apt: -# update_cache: "{{ update_cache }}" -# upgrade: "{{ upgrade_mode }}" -# dpkg_options: "{{ package_manager__upgrade_dpkg_options | default(omit) }}" -# vars: -# upgrade_mode: "{{ package_manager__upgrade_mode | regex_replace('clean_', '') }}" -# update_cache: "{{ (__package_manager__upgrade_clean | default(false) | bool) or (package_manager__upgrade_update_repo_cache | default(true) | bool) }}" -# register: package_manager__deb_upgrade -# when: -# - ansible_os_family | lower == 'debian' -# - package_manager__upgrade_mode is defined -# - upgrade_mode in __package_manager__upgrade_modes + - name: Remove backup repo list files (Clean Upgrade) + become: true + ansible.builtin.file: + path: "{{ item }}" + state: absent + loop: "{{ package_manager__upgrade_clean_restore_repo_lists.results | map(attribute='src') }}" + register: package_manager__upgrade_clean_remove_backup_repo_lists + when: + - __package_manager__upgrade_clean | default(false) | bool + - package_manager__clean_upgrade_post_remove_backups | default(false) | bool + - package_manager__upgrade_clean_restore_repo_lists.results | default([]) | length > 0 -# - name: Clean RPM repo metadata cache before upgrade -# become: true -# ansible.builtin.command: -# cmd: yum clean metadata -# vars: -# update_cache: "{{ (__package_manager__upgrade_clean | default(false) | bool) or (package_manager__upgrade_update_repo_cache | default(true) | bool) }}" -# register: package_manager__rpm_upgrade_clean_cache_pre -# when: -# - ansible_os_family | lower == 'redhat' -# - update_cache - -# - name: Perform RPM package upgrade via DNF -# become: true -# ansible.builtin.dnf: -# name: "*" -# state: latest -# register: package_manager__rpm_upgrade -# when: ansible_os_family | lower == 'redhat' - -# - name: Copy (Restore) repo list files and directory (Clean Upgrade) -# become: true -# ansible.builtin.copy: -# src: "{{ item.src }}" -# dest: "{{ item.dest }}" -# remote_src: true -# loop: "{{ __package_manager__clean_upgrade_restore }}" -# register: package_manager__upgrade_repo_list_restore -# when: -# - __package_manager__upgrade_clean -# - __package_manager__clean_upgrade_restore is defined -# - __package_manager__clean_upgrade_restore | length > 0 - -# - name: Remove temporary directory for repo lists (Clean Upgrade) -# become: true -# ansible.builtin.tempfile: -# path: "{{ package_manager__upgrade_create_temp_repo_dir.path }}" -# state: absent -# register: package_manager__upgrade_remove_temp_repo_dir -# when: -# - __package_manager__upgrade_clean -# - package_manager__upgrade_create_temp_repo_dir.path is defined - -# - name: Update DEB repo cache via APT after upgrade (Clean Upgrade) -# become: true -# ansible.builtin.apt: -# update_cache: true -# register: package_manager__deb_upgrade_clean_cache_post -# when: -# - ansible_os_family | lower == 'debian' -# - __package_manager__upgrade_clean | default(false) | bool - -# - name: Clean RPM repo metadata cache after upgrade (Clean Upgrade) -# become: true -# ansible.builtin.command: -# cmd: yum clean metadata -# register: package_manager__rpm_upgrade_clean_cache_post -# when: -# - ansible_os_family | lower == 'redhat' -# - __package_manager__upgrade_clean | default(false) | bool \ No newline at end of file + - name: Update package manager cache after repo list changes (Clean Upgrade) + ansible.builtin.meta: 'flush_handlers' + when: package_manager__upgrade_clean_restore_repo_lists.changed diff --git a/roles/package_manager/vars/debian.yml b/roles/package_manager/vars/debian.yml index 37db278..900f008 100644 --- a/roles/package_manager/vars/debian.yml +++ b/roles/package_manager/vars/debian.yml @@ -3,6 +3,7 @@ __package_manager__upgrade_modes: ['full', 'safe', 'yes', 'dist'] package_manager__repo_list_dir: /etc/apt/sources.list.d package_manager__repo_list_patterns: [".*\\.list$"] package_manager__upgrade_dpkg_options: '' +__package_manager__upgrade_update_cache_handler: package_manager__deb_update_repo_cache __package_manager__config: packages: diff --git a/roles/package_manager/vars/redhat.yml b/roles/package_manager/vars/redhat.yml index 210c516..6de9908 100644 --- a/roles/package_manager/vars/redhat.yml +++ b/roles/package_manager/vars/redhat.yml @@ -4,6 +4,7 @@ __package_manager__has_main_repo_list: false package_manager__repo_list_dir: /etc/yum.repos.d package_manager__repo_list_use_regex: true package_manager__repo_list_patterns: [".*\\.repo$"] +__package_manager__upgrade_update_cache_handler: package_manager__rpm_clean_metadata_cache __package_manager__clean_upgrade_modes: "{{ ['clean_'] | product(__package_manager__upgrade_modes) | map('join') }}"