Actualización: a partir de Ansible 2.0, ahora hay un módulo genérico y abstractopackage
Ejemplos de uso:
Ahora, cuando el nombre del paquete es el mismo en diferentes familias de sistemas operativos, es tan simple como:
---
- name: Install foo
package: name=foo state=latest
Cuando el nombre del paquete difiere entre las familias del sistema operativo, puede manejarlo con distribución o archivos vars específicos de la familia del sistema operativo:
---
# 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
Luego, para cada sistema operativo que debe manejar de manera diferente ... cree un archivo 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
EDITAR: dado que Michael DeHaan (creador de Ansible) ha elegido no resumir los módulos del administrador de paquetes como lo hace Chef ,
Si todavía usa una versión anterior de Ansible (Ansible <2.0) , desafortunadamente tendrá que manejar esto en todos sus libros de jugadas y roles. En mi humilde opinión, esto empuja mucho trabajo repetitivo innecesario en el libro de jugadas y los autores de roles ... pero es como es actualmente. Tenga en cuenta que no estoy diciendo que debamos tratar de abstraer los administradores de paquetes mientras intentamos admitir todas sus opciones y comandos específicos, sino simplemente tener una manera fácil de instalar un paquete que sea independiente del administrador de paquetes. Tampoco estoy diciendo que todos deberíamos saltar al Smart Package Manager, pero que algún tipo de capa de abstracción de instalación de paquetes en su herramienta de administración de configuración es muy útil para simplificar libros de cocina / libros de cocina multiplataforma. El proyecto Smart parece interesante, pero es bastante ambicioso unificar la gestión de paquetes en distribuciones y plataformas sin mucha adopción todavía ... será interesante ver si tiene éxito. El problema real es solo que los nombres de paquetes a veces tienden a ser diferentes en las distribuciones, por lo que todavía tenemos que hacer declaraciones de casos o when:
declaraciones para manejar las diferencias.
La forma en que lo he tratado es seguir esta tasks
estructura de directorios en un libro de jugadas o rol:
roles/foo
└── tasks
├── apt_package.yml
├── foo.yml
├── homebrew_package.yml
├── main.yml
└── yum_package.yml
Y luego tener esto en mi main.yml
:
---
# foo: entry point for tasks
# Generally only include other file(s) and add tags here.
- include: foo.yml tags=foo
Esto en foo.yml
(para el paquete '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'
Luego para los diferentes gestores de paquetes:
Apto:
---
# 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
Mmm:
---
# 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
Cerveza casera:
---
- name: Tap homebrew foobar/foo
homebrew_tap: >
name=foobar/foo
state=present
- homebrew: >
name=foo
state=latest
Tenga en cuenta que esto es terriblemente repetitivo y no SECO , y aunque algunas cosas pueden ser diferentes en las diferentes plataformas y tendrán que manejarse, en general creo que esto es detallado y difícil de manejar en comparación con Chef:
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
Y sí, existe el argumento de que algunos nombres de paquetes son diferentes en las distribuciones. Y aunque actualmente hay una falta de datos fácilmente accesibles , me aventuraría a adivinar que los nombres de paquetes más populares son comunes en todas las distribuciones y podrían instalarse a través de un módulo de administrador de paquetes abstraído. Los casos especiales tendrían que manejarse de todos modos, y ya requerirían un trabajo extra para que las cosas sean menos SECAS. En caso de duda, consulte pkgs.org .