5

I have a few tens of hosts that are a mix of CentOS 6 and 7. I recently started using Ansible to help manage them, but I'm still very much a newbie.

Like everybody, I have a periodic need to update packages on those machines, especially for security reasons. However, I don't want to update all packages on them, just specific ones -- which may vary from machine to machine, depending on its roles. I have used Ansible's yum command, with state=latest, and a list of specific packages, to update those hosts in the past, but only today did I notice that when running that against a host, if one of the listed packages is not installed on that machine it will then be installed.

What I need is a way to supply Ansible with a list of packages, and then for each host it will act upon: - if the package is present, update it to the latest version; - if the package is not present, do nothing.

Is there a practical way to do that?

2
  • You will have to make a list of packages, and for each package check first if it's installed e.g. with rpm -q package (which exits with false if not), register that result in a variable and then use that to determine to perform the yum command or not (with a when: clause). I can't spell it out as I'm not that good either :)
    – wurtel
    May 19, 2016 at 14:57
  • Thanks, @wurtel! Will try to make that work. If somebody else could provide a simple example of that at work, that'd still be much appreciated.
    – Iba Popo
    May 20, 2016 at 13:15

3 Answers 3

4

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.

3

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) }}
5
  • Thank you, knowhy. But, if I understood correctly, I would need to know beforehand exactly which packages I want updated on which host or group of hosts, right? What I need is for this to be done dynamically -- one list of packages is provided and, for each host, only those packages in the list that are present in that host should be actioned.
    – Iba Popo
    Jun 3, 2016 at 14:17
  • Why do you want to update only subset of the packages installed? Jun 3, 2016 at 17:14
  • Stability. We don't have the means to test all the updates, and we have a sensitive environment, so we only install the more important security ones.
    – Iba Popo
    Jun 6, 2016 at 13:05
  • I still don't think it is a good idea, but I have added an attempted to do that. I guess rpm might update packages as dependencies even when they are not set. But not sure.I have no RHEL distro at hand so you are welcome to correct me if made mistakes. Jun 6, 2016 at 17:53
  • See stackoverflow.com/a/41551876/2897386 for a similar solution, but without relying on the rpm shell command.
    – DustWolf
    Aug 4, 2020 at 7:48
2

This all seems a little complicated for a yum update?

why not just use a local command for this until Ansible gets around to allowing this option?

A simple playbook like this would do it.

---
- hosts: dev-systems
  remote_user: admin
  become: yes
  tasks:
    - name: Update installed packages.
      command: /usr/bin/yum update -y {{item}}
      with_items:
          - package1
          - package2
          - package3
          - package-etc

I just tested this and using two packages. one that needed an update and one that was not installed. End result was an updated package with out the other being installed.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .