Ansible Playbook is it necessary to specify the exact version of the package to set on hold by dist-upgrade?

Viewed 1370

Ansible 2: Is it possible in Ansible Playbook to exclude a package that normally would be upgraded during dist-upgrade by using just the name of the package instead of the exact version?

---
- hosts: localhost
  become: yes
  tasks: 

  - name: disable upgrade of Java
    dpkg_selections:
      name: openjdk-8-jre
      selection: hold

I'd like to specify just openjdk instead of openjkd-8-jre because no openjdk should be installed no matter what version of openjdk is available to upgrade to (have different servers with different ubuntu os).

1 Answers

Preliminary note (extending my comment)

openjdk-8-jre is the package name. There is actually one different package for each major version of java. They can be installed alone or all together and managed through alternatives. But e.g. openjdk-11-jre-headless will never replace openjdk-8-jre-headless.

So it is quite unusual to hold such packages as your are cutting yourself off the latest bug and security fixes that should not impact the application using it (e.g. a java-8 application should run on any minor version of openjdk-8).

That being said, if you still want to do it...

Solution with package_facts.

This is basically doing exactly what you were trying except it will only mark as hold existing packages on the machine (which is probably better anyway).

Ansible has a package_facts module which will return the existing installed package in the packages variable.

The idea: get those package name, select only the ones starting with a given name and feed that list to dpkg_selections to mark them as hold. The below playbook was tested successfully against my unbuntu 18.04 home machine.

- name: Disable package upgrade based on partial name
  hosts: localhost
  gather_facts: false
  become: true

  vars:
    partial_hold_name: openjdk
    partial_hold_regexp: "^{{ partial_hold_name }}.*"
    hold_package_list: "{{ packages | dict2items | map(attribute='key') | select('match', partial_hold_regexp) | list }}"

  tasks:
    - name: Gather package facts
      package_facts:

    - name: dselect all openjdk packages if they exists
      dpkg_selections:
        name: "{{ item }}"
        selection: hold
      loop: "{{ hold_package_list }}"

Which gives (first run with openjdk-11 and openjdk-8 installed in parallel and marked as "install")

$ ansible-playbook test.yml 

PLAY [Disable package upgrade based on partial name] ***********************************************************************************************************************************************************************************

TASK [Gather package facts] ************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [dselect all openjdk packages if they exists] *************************************************************************************************************************************************************************************
changed: [localhost] => (item=openjdk-11-jre-headless)
changed: [localhost] => (item=openjdk-8-jdk-headless)
changed: [localhost] => (item=openjdk-8-jre-headless)

PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
Related