Since ansible 2.5 there is an option update_only for yum (and since ansible 2.1 only_upgrade for apt) which installs latest version only if it was already installed on the system. So, instead of collecting a list of packages in another task, you can add the option.
- name: Update subset of packages.
yum:
name: "{{ item }}"
state: latest
update_only: yes
with_items:
- package1
- package2
I am myself was searching the web and this article was found before I got to the official documentation. So I think it worse to be added here.
Answer from Dennis M. on serverfault.comSince ansible 2.5 there is an option update_only for yum (and since ansible 2.1 only_upgrade for apt) which installs latest version only if it was already installed on the system. So, instead of collecting a list of packages in another task, you can add the option.
- name: Update subset of packages.
yum:
name: "{{ item }}"
state: latest
update_only: yes
with_items:
- package1
- package2
I am myself was searching the web and this article was found before I got to the official documentation. So I think it worse to be added here.
If you only want to update a subset of the packages with available updates you might want to try @wurtel s attempt. You will need to register the installed packages like this:
- name: Get installed packages.
command: rpm -qa --qf "%{NAME}\n"
register: installed_packages
Then you can define a set theory filter and update all the packages defined in the list of packages which are allowed to update packages_to_update.
- name: Update subset of packages.
yum:
name: "{{ item }}"
state: latest
with_items:
- {{ installed_packages | intersect(packages_to_update) }}
I don't think the yum module would help in this case. It currently has 3 states: absent, present, and latest. Since it sounds like you don't want to actually install or remove the package (at least at this point) then you would need to do this in two manual steps. The first task would check to see if the package exists, then the second task would invoke a command based on the output of the first command.
If you use "rpm -q" to check if a package exists then the output would look like this for a package that exists:
# rpm -q httpd
httpd-2.2.15-15.el6.centos.1.x86_64
and like this if the package doesn't exist:
# rpm -q httpdfoo
package httpdfoo is not installed
So your ansible tasks would look something like this:
- name: Check if foo.rpm is installed
command: rpm -q foo.rpm
register: rpm_check
- name: Execute script if foo.rpm is not installed
command: somescript
when: rpm_check.stdout.find('is not installed') != -1
The rpm command will also exit with a 0 if the package exists, or a 1 if the package isn't found, so another possibility is to use:
when: rpm_check.rc == 1
Based on the Bruce P answer above, a similar approach for apt/deb files is
- name: Check if foo is installed
command: dpkg-query -l foo
register: deb_check
- name: Execute script if foo is not installed
command: somescript
when: deb_check.stdout.find('no packages found') != -1
yum module refuses to install package, saying it's already installed
yum state=latest doesn't install if not already installed
php - Unable to install package in Ansible - Stack Overflow
Ansible yum module to install a list of packages AND remove any other packages - Stack Overflow
Building up on @gary lopez answer to add security and performance.
First you will need to get an actual list of all packages you want to see installed on your final machine, including the default ones that come with the system. I assume that list will be in var yum_rpm
Once you have that, the next step is to get the list of currently installed packages on the machine. To create an actual list we can reuse:
- name: Get installed packages
yum:
list: installed
register: __yum_packages
- name: Make installed packages a list of names
set_fact:
installed_packages: "{{ __yum_packages.results | map(attribute='name') | list }}"
From there, adding and removing is just a matter of making a difference on lists. The goal here is to avoid looping on the yum module package by package (because it is damn slow and listed as a bad practice on the module documentation page) and to make the install and remove operations in one go.
- name: align packages on system to expected
yum:
name: "{{ item.packages }}"
state: "{{ item.state }}"
loop:
- packages: "{{ yum_rpm | difference(installed_packages) }}"
state: present
- packages: "{{ installed_packages | difference(yum_rpm) }}"
state: absent
when: item.packages | length > 0
In the first task you need to use state: present. You could try this
vars:
- yum_rpm:
- tcpdump
- tmux
- psacct
tasks:
- name: "Install all package in our list"
yum:
name: "{{ yum_rpm }}"
state: present
update_cache: no
- name: Get packages installed
yum:
list: installed
register: __yum_packages
- name: "Remove any other unexpected package already installed"
yum:
name: "{{ item.name }}"
state: absent
with_items: "{{ __yum_packages.results }}"
But I recommend you validate packages to uninstall because you could uninstall some packages required for your OS.
Ansible is part of the Extra Packages for Enterprise Linux (EPEL) repository so you need to install epel-release package first
$ sudo yum install epel-release
The repo should now be visible in the repo list
$ sudo yum repolist
So now you can go ahead and install ansible
$ sudo yum install ansible
Before RHEL 7.x, the installtion needed to be done manually. Open install epel-release package and download the newest version of epel-release for EL5 or follow the commands below
$ wget https://archives.fedoraproject.org/pub/archive/epel/5/x86_64/epel-release-5-4.noarch.rpm
$ sudo rpm –ivh epel-release-latest-5.noarch.rpm
$ sudo yum repolist
$ sudo yum install ansible
In the installation manual for ansible, this is referred to as configure EPEL
Hope this helps :)
Response to second update
When installing manually you may also need to expire your cache and recreate the the local repository database before you can install software from EPEL. That can be done with the following
$ yum clean expire-cache
$ yum createrepo
EPEL is required for this.
Follow these steps for installing Ansible for Red Hat Enterprise Linux Server release 7 Based on the redhat version, follow Enabline EPEL
1. yum -y update
2. yum install wget
3. wget http://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-11.noarch.rpm
4. rpm -ivh epel-release-7-11.noarch.rpm
5. yum repolist
6. yum install ansible
Short Generic Answer:
You should be able to just use wildcards *.
So just:
- name: Install package
yum:
name: package-2.6*
state: latest
Long Case Specific Answer:
I created a test server in AWS for your specific case and found that wildcards do indeed work (EC2 instance running CentOS 7, installing `mongodb-org-server-3.4.0*).
You do need to make sure you have properly configured the mongo repository first, but you said in the comments that you are able to download the package if you provide the full version number, which is unusual. Anyway, this is the minimal playbook I made and ran:
play.yml:
- hosts: all
remote_user: centos
tasks:
- name: Add MongoDB repo for CentOS
become: true
copy:
src: ./files/mongodb-org-3.4.repo
dest: /etc/yum.repos.d/mongodb-org-3.4.repo
- name: Install mongodb
become: true
yum:
name: mongodb-org-server-3.4.0*
state: latest # Works with 'present' too, but won't update versions
This playbook copies a local file for the repo config which looks like this (path is relative to the play.yml file):
files/mongod-org-3.4.repo:
[mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc
Not sure if applicable for your Yum package. But for Java Open JDK installations where both java-1.7.0 and java-1.8.0 packages are available for installation from my configured yum repos.
This will ensure the 1.7.x version is at the latest version, without ever installing 1.8.x.
- name: Install latest 1.7.x jdk
yum:
name: java-1.7.0-openjdk.x86_64
state: latest
Actual version installed from the above is:
$ rpm -q java-1.7.0-openjdk.x86_64
java-1.7.0-openjdk-1.7.0.121-2.6.8.1.el6_8.x86_64
In the case of MongoDB the package name is the same for the 2.x version and the 3.x version.
But there is one Yum repo file for the 2.x version and another for the 3.x version. https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat/
So to ensure you get the latest 2.x version without ever moving to 3.x add the 2.x repo file to your target hosts and use the disable and enablerepo parameters in your ansible task for the install/update operation.
- name: Ensure latest 2.x mongodb version is installed
yum:
name: mongodb-org
disablerepo: "*"
enablerepo: mongodb-org-2.6
state: latest
Note: using disablerepo: "*" as mongodb packages also exist in other repos such as epel.