├── .travis.yml ├── LICENSE ├── README.md ├── defaults └── main.yml ├── meta └── main.yml ├── tasks ├── main.yml ├── package-apk.yml ├── package-apt.yml ├── package-brew.yml ├── package-dnf.yml ├── package-opkg.yml ├── package-pacman.yml ├── package-portage.yml ├── package-snap.yml ├── package-yum.yml └── package-zypper.yml ├── tests ├── inventory └── test.yml └── vars └── main.yml /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: python 3 | python: "2.7" 4 | 5 | # Do not use the new container infrastructure 6 | sudo: true 7 | 8 | # Install ansible 9 | addons: 10 | apt: 11 | packages: 12 | - python-pip 13 | 14 | notifications: 15 | webhooks: https://galaxy.ansible.com/api/v1/notifications/ 16 | 17 | install: 18 | # Install Ansible. 19 | - pip install ansible==2.4.6.0 20 | 21 | # Check ansible version 22 | - ansible --version 23 | 24 | # Create ansible.cfg with correct roles_path 25 | - printf '[defaults]\nroles_path=../' >ansible.cfg 26 | 27 | script: 28 | # Check the role/playbook's syntax. 29 | - ansible-playbook tests/test.yml -i tests/inventory --syntax-check 30 | 31 | # Run the role/playbook with ansible-playbook. 32 | - ansible-playbook tests/test.yml -i tests/inventory --connection=local --become 33 | 34 | # Run the role/playbook again, checking to make sure it's idempotent. 35 | - > 36 | ansible-playbook tests/test.yml -i tests/inventory --connection=local --become 37 | | grep -q 'changed=0.*failed=0' 38 | && (echo 'Idempotence test: pass' && exit 0) 39 | || (echo 'Idempotence test: fail' && exit 1) 40 | 41 | # Check if the test package (htop) is installed. 42 | - dpkg -s htop 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright © 2016 GROG 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the "Software"), 7 | to deal in the Software without restriction, including without limitation 8 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | and/or sell copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included 13 | in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 19 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 21 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Package 2 | 3 | [![Ansible Galaxy][galaxy_image]][galaxy_link] 4 | [![Build Status][travis_image]][travis_link] 5 | [![Latest tag][tag_image]][tag_url] 6 | [![Gitter chat][gitter_image]][gitter_url] 7 | 8 | A role for managing packages on different operating systems. 9 | 10 | This role currently supports apt, yum, dnf, brew, zypper, pacman, portage and snap. 11 | Feel free to send a pull or feature request to add your favorite package 12 | manager! 13 | 14 | **Attention:** 15 | 16 | - This role handles name differences between package managers but not between 17 | distributions using the same package manager. 18 | - Test coverage is rather small so please do report bugs! 19 | 20 | ## Requirements 21 | 22 | - Hosts should be bootstrapped for ansible usage (have python,...) 23 | - Root privileges, eg `become: yes` 24 | 25 | ## Role Variables 26 | 27 | | Variable | Description | Default value | 28 | |----------|-------------|---------------| 29 | | `package_list` | List of packages **(see details!)** | `[]` | 30 | | `package_list_host`| List of packages **(see details!)** | `[]` | 31 | | `package_list_group` | List of packages **(see details!)** | `[]` | 32 | | `package_state` | Default package state | 'present' | 33 | | `package_update_cache` | Update the cache? | `yes` | 34 | | `package_cache_valid_time` | How long is the package cache valid? (seconds) | 3600 | 35 | 36 | #### `package_list` details 37 | 38 | `package_list`, `package_list_host` and `package_list_group` are merged when 39 | managing the packages. You can use the host and group lists to specify 40 | packages per host or group. 41 | 42 | The package list allows you to define which packages must be managed. Each item 43 | in the list can have following attributes: 44 | 45 | | Variable | Description | required | 46 | |----------|-------------|----------| 47 | | `name` | Package name | yes | 48 | | `state` | Package state | no | 49 | | `apt` | Package name for apt | no | 50 | | `apt_ignore` | Ignore package for apt | no | 51 | | `apt_install_recommends` | Whether to install recommended dependencies apt | no | 52 | | `apk` | Package name for apk | no | 53 | | `apk_ignore` | Ignore package for apk | no | 54 | | `yum` | Package name for yum | no | 55 | | `yum_ignore` | Ignore package for yum | no | 56 | | `dnf` | Package name for dnf | no | 57 | | `dnf_ignore` | Ignore package for dnf | no | 58 | | `brew` | Package name for brew | no | 59 | | `brew_ignore` | Ignore package for brew | no | 60 | | `zypper` | Package name for zypper | no | 61 | | `zypper_ignore` | Ignore package for zypper | no | 62 | | `pacman` | Package name for pacman | no | 63 | | `pacman_ignore` | Ignore package for pacman | no | 64 | | `portage` | Package name for portage | no | 65 | | `portage_ignore` | Ignore package for portage | no | 66 | | `opkg` | Package name for opkg | no | 67 | | `opkg_ignore` | Ignore package for opkg | no | 68 | | `snap` | Package name for snap | no | 69 | 70 | By default `package_state` and `item.name` are used when managing the packages. 71 | If however `item.state` is defined or a more specific package name (eg 72 | `item.apt`) these will be used instead. If you want a package to be ignored for 73 | some package managers you can add `***_ignore`: yes. 74 | 75 | ##### `package_list` example 76 | 77 | ```yaml 78 | package_list: 79 | - name: package 80 | - name: package1 81 | state: absent 82 | - name: package2 83 | apt: package2_apt_name 84 | - name: package3 85 | apt_ignore: yes 86 | yum: package3_yum_name 87 | pacman: package3_pacman_name 88 | portage: package3_portage_name 89 | ``` 90 | 91 | ## Dependencies 92 | 93 | None. 94 | 95 | ## Example Playbook 96 | 97 | ```yaml 98 | --- 99 | - hosts: servers 100 | roles: 101 | - { role: GROG.package, 102 | become: yes, 103 | package_list: [ 104 | { name: htop, 105 | brew: htop-osx }, 106 | { name: tree } 107 | ] 108 | } 109 | ``` 110 | 111 | ## Contributing 112 | 113 | All assistance, changes or ideas [welcome][issues]! 114 | 115 | ## Author 116 | 117 | By [G. Roggemans][groggemans] 118 | 119 | ## License 120 | MIT 121 | 122 | [galaxy_image]: http://img.shields.io/badge/galaxy-GROG.package-660198.svg?style=flat 123 | [galaxy_link]: https://galaxy.ansible.com/GROG/package 124 | [travis_image]: https://travis-ci.org/GROG/ansible-role-package.svg?branch=master 125 | [travis_link]: https://travis-ci.org/GROG/ansible-role-package 126 | [tag_image]: https://img.shields.io/github/tag/GROG/ansible-role-package.svg 127 | [tag_url]: https://github.com/GROG/ansible-role-package/tags 128 | [gitter_image]: https://badges.gitter.im/GROG/chat.svg 129 | [gitter_url]: https://gitter.im/GROG/chat 130 | 131 | [issues]: https://github.com/GROG/ansible-role-package/issues 132 | [groggemans]: https://github.com/groggemans 133 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # List of packages 4 | package_list: [] 5 | 6 | # List of packages 7 | package_list_host: [] 8 | 9 | # List of packages 10 | package_list_group: [] 11 | 12 | # Packages state 13 | package_state: present 14 | 15 | # Update cache? 16 | package_update_cache: yes 17 | 18 | # Cache valid time 19 | package_cache_valid_time: 3600 20 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: G. Roggemans 4 | description: A role for installing packages on different operating systems. 5 | company: GROG 6 | license: MIT 7 | min_ansible_version: 2.4 8 | platforms: 9 | - name: EL 10 | versions: 11 | - all 12 | # - 5 13 | # - 6 14 | # - 7 15 | #- name: GenericUNIX 16 | # versions: 17 | # - all 18 | # - any 19 | - name: Fedora 20 | versions: 21 | - all 22 | # - 16 23 | # - 17 24 | # - 18 25 | # - 19 26 | # - 20 27 | # - 21 28 | # - 22 29 | #- name: Windows 30 | # versions: 31 | # - all 32 | # - 2012R2 33 | #- name: SmartOS 34 | # versions: 35 | # - all 36 | # - any 37 | - name: opensuse 38 | versions: 39 | - all 40 | # - 12.1 41 | # - 12.2 42 | # - 12.3 43 | # - 13.1 44 | # - 13.2 45 | #- name: Amazon 46 | # versions: 47 | # - all 48 | # - 2013.03 49 | # - 2013.09 50 | #- name: GenericBSD 51 | # versions: 52 | # - all 53 | # - any 54 | #- name: FreeBSD 55 | # versions: 56 | # - all 57 | # - 8.0 58 | # - 8.1 59 | # - 8.2 60 | # - 8.3 61 | # - 8.4 62 | # - 9.0 63 | # - 9.1 64 | # - 9.1 65 | # - 9.2 66 | - name: Ubuntu 67 | versions: 68 | - all 69 | # - lucid 70 | # - maverick 71 | # - natty 72 | # - oneiric 73 | # - precise 74 | # - quantal 75 | # - raring 76 | # - saucy 77 | # - trusty 78 | # - utopic 79 | # - vivid 80 | - name: SLES 81 | versions: 82 | - all 83 | # - 10SP3 84 | # - 10SP4 85 | # - 11 86 | # - 11SP1 87 | # - 11SP2 88 | # - 11SP3 89 | #- name: GenericLinux 90 | # versions: 91 | # - all 92 | # - any 93 | - name: Debian 94 | versions: 95 | - all 96 | # - etch 97 | # - jessie 98 | # - lenny 99 | # - squeeze 100 | # - wheezy 101 | galaxy_tags: 102 | - apt 103 | - yum 104 | - brew 105 | - zypper 106 | - pacman 107 | - portage 108 | - packaging 109 | 110 | allow_duplicates: yes 111 | 112 | dependencies: [] 113 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - include_tasks: "{{ package_manager }}" 4 | with_first_found: 5 | - "package-{{ ansible_pkg_mgr }}.yml" 6 | loop_control: 7 | loop_var: package_manager 8 | -------------------------------------------------------------------------------- /tasks/package-apk.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Apk 4 | apk: 5 | name: "{{ item.apk | default(item.name) }}" 6 | state: "{{ item.state | default(package_state) }}" 7 | update_cache: "{{ package_update_cache }}" 8 | when: (item.apk_ignore|default('no'))|string in 'False,false,No,no' 9 | with_items: "{{ packages }}" -------------------------------------------------------------------------------- /tasks/package-apt.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Apt 4 | apt: 5 | name: "{{ item.apt | default(item.name) }}" 6 | state: "{{ item.state | default(package_state) }}" 7 | update_cache: "{{ package_update_cache }}" 8 | cache_valid_time: "{{ package_cache_valid_time }}" 9 | install_recommends: "{{ item.apt_install_recommends | default(omit) }}" 10 | when: (item.apt_ignore|default('no'))|string in 'False,false,No,no' 11 | with_items: "{{ packages }}" 12 | -------------------------------------------------------------------------------- /tasks/package-brew.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Brew 4 | become: no 5 | homebrew: 6 | name: "{{ item.brew | default(item.name) }}" 7 | state: "{{ item.state | default(package_state) }}" 8 | when: (item.brew_ignore|default('no'))|string in 'False,false,No,no' 9 | with_items: "{{ packages }}" 10 | -------------------------------------------------------------------------------- /tasks/package-dnf.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: dnf 4 | dnf: 5 | name: "{{ item.dnf | default(item.name) }}" 6 | state: "{{ item.state | default(package_state) }}" 7 | when: (item.dnf_ignore|default('no'))|string in 'False,false,No,no' 8 | with_items: "{{ packages }}" 9 | -------------------------------------------------------------------------------- /tasks/package-opkg.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Opkg 4 | opkg: 5 | name: "{{ item.opkg | default(item.name) }}" 6 | state: "{{ item.state | default(package_state) }}" 7 | update_cache: "{{ package_update_cache }}" 8 | when: (item.opk_ignore|default('no'))|string in 'False,false,No,no' 9 | with_items: "{{ packages }}" 10 | -------------------------------------------------------------------------------- /tasks/package-pacman.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Pacman 4 | pacman: 5 | name: "{{ item.pacman | default(item.name) }}" 6 | state: "{{ item.state | default(package_state) }}" 7 | when: (item.pacman_ignore|default('no'))|string in 'False,false,No,no' 8 | with_items: "{{ packages }}" 9 | -------------------------------------------------------------------------------- /tasks/package-portage.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Portage 4 | portage: 5 | package: "{{ item.portage | default(item.name) }}" 6 | state: "{{ item.state | default(package_state) }}" 7 | sync: "{{ package_update_cache }}" 8 | when: (item.portage_ignore|default('no'))|string in 'False,false,No,no' 9 | with_items: "{{ packages }}" 10 | -------------------------------------------------------------------------------- /tasks/package-snap.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Snap 4 | snap: 5 | name: "{{ item.snap | default(item.name) }}" 6 | state: "{{ item.state | default(package_state) }}" 7 | classic: "{{ item.snap_classic | default(omit) }}" 8 | dangerous: "{{ item.snap_dangerous | default(omit) }}" 9 | channel: "{{ item.snap_channel | default(omit) }}" 10 | options: "{{ item.snap_options | default(omit) }}" 11 | when: (item.snap_ignore|default('no'))|string in 'False,false,No,no' 12 | with_items: "{{ packages }}" 13 | -------------------------------------------------------------------------------- /tasks/package-yum.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Yum 4 | yum: 5 | name: "{{ item.yum | default(item.name) }}" 6 | state: "{{ item.state | default(package_state) }}" 7 | update_cache: "{{ package_update_cache }}" 8 | when: (item.yum_ignore|default('no'))|string in 'False,false,No,no' 9 | with_items: "{{ packages }}" 10 | -------------------------------------------------------------------------------- /tasks/package-zypper.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Zypper 4 | zypper: 5 | name: "{{ item.zypper | default(item.name) }}" 6 | state: "{{ item.state | default(package_state) }}" 7 | when: (item.zypper_ignore|default('no'))|string in 'False,false,No,no' 8 | with_items: "{{ packages }}" 9 | -------------------------------------------------------------------------------- /tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | -------------------------------------------------------------------------------- /tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - role: ansible-role-package 6 | package_list: 7 | - name: htop 8 | brew: htop-osx 9 | -------------------------------------------------------------------------------- /vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # List of unique packages 4 | packages: "{{ (package_list + package_list_group + package_list_host ) | list | unique }}" 5 | --------------------------------------------------------------------------------