¿Cómo unificar las tareas de instalación de paquetes en ansible?

¿Cómo unificar las tareas de instalación de paquetes en ansible?

estoy empezando conansibley lo usará, entre otros, para instalar paquetes en varias distribuciones de Linux.

Veo en los documentos que los comandos yumy aptestán separados; cuál sería la forma más fácil de unificarlos y usar algo como esto:

- name: install the latest version of Apache
  unified_install: name=httpd state=latest

en lugar de

- name: install the latest version of Apache on CentOS
  yum: name=httpd state=latest
  when: ansible_os_family == "RedHat"

- name: install the latest version of Apache on Debian
  apt: pkg=httpd state=latest 
  when: ansible_os_family == "Debian"

Entiendo que los dos administradores de paquetes son diferentes, pero aún tienen un conjunto de usos básicos comunes. Otros orquestadores (sal por ejemplo) tienen un único comando de instalación.

Respuesta1

Actualización: a partir de Ansible 2.0, ahora hay una versión genérica y abstractapackagemódulo

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 de sistemas operativos, puede manejarlo con archivos vars específicos de la familia de sistemas operativos o de distribución:

---
# 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 debas manejar de manera diferente... crea 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: Desde Michael DeHaan (creador de Ansible)ha optado por no abstraer los módulos del administrador de paquetescomoCocinerohace,

Si todavía utiliza una versión anterior de Ansible (Ansible < 2.0), desafortunadamente tendrás que encargarte de hacer esto entodode sus manuales y roles. En mi humilde opiniónesto impone una gran cantidad de trabajo repetitivo innecesario a los autores de libros de jugadas y roles... pero así es actualmente. Tenga en cuenta que no estoy diciendo que debamos intentar abstraer los administradores de paquetes y al mismo tiempo intentar 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 debamos lanzarnos alAdministrador de paquetes inteligentevagon, 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 los libros de estrategias y recetas multiplataforma. El proyecto Smart parece interesante, pero es bastante ambicioso para unificar la gestión de paquetes entre distribuciones y plataformas sin mucha adopción todavía... será interesante ver si tiene éxito. El verdadero problema es que los nombres de los paquetes a veces tienden a ser diferentes entre 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 estado abordando es seguir esta tasksestructura de directorio en un manual o rol:

roles/foo
└── tasks
    ├── apt_package.yml
    ├── foo.yml
    ├── homebrew_package.yml
    ├── main.yml
    └── yum_package.yml

Y luego tengo 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 administradores 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

Mmmm:

---
# 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

Elaboración 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 noSECO, y aunque algunas cosaspodríaser diferente en las diferentes plataformas y tendrá que ser manejado, en general creo que esto es detallado y difícil de manejar en comparación con Chef's:

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 quealgunoLos nombres de los paquetes son diferentes entre las distribuciones. Y aunque actualmente existe unafalta de datos fácilmente accesibles, me atrevería a suponer quemayoríaLos nombres de paquetes populares son comunes en todas las distribuciones y se pueden instalar a través de un módulo de administrador de paquetes abstracto. Los casos especiales tendrían que ser manejados de todos modos, y ya requerirían trabajo adicional para hacer las cosas menos SECAS. En caso de duda, verifiquepkgs.org.

Respuesta2

Puede abstraer los administradores de paquetes a través de hechos

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

Todo lo que necesitas es algo de lógica que ansible_pkg_mgrestablezca apto yumetc.

ansibleTambién estamos trabajando para hacer lo que quieras en un módulo futuro..

Respuesta3

De Ansible 2.0 existe el nuevo Package-modul.

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

Luego puedes usarlo como tu propuesta:

- name: install the latest version of Apache
  package: name=httpd state=latest

Aún debes considerar las diferencias de nombres.

Respuesta4

No desea hacer eso porque ciertos nombres de paquetes difieren entre distribuciones. Por ejemplo, en las distribuciones relacionadas con RHEL, el popular paquete de servidor web se denomina httpd, mientras que en las distribuciones relacionadas con Debian se denomina apache2. Lo mismo ocurre con una lista enorme de otros sistemas y bibliotecas de soporte.

Puede haber un conjunto de parámetros básicos comunes, pero también hay una serie de parámetros más avanzados que son diferentes entre los administradores de paquetes. Y no querrás estar en una situación ambigua en la que para algunos comandos uses una sintaxis y para otros comandos uses otra sintaxis.

información relacionada