Параметрическая команда, основанная на фактах, как это сделать?

Я обновляю некоторые из моих доступных сборников для последней версии Fedora, которая теперь использует dnf по умолчанию.

Поскольку большинство моих сборников игр должно работать и на CentOS, я бы хотел, чтобы мой скрипт запускал ANSI yum при запуске на компьютере CentOS, и запустить dnf команда (новая в Ansible 1.9) при работе с Fedora, но с использованием остальной роли как есть.

Другими словами, я хотел бы написать одну операцию, которая может разумно выбрать правильную команду (что-то похожее):

- name: Install zsh
  sudo: yes
  yum|dnf: name=zsh state=latest

... вместо того, чтобы вставлять одну и ту же команду дважды, заменяя yum с dnf в одном из двух, а затем реализует некоторую логику, которая говорит, какую из двух разных ролей выполнять:

- name: Install zsh (yum version)
  sudo: yes
  yum: name=zsh state=latest

- name: Install zsh (dnf version)
  sudo: yes
  dnf: name=zsh state=latest

Прежде чем кто-то бросается на это: я знаю, что yum в псевдониме dnf на последней Fedora, и что я мог просто оставить Playbook как есть... Мой вопрос не о написании CentOS/Fedora-совместимых Playbook, мой вопрос о выборе другой команды для тех же параметров в зависимости от целевой среды

2 ответа

Решение

В Ansible 2 теперь есть стандартный менеджер пакетов:

http://docs.ansible.com/ansible/package_module.html

Для более старых версий вы можете связать менеджеры пакетов через факты

- name: Install packages
  with_items: package_list
  action: "{{ ansible_pkg_mgr }} state=installed name={{ item }}"

Теперь все, что вам нужно, это некоторая логика, которая устанавливает ansible_pkg_mgr в apt или же yum и т. д. и все when логика уходит.

Похоже, Ansible также работает над тем, что вы хотите в будущем модуле.

Насколько я могу судить, это одна из самых грязных частей Ansible. Я всегда думал, что у него должен быть способ выяснить, какой менеджер пакетов используется сам по себе, без необходимости указывать его.

Между тем, у меня много ролей с задачами, которые выглядят так:

- name: Update OpenSSH on CentOS
  yum: name=openssh state=latest enablerepo=cr
  when: ansible_distribution == 'CentOS' and ansible_distribution_major_version|int == 7
  notify: restart sshd

- name: Update OpenSSH on RHEL
  yum: name=openssh state=latest
  when: ansible_distribution == 'RedHat' and ansible_distribution_major_version|int == 7
  notify: restart sshd

- name: Update OpenSSH on Fedora
  yum: name=openssh state=latest
  when: ansible_distribution == 'Fedora' andansible_distribution_major_version|int <= 21
  notify: restart sshd

- name: Update OpenSSH on Fedora
  dnf: name=openssh state=latest
  when: ansible_distribution == 'Fedora' andansible_distribution_major_version|int >= 22
  notify: restart sshd

- name: Update OpenSSH on Debian/Ubuntu
  apt: name=openssh-server state=latest
  when: ansible_os_family == 'Debian'
  notify: restart ssh

Это становится немного громоздким. Тем не менее, у него есть свои преимущества. Если вы внимательно осмотрите это, вы заметите, что версия CentOS отличается; он включает хранилище при установке пакета.

Конечно, есть причина для этого. В разных системах у вас могут даже быть разные имена пакетов, так что вам может в конечном итоге придется решать разные задачи для них. Но это то, что вы можете вставить в специфическую для ОС переменную, а затем сделать что-то вроде:

- include_vars: common_os_{{ansible_distribution}}_{{ansible_distribution_major_version}}.yml

- name: Install minimum system administration packages
  yum: name={{item}} state=present
  with_items: common_packages_admin
  when: ansible_os_family == 'RedHat'

- name: Install minimum system administration packages
  apt: name={{item}} state=present
  with_items: common_packages_admin
  when: ansible_os_family == 'Debian'

Но продлить это для dnf потребует кучу дополнительных when: логика, которая много работает для абсолютно нулевого усиления, так как dnf-yum-совместимость позаботится об этом. Вот место, где этот гипотетический модуль "автоматически выяснить, какой менеджер пакетов использовать" будет полезен.

Но даже если у вас есть один, вам все равно иногда придется использовать отдельные менеджеры пакетов, потому что некоторые из них имеют... свои особенности.

- name: Install salt-minion
  yum: name=salt-minion state=latest
  when: ansible_os_family == 'RedHat'

- name: Install salt-minion
  apt: name=salt-minion state=latest update_cache=yes
  when: ansible_os_family == 'Debian'

Итак, лучший совет, который я могу вам дать: подождите, пока у Ansible не появится лучший способ взаимодействия с менеджерами пакетов. Или напиши один...

Другие вопросы по тегам