Обновление: Начиная с Ansible 2.0, теперь есть универсальный и абстрагированный package
модуль
Примеры использования:
Теперь, когда имя пакета одинаково для разных семейств ОС, это так просто:
---
- name: Install foo
package: name=foo state=latest
Если имя пакета в разных семействах ОС различается, вы можете обработать его с помощью файлов vars для дистрибутива или семейства ОС:
---
# roles/apache/apache.yml: Tasks entry point for 'apache' role. Called by main.yml
# Load a variable file based on the OS type, or a default if not found.
- include_vars: "{{ item }}"
with_first_found:
- "../vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version | int}}.yml"
- "../vars/{{ ansible_distribution }}.yml"
- "../vars/{{ ansible_os_family }}.yml"
- "../vars/default.yml"
when: apache_package_name is not defined or apache_service_name is not defined
- name: Install Apache
package: >
name={{ apache_package_name }}
state=latest
- name: Enable apache service
service: >
name={{ apache_service_name }}
state=started
enabled=yes
tags: packages
Затем для каждой ОС, которую вы должны обрабатывать по-разному ... создайте файл vars:
---
# roles/apache/vars/default.yml
apache_package_name: apache2
apache_service_name: apache2
---
# roles/apache/vars/RedHat.yml
apache_package_name: httpd
apache_service_name: httpd
---
# roles/apache/vars/SLES.yml
apache_package_name: apache2
apache_service_name: apache2
---
# roles/apache/vars/Debian.yml
apache_package_name: apache2
apache_service_name: apache2
---
# roles/apache/vars/Archlinux.yml
apache_package_name: apache
apache_service_name: httpd
РЕДАКТИРОВАТЬ: поскольку Майкл ДеХан (создатель Ansible) решил не абстрагировать модули менеджера пакетов, как это делает Chef ,
Если вы все еще используете более старую версию Ansible (Ansible <2.0) , к сожалению, вам придется справиться с этим во всех своих книгах и ролях. ИМХО, это толкает много ненужных повторяющихся работ на авторов книг и ролей ... но так оно и есть в настоящее время. Обратите внимание, что я не говорю, что мы должны пытаться абстрагировать менеджеров пакетов, все еще пытаясь поддерживать все их специфические опции и команды, а просто иметь простой способ установить пакет, который не зависит от менеджера пакетов. Я также не говорю, что мы все должны перейти на Smart Package Managerно это своего рода уровень абстракции установки пакетов в вашем инструменте управления конфигурацией очень полезен для упрощения кроссплатформенных сборников / поваренных книг. Проект Smart выглядит интересно, но довольно амбициозно объединить управление пакетами на всех дистрибутивах и платформах без особого принятия ... покажем, будет ли он успешным. Реальная проблема заключается в том, что имена пакетов иногда имеют тенденцию быть разными в разных дистрибутивах, поэтому нам по-прежнему приходится делать операторы case или when:
операторы для обработки различий.
Способ, которым я имел дело с этим, состоит в том, чтобы следовать этой tasks
структуре каталогов в книге или роли:
roles/foo
└── tasks
├── apt_package.yml
├── foo.yml
├── homebrew_package.yml
├── main.yml
└── yum_package.yml
И тогда есть это в моем main.yml
:
---
# foo: entry point for tasks
# Generally only include other file(s) and add tags here.
- include: foo.yml tags=foo
Это в foo.yml
(для пакета 'foo'):
---
# foo: Tasks entry point. Called by main.yml
- include: apt_package.yml
when: ansible_pkg_mgr == 'apt'
- include: yum_package.yml
when: ansible_pkg_mgr == 'yum'
- include: homebrew_package.yml
when: ansible_os_family == 'Darwin'
- name: Enable foo service
service: >
name=foo
state=started
enabled=yes
tags: packages
when: ansible_os_family != 'Darwin'
Тогда для разных менеджеров пакетов:
Апт:
---
# tasks file for installing foo on apt based distros
- name: Install foo package via apt
apt: >
name=foo{% if foo_version is defined %}={{ foo_version }}{% endif %}
state={% if foo_install_latest is defined and foo_version is not defined %}latest{% else %}present{% endif %}
tags: packages
Yum:
---
# tasks file for installing foo on yum based distros
- name: Install EPEL 6.8 repos (...because it's RedHat and foo is in EPEL for example purposes...)
yum: >
name={{ docker_yum_repo_url }}
state=present
tags: packages
when: ansible_os_family == "RedHat" and ansible_distribution_major_version|int == 6
- name: Install foo package via yum
yum: >
name=foo{% if foo_version is defined %}-{{ foo_version }}{% endif %}
state={% if foo_install_latest is defined and foo_version is not defined %}latest{% else %}present{% endif %}
tags: packages
- name: Install RedHat/yum-based distro specific stuff...
yum: >
name=some-other-custom-dependency-on-redhat
state=latest
when: ansible_os_family == "RedHat"
tags: packages
Homebrew:
---
- name: Tap homebrew foobar/foo
homebrew_tap: >
name=foobar/foo
state=present
- homebrew: >
name=foo
state=latest
Обратите внимание, что это ужасно повторяющееся и не СУХОЕ , и хотя некоторые вещи могут отличаться на разных платформах и должны быть обработаны, в общем, я думаю, что это многословно и громоздко по сравнению с шеф-поварами:
package 'foo' do
version node['foo']['version']
end
case node["platform"]
when "debian", "ubuntu"
# do debian/ubuntu things
when "redhat", "centos", "fedora"
# do redhat/centos/fedora things
end
И да, есть аргумент, что некоторые имена пакетов различаются в разных дистрибутивах. И хотя в настоящее время не хватает легко доступных данных , я бы рискнул предположить, что наиболее популярные имена пакетов распространены в дистрибутивах и могут быть установлены через абстрагированный модуль менеджера пакетов. Особые случаи должны быть обработаны в любом случае, и уже потребуют дополнительной работы, чтобы сделать вещи менее сухими . В случае сомнений, проверьте pkgs.org .