Как в ansible выбрать имена пакетов по маске?

Мне нужно получить список пакетов, имя которых начинается на dotnet.

Такая схема работает:

- debug:
    msg: "{{ ansible_facts.packages['dotnet-runtime-3.1'] }}"

А такая уже нет:

- debug:
    msg: "{{ ansible_facts.packages['dotnet*'] }}"

"{{ ansible_facts.packages | regex_findall('^dotnet.*') }}" тоже почему-то не отрабатывает.


Ответы (1 шт):

Автор решения: don Rumata

Выяснились интересные моменты. Проблема и решилась и не решилась одновременно.

package_facts

Итак, модуль package_facts показывает инфу только об установленных пакетах. Те, которые доступны - он игнорит. Это ставит крест на том, чтобы избежать использования aptitude search и aptitude versions. Тем не менее, инфу об установленных пакетах можно вытащить вот так (огромное спасибо коллеге, который умеет читать документацию в отличии от меня).

Буду показывать на firefox:

- package_facts:

- name: Get installed soft
  vars:
    my_json_query: keys(packages)[?contains(@, 'firefox')]
  set_fact:
    needing_package: "{{ ansible_facts | json_query(my_json_query) }}"
ok: [test-vm.local] => {
    "ansible_facts": {
        "needing_package": [
            "firefox", 
            "firefox-locale-ru"
        ]
    }, 
    "changed": false
}

Вывалило 2 пакета. Хотя aptitude search firefox | wc -l возвращает аж 218

Решение конкретной задачи

Debian\Ubuntu

Кроме как дёргать apt-cache я других вариантов не нашёл, поэтому:

Спрашиваем у кэша какие пакеты с маской dotnet-runtime-* нам доступны, выдёргиваем строки, содержащие слова Package: и Version:, и магией sed+tr формируем...

apt-cache show dotnet-runtime-* | grep -E -i '(Package:|Version:)' | tr '\n' ' ' | sed 's| Package|\nPackage|g' | grep -v -i deps

... здоровенный лист, который на момент написания выглядит так:

Package: dotnet-runtime-2.1 Version: 2.1.20-1
Package: dotnet-runtime-2.1 Version: 2.1.19-1
Package: dotnet-runtime-2.1 Version: 2.1.18-1
Package: dotnet-runtime-2.1 Version: 2.1.17-1
Package: dotnet-runtime-2.1 Version: 2.1.16-1
Package: dotnet-runtime-2.1 Version: 2.1.15-1
Package: dotnet-runtime-2.1 Version: 2.1.14-1
Package: dotnet-runtime-2.1 Version: 2.1.13-1
Package: dotnet-runtime-2.1 Version: 2.1.12-1
Package: dotnet-runtime-2.1 Version: 2.1.11-1
Package: dotnet-runtime-2.1 Version: 2.1.10-1
Package: dotnet-runtime-2.1 Version: 2.1.9-1
Package: dotnet-runtime-2.1 Version: 2.1.8-1
Package: dotnet-runtime-2.1 Version: 2.1.7-1
Package: dotnet-runtime-2.1 Version: 2.1.6-1
Package: dotnet-runtime-2.1 Version: 2.1.5-1
Package: dotnet-runtime-2.1 Version: 2.1.4-1
Package: dotnet-runtime-2.1 Version: 2.1.3-1
Package: dotnet-runtime-2.1 Version: 2.1.2-1
Package: dotnet-runtime-2.1 Version: 2.1.1-1
Package: dotnet-runtime-2.1 Version: 2.1.0-1
Package: dotnet-runtime-2.1.0-preview2-26406-04 Version: 2.1.0-preview2-26406-04-1
Package: dotnet-runtime-2.1.0-rc1 Version: 2.1.0-rc1-1
Package: dotnet-runtime-2.2 Version: 2.2.8-1
Package: dotnet-runtime-2.2 Version: 2.2.7-1
Package: dotnet-runtime-2.2 Version: 2.2.6-1
Package: dotnet-runtime-2.2 Version: 2.2.5-1
Package: dotnet-runtime-2.2 Version: 2.2.4-1
Package: dotnet-runtime-2.2 Version: 2.2.3-1
Package: dotnet-runtime-2.2 Version: 2.2.2-1
Package: dotnet-runtime-2.2 Version: 2.2.1-1
Package: dotnet-runtime-2.2 Version: 2.2.0-1
Package: dotnet-runtime-3.0 Version: 3.0.3-1
Package: dotnet-runtime-3.0 Version: 3.0.2-1
Package: dotnet-runtime-3.0 Version: 3.0.1-1
Package: dotnet-runtime-3.0 Version: 3.0.0-1
Package: dotnet-runtime-3.1 Version: 3.1.6-1
Package: dotnet-runtime-3.1 Version: 3.1.5-1
Package: dotnet-runtime-3.1 Version: 3.1.4-1
Package: dotnet-runtime-3.1 Version: 3.1.3-1
Package: dotnet-runtime-3.1 Version: 3.1.2-1
Package: dotnet-runtime-3.1 Version: 3.1.1-1
Package: dotnet-runtime-3.1 Version: 3.1.0-1
Package: dotnet-runtime-2.0.7 Version: 2.0.7-1
Package: dotnet-runtime-2.0.9 Version: 2.0.9-1

Дальше - просто. Дёргаем regex_search и split уже из под ansible получая вот это (по условию, нам надо найти имя пакета, в котором есть версия 3.1.6):

vars:
  dotnet_current_version: 3.1.6
- name: Find .NET versions on Debian\Ubuntu over shell
  when:
    - ansible_os_family == 'Debian'
    - ansible_pkg_mgr == 'apt'
  environment:
    LANG: C
    LC_ALL: C
  shell: apt-cache show dotnet-{{ dotnet_default_component }}-* | grep -E -i '(Package:|Version:)' | tr '\n' ' ' | sed 's| Package|\nPackage|g' | grep -v -i deps
  register: dotnet_current_version_list
  changed_when: dotnet_current_version_list.rc != 0

- name: Get current .NET version 4 install over shell
  when:
    - ansible_os_family == 'Debian'
    - ansible_pkg_mgr == 'apt'
  block:
    - set_fact:
        # https://stackoverflow.com/a/55047177/5430535
        dotnet_package_and_version_in_on_line_fact: "{{ dotnet_current_version_list.stdout | regex_search('.*' + dotnet_current_version + '.*') }}"
    - set_fact:
        dotnet_current_packagename_fact: "{{ dotnet_package_and_version_in_on_line_fact.split(' ')[1] }}"
    - set_fact:
        dotnet_current_version_fact: "{{ dotnet_package_and_version_in_on_line_fact.split(' ')[3] }}"

Выхлоп будет таким:

ok: [test-vm.local] => {
    "ansible_facts": {
        "dotnet_package_and_version_in_on_line_fact": "Package: dotnet-runtime-3.1 Version: 3.1.6-1"
    }, 
    "changed": false
}

ok: [test-vm.local] => {
    "ansible_facts": {
        "dotnet_current_packagename_fact": "dotnet-runtime-3.1"
    }, 
    "changed": false
}

ok: [test-vm.local] => {
    "ansible_facts": {
        "dotnet_current_version_fact": "3.1.6-1"
    }, 
    "changed": false
}

Т.е. установить dotnet теперь можно так:

- name: Install dotnet 4 Debian\Ubuntu
  when:
    - ansible_os_family == 'Debian'
    - ansible_pkg_mgr == 'apt'
  become: yes
  apt:
    name:
      - '{{ dotnet_current_packagename_fact }}={{ dotnet_current_version_fact }}'
    state: present
    install_recommends: yes
    force: yes

P.S. ansible 2.9.11, python version = 2.7.12 (default, Jul 21 2020, 15:19:50) [GCC 5.4.0 20160609], ubuntu 16.04.6

→ Ссылка