From c94df9fefa400ef9f8e5f8a7307af5bcd02dce87 Mon Sep 17 00:00:00 2001 From: mathieu Date: Sun, 24 May 2026 16:40:42 +0200 Subject: [PATCH] feat: initial cross-distro package management role Supports apt, dnf, yum, pacman, apk and zypper. Variables cover install, remove, upgrade, cache refresh and autoremove. --- .gitignore | 1 + README.md | 43 +++++++++++++++++++++++++++++++++++++++++++ defaults/main.yml | 8 ++++++++ handlers/main.yml | 1 + meta/main.yml | 38 ++++++++++++++++++++++++++++++++++++++ tasks/apk.yml | 26 ++++++++++++++++++++++++++ tasks/apt.yml | 34 ++++++++++++++++++++++++++++++++++ tasks/dnf.yml | 33 +++++++++++++++++++++++++++++++++ tasks/main.yml | 9 +++++++++ tasks/pacman.yml | 26 ++++++++++++++++++++++++++ tasks/yum.yml | 27 +++++++++++++++++++++++++++ tasks/zypper.yml | 27 +++++++++++++++++++++++++++ 12 files changed, 273 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 defaults/main.yml create mode 100644 handlers/main.yml create mode 100644 meta/main.yml create mode 100644 tasks/apk.yml create mode 100644 tasks/apt.yml create mode 100644 tasks/dnf.yml create mode 100644 tasks/main.yml create mode 100644 tasks/pacman.yml create mode 100644 tasks/yum.yml create mode 100644 tasks/zypper.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a8b42eb --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.retry diff --git a/README.md b/README.md new file mode 100644 index 0000000..13d404d --- /dev/null +++ b/README.md @@ -0,0 +1,43 @@ +# ansible-role-packages + +Manages Linux packages across distributions using the native package manager. + +Supported package managers: `apt`, `dnf`, `yum`, `pacman`, `apk`, `zypper`. + +## Requirements + +- Ansible >= 2.14 +- `community.general` collection (required for Arch, Alpine, openSUSE targets) + +## Role Variables + +| Variable | Default | Description | +|---|---|---| +| `packages_install` | `[]` | List of packages to install | +| `packages_remove` | `[]` | List of packages to remove | +| `packages_state` | `present` | State for installed packages: `present` or `latest` | +| `packages_upgrade` | `false` | Upgrade all packages on the system | +| `packages_update_cache` | `true` | Refresh the package cache before operations | +| `packages_cache_valid_time` | `3600` | Maximum cache age in seconds before forcing a refresh (apt only) | +| `packages_autoremove` | `false` | Remove unused dependencies after operations (apt, dnf only) | + +## Example Playbook + +```yaml +- hosts: servers + roles: + - role: ansible-role-packages + vars: + packages_install: + - curl + - git + - vim + packages_remove: + - telnet + packages_update_cache: true + packages_upgrade: false +``` + +## License + +MIT diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..8b92050 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,8 @@ +--- +packages_install: [] +packages_remove: [] +packages_upgrade: false +packages_update_cache: true +packages_cache_valid_time: 3600 +packages_state: present +packages_autoremove: false diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1 @@ +--- diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..166ea8b --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,38 @@ +--- +galaxy_info: + author: mathieu + description: Cross-distribution Linux package management + license: MIT + min_ansible_version: "2.14" + platforms: + - name: Debian + versions: + - bullseye + - bookworm + - name: Ubuntu + versions: + - focal + - jammy + - noble + - name: EL + versions: + - "8" + - "9" + - name: Fedora + versions: + - all + - name: ArchLinux + versions: + - all + - name: Alpine + versions: + - all + - name: opensuse + versions: + - all + galaxy_tags: + - packages + - system + - linux + +dependencies: [] diff --git a/tasks/apk.yml b/tasks/apk.yml new file mode 100644 index 0000000..8e21c64 --- /dev/null +++ b/tasks/apk.yml @@ -0,0 +1,26 @@ +--- +- name: Update apk cache + community.general.apk: + update_cache: true + become: true + when: packages_update_cache | bool + +- name: Upgrade all packages + community.general.apk: + upgrade: true + become: true + when: packages_upgrade | bool + +- name: Install packages + community.general.apk: + name: "{{ packages_install }}" + state: "{{ packages_state }}" + become: true + when: packages_install | length > 0 + +- name: Remove packages + community.general.apk: + name: "{{ packages_remove }}" + state: absent + become: true + when: packages_remove | length > 0 diff --git a/tasks/apt.yml b/tasks/apt.yml new file mode 100644 index 0000000..5a7b307 --- /dev/null +++ b/tasks/apt.yml @@ -0,0 +1,34 @@ +--- +- name: Update apt cache + ansible.builtin.apt: + update_cache: true + cache_valid_time: "{{ packages_cache_valid_time }}" + become: true + when: packages_update_cache | bool + +- name: Upgrade all packages + ansible.builtin.apt: + upgrade: dist + become: true + when: packages_upgrade | bool + +- name: Install packages + ansible.builtin.apt: + name: "{{ packages_install }}" + state: "{{ packages_state }}" + become: true + when: packages_install | length > 0 + +- name: Remove packages + ansible.builtin.apt: + name: "{{ packages_remove }}" + state: absent + purge: false + become: true + when: packages_remove | length > 0 + +- name: Remove unused dependencies + ansible.builtin.apt: + autoremove: true + become: true + when: packages_autoremove | bool diff --git a/tasks/dnf.yml b/tasks/dnf.yml new file mode 100644 index 0000000..0e9e161 --- /dev/null +++ b/tasks/dnf.yml @@ -0,0 +1,33 @@ +--- +- name: Update dnf cache + ansible.builtin.dnf: + update_cache: true + become: true + when: packages_update_cache | bool + +- name: Upgrade all packages + ansible.builtin.dnf: + name: "*" + state: latest + become: true + when: packages_upgrade | bool + +- name: Install packages + ansible.builtin.dnf: + name: "{{ packages_install }}" + state: "{{ packages_state }}" + become: true + when: packages_install | length > 0 + +- name: Remove packages + ansible.builtin.dnf: + name: "{{ packages_remove }}" + state: absent + become: true + when: packages_remove | length > 0 + +- name: Remove unused dependencies + ansible.builtin.dnf: + autoremove: true + become: true + when: packages_autoremove | bool diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..ffa30ed --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,9 @@ +--- +- name: Assert supported package manager + ansible.builtin.assert: + that: + - ansible_pkg_mgr in ['apt', 'dnf', 'yum', 'pacman', 'apk', 'zypper'] + fail_msg: "Package manager '{{ ansible_pkg_mgr }}' is not supported by this role" + +- name: Include package manager tasks + ansible.builtin.include_tasks: "{{ ansible_pkg_mgr }}.yml" diff --git a/tasks/pacman.yml b/tasks/pacman.yml new file mode 100644 index 0000000..f564f09 --- /dev/null +++ b/tasks/pacman.yml @@ -0,0 +1,26 @@ +--- +- name: Update pacman cache + community.general.pacman: + update_cache: true + become: true + when: packages_update_cache | bool + +- name: Upgrade all packages + community.general.pacman: + upgrade: true + become: true + when: packages_upgrade | bool + +- name: Install packages + community.general.pacman: + name: "{{ packages_install }}" + state: "{{ packages_state }}" + become: true + when: packages_install | length > 0 + +- name: Remove packages + community.general.pacman: + name: "{{ packages_remove }}" + state: absent + become: true + when: packages_remove | length > 0 diff --git a/tasks/yum.yml b/tasks/yum.yml new file mode 100644 index 0000000..6916a03 --- /dev/null +++ b/tasks/yum.yml @@ -0,0 +1,27 @@ +--- +- name: Update yum cache + ansible.builtin.yum: + update_cache: true + become: true + when: packages_update_cache | bool + +- name: Upgrade all packages + ansible.builtin.yum: + name: "*" + state: latest + become: true + when: packages_upgrade | bool + +- name: Install packages + ansible.builtin.yum: + name: "{{ packages_install }}" + state: "{{ packages_state }}" + become: true + when: packages_install | length > 0 + +- name: Remove packages + ansible.builtin.yum: + name: "{{ packages_remove }}" + state: absent + become: true + when: packages_remove | length > 0 diff --git a/tasks/zypper.yml b/tasks/zypper.yml new file mode 100644 index 0000000..aa2be0d --- /dev/null +++ b/tasks/zypper.yml @@ -0,0 +1,27 @@ +--- +- name: Refresh zypper repositories + community.general.zypper_repository: + runrefresh: true + become: true + when: packages_update_cache | bool + +- name: Upgrade all packages + community.general.zypper: + name: "*" + state: dist-upgrade + become: true + when: packages_upgrade | bool + +- name: Install packages + community.general.zypper: + name: "{{ packages_install }}" + state: "{{ packages_state }}" + become: true + when: packages_install | length > 0 + +- name: Remove packages + community.general.zypper: + name: "{{ packages_remove }}" + state: absent + become: true + when: packages_remove | length > 0