Параметрическая команда, основанная на фактах, как это сделать?
Я обновляю некоторые из моих доступных сборников для последней версии 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 не появится лучший способ взаимодействия с менеджерами пакетов. Или напиши один...