Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need ansible.builtin.dpkg_selections to hold package even if not already installed #83087

Open
1 task done
rclilly opened this issue Apr 18, 2024 · 7 comments · May be fixed by #83088
Open
1 task done

Need ansible.builtin.dpkg_selections to hold package even if not already installed #83087

rclilly opened this issue Apr 18, 2024 · 7 comments · May be fixed by #83088
Labels
affects_2.16 bug This issue/PR relates to a bug. has_pr This issue has an associated PR. module This issue/PR relates to a module.

Comments

@rclilly
Copy link

rclilly commented Apr 18, 2024

Summary

When I try to use ansible.builtin.dpkg_selections to put a hold on python2.7-minimal (or any python2.7 package) in Ubuntu 22.04.4 it fails. This appears to be related to dpkg_selections: Check if package exists before selection operation. I would expect dpkg_selections to be able to put holds on any package in the repos regardless of whether it is installed or not, similar to how apt-mark hold works manually. My goal is to prevent the installation of python2.7.

Issue Type

Bug Report

Component Name

dpkg_selections

Ansible Version

$ ansible --version
ansible [core 2.16.5]
  config file = /srv/home/rlilly/repos/ansible/ansible.cfg
  configured module search path = ['/home/rlillyx/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/rlillyx/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (/usr/bin/python3)
  jinja version = 3.1.3
  libyaml = True

Configuration

# if using a version older than ansible-core 2.12 you should omit the '-t all'
$ ansible-config dump --only-changed -t all
CONFIG_FILE() = /srv/home/rlilly/repos/ansible/ansible.cfg
DEFAULT_FORKS(/srv/home/rlilly/repos/ansible/ansible.cfg) = 50
DEFAULT_HOST_LIST(/srv/home/rlilly/repos/ansible/ansible.cfg) = ['/srv/home/rlilly/repos/ansible/inventory.yml']
DEFAULT_JINJA2_EXTENSIONS(/srv/home/rlilly/repos/ansible/ansible.cfg) = jinja2.ext.do
DEFAULT_PRIVATE_KEY_FILE(/srv/home/rlilly/repos/ansible/ansible.cfg) = /home/szollin/.ssh/internal.key
HOST_KEY_CHECKING(/srv/home/rlilly/repos/ansible/ansible.cfg) = False
INTERPRETER_PYTHON(/srv/home/rlilly/repos/ansible/ansible.cfg) = auto
INVENTORY_CACHE_ENABLED(/srv/home/rlilly/repos/ansible/ansible.cfg) = True
INVENTORY_CACHE_PLUGIN(/srv/home/rlilly/repos/ansible/ansible.cfg) = jsonfile
INVENTORY_CACHE_PLUGIN_CONNECTION(/srv/home/rlilly/repos/ansible/ansible.cfg) = /tmp/ansible_inventory
PAGER(env: PAGER) = less
RETRY_FILES_ENABLED(/srv/home/rlilly/repos/ansible/ansible.cfg) = False

CONNECTION:
==========
:...skipping...
CONFIG_FILE() = /srv/home/rlilly/repos/ansible/ansible.cfg
DEFAULT_FORKS(/srv/home/rlilly/repos/ansible/ansible.cfg) = 50
DEFAULT_HOST_LIST(/srv/home/rlilly/repos/ansible/ansible.cfg) = ['/srv/home/rlilly/repos/ansible/inventory.yml']
DEFAULT_JINJA2_EXTENSIONS(/srv/home/rlilly/repos/ansible/ansible.cfg) = jinja2.ext.do
DEFAULT_PRIVATE_KEY_FILE(/srv/home/rlilly/repos/ansible/ansible.cfg) = /home/szollin/.ssh/internal.key
HOST_KEY_CHECKING(/srv/home/rlilly/repos/ansible/ansible.cfg) = False
INTERPRETER_PYTHON(/srv/home/rlilly/repos/ansible/ansible.cfg) = auto
INVENTORY_CACHE_ENABLED(/srv/home/rlilly/repos/ansible/ansible.cfg) = True
INVENTORY_CACHE_PLUGIN(/srv/home/rlilly/repos/ansible/ansible.cfg) = jsonfile
INVENTORY_CACHE_PLUGIN_CONNECTION(/srv/home/rlilly/repos/ansible/ansible.cfg) = /tmp/ansible_inventory
PAGER(env: PAGER) = less
RETRY_FILES_ENABLED(/srv/home/rlilly/repos/ansible/ansible.cfg) = False

CONNECTION:
==========

paramiko_ssh:
____________
host_key_checking(/srv/home/rlilly/repos/ansible/ansible.cfg) = False
private_key_file(/srv/home/rlilly/repos/ansible/ansible.cfg) = /home/szollin/.ssh/internal.key

ssh:
___
host_key_checking(/srv/home/rlilly/repos/ansible/ansible.cfg) = False
pipelining(/srv/home/rlilly/repos/ansible/ansible.cfg) = True
private_key_file(/srv/home/rlilly/repos/ansible/ansible.cfg) = /home/szollin/.ssh/internal.key
scp_if_ssh(/srv/home/rlilly/repos/ansible/ansible.cfg) = true

OS / Environment

Both the control machine and the target are Ubuntu 22.04.4

Steps to Reproduce

Vars:

base_pkg_setup_apt_pkg_hold:
  - "python2.7-minimal"

Play:

    - name: Hold selected package(s) Ubuntu 22 and above
      ansible.builtin.dpkg_selections:
        name: "{{ item }}"
        selection: hold
      with_items: "{{ base_pkg_setup_apt_pkg_hold }}"
      when:
        - ansible_facts['distribution'] == "Ubuntu"
        - ansible_facts['distribution_major_version'] >= "22"
        - "item not in held_packages.stdout_lines"

Expected Results

I expect the package python2.7-minimal to be held even if it's not installed, similar to how apt-mark hold python2.7-minimal works.

Actual Results

TASK [base_pkg_setup : Hold selected package(s) Ubuntu 22 and above] **************************************************************************
failed: [upgrade-test-ws.ostc.intel.com] (item=python2.7-minimal) => {"ansible_loop_var": "item", "changed": false, "item": "python2.7-minimal", "msg": "Failed to find package 'python2.7-minimal' to perform selection 'hold'."}

Code of Conduct

  • I agree to follow the Ansible Code of Conduct
@ansibot ansibot added bug This issue/PR relates to a bug. needs_triage Needs a first human triage before being processed. affects_2.16 module This issue/PR relates to a module. labels Apr 18, 2024
@ansibot
Copy link
Contributor

ansibot commented Apr 18, 2024

Files identified in the description:

If these files are incorrect, please update the component name section of the description or use the component bot command.

@bcoca bcoca removed the needs_triage Needs a first human triage before being processed. label Apr 18, 2024
@bcoca
Copy link
Member

bcoca commented Apr 18, 2024

I'm not sure this is true, in my tests dpkg --set-selections fails to hold a package if the name is for an unknown package. I think you are confusing an 'existing' package vs an installed one.

https://wiki.debian.org/Teams/Dpkg/FAQ#set-selections

@rclilly
Copy link
Author

rclilly commented Apr 18, 2024

@bcoca Thank you for your quick reply! I haven't tried using dpkg --set-selections, only apt-mark hold, which works. If this module uses dpkg, and it can't do this task, then is there a way to accomplish this with the apt module?

@bcoca
Copy link
Member

bcoca commented Apr 18, 2024

I might have been a bit premature since my debian based distros are pretty updated and there is no Python2 available, so its 'non existant', but i kept testing other cases, of which i've found 4:

  • package exists, is in dpkg cache and selections are available, action works fine, matches dpkg
  • package does not exist anywhere, action works fine, matches dpkg
  • package exists in repository, but dpkg cache was not updated, so action reacts as if it didnt exist, i think this is still correct and matches dpkg
  • package exists in repo and dpkg cache, but was never in selections, in this case action incorrectly treats as non existant but dpkg itself does work.

I'll push a fix for this last case.

@bcoca bcoca linked a pull request Apr 18, 2024 that will close this issue
@sivel
Copy link
Member

sivel commented Apr 18, 2024

This would also be fairly trivial to implement with just running apt-mark:

- name: Get list of packages on hold
  command: apt-mark showhold
  register: apt_mark_hold
  changed_when: false

- name: Set hold for python2.7-minimal
  command: apt-mark hold python2.7-minimal
  when: '"python2.7-minimal" not in apt_mark_hold.stdout'

@ansibot ansibot added the has_pr This issue has an associated PR. label Apr 18, 2024
@alexcernat
Copy link

alexcernat commented May 1, 2024

Same problem with the elasticsearch ansible role (yes, I know, old one, but afaik there isn't another better, so...):

- name: Debian - unhold elasticsearch version
  become: yes
  dpkg_selections:
    name: "{{ es_package_name }}"
    selection: "install"
  when: not es_version_lock or (installed_es_version.stdout and installed_es_version.stdout != es_version)

this fails too with "Failed to find package 'elasticsearch' to perform selection 'install'." when no elasticsearch package is installed
(debian 12 / ansible-core 2.16.5-1ppa)

because initial install (some years ago) was flawless and since then was only "checked", probably it's an old "bug/feature" in ansible, glad that at least one person had the same issue.

I agree that it's kind of unusual to hold/unhold a non-existent package, but it worked (not sure that the package name should be a t least a debian package or any string would match ok).

@bcoca
Copy link
Member

bcoca commented May 1, 2024

i've been testing this and sadly i get different results on different versions of Debian and Debian derivatives. Some allow any package name to be held w/o error, so it won't catch misspellings, other versions ONLY allow packages they recognize so they need to be in the local cache. I'm not sure we should bypass this behavior as it opens up many doors to user error and complexity in tracking the different underlying responses from the tool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
affects_2.16 bug This issue/PR relates to a bug. has_pr This issue has an associated PR. module This issue/PR relates to a module.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants