Ejecute múltiples tareas de Ansible con la misma lista de elementos


13

Estoy usando un libro de jugadas ansible para configurar Apache para una lista de sitios. El libro de jugadas debe copiar la plantilla de configuración de host virtual para cada sitio en su lugar y luego habilitar cada sitio usando a2ensite:

- name: Install apache site conf
  template: src=apache-sites-{{item}}-conf.j2 dest=/etc/apache2/sites-available/{{item}}.conf mode=0644
  with_items:
  - sitea
  - siteb
  - sitec
  - sited
- name: Enable site apache conf
  command: a2ensite {{item}}
  args:
    creates: /etc/apache2/sites-enabled/{{item}}.conf
  with_items:
  - sitea
  - siteb
  - sitec
  - sited

No me gusta tener que repetir la misma lista para cada tarea. ¿Cómo configuro el libro de jugadas para ejecutar ambas tareas con la misma lista de elementos?

Respuestas:


15

Hacer un archivo de tareas por separado make_site.yml:

---
- name: Install apache site conf
  template:
    src: apache-sites-{{ site }}-conf.j2
    dest: /etc/apache2/sites-available/{{ site }}.conf
    mode: 0644

- name: Enable site apache conf
  command: a2ensite {{ site }}
  args:
    creates: /etc/apache2/sites-enabled/{{ site }}.conf

Y en tu libro de jugadas:

- include_tasks: make_site.yml
  with_items:
    - sitea
    - siteb
    - sitec
    - sited
  loop_control:
    loop_var: site

Esperaba encontrar una solución sin tener que crear un archivo separado. Algo así como un loopen una blockcuadra. Eso parece ser solicitado, pero rechazado a través de Ansible GH número 13262 . :-(
gertvdijk

2

Encontré una solución usando archivos glob. Como tengo un archivo de configuración para cada sitio, simplemente puedo usar la lista de esos archivos para iterar sobre todos ellos. De esa manera, no tengo la lista de sitios en mi archivo de tareas ni una sola vez, y mucho menos dos veces. Todo lo que necesito hacer para agregar un sitio es agregar un archivo.

Para facilitar un poco las cosas, creé un directorio para las plantillas:

  • roles/webserver/templates/apache-sites/sitea.conf.j2
  • roles/webserver/templates/apache-sites/siteb.conf.j2
  • roles/webserver/templates/apache-sites/sitec.conf.j2
  • roles/webserver/templates/apache-sites/sited.conf.j2

Luego en roles/webserver/tasks/main.ymlpuedo usar esa lista de archivos y algunas expresiones regulares:

---
- block:
  - name: Install apache site conf
    template: src={{item}} dest=/etc/apache2/sites-available/{{item|regex_replace(".*/","")|regex_replace("\.j2$","")}} mode=0644
    with_fileglob:
    - "roles/webserver/templates/apache-sites/*"
  - name: Enable site apache conf
    command: a2ensite {{item|regex_replace(".*/","")|regex_replace("\.conf\.j2$","")}}
    args:
      creates: /etc/apache2/sites-enabled/{{item|regex_replace(".*/","")|regex_replace("\.j2$","")}}
    with_fileglob:
    - "roles/webserver/templates/apache-sites/*"
  become: yes

Esta técnica incluso podría usarse con archivos ficticios vacíos para crear una lista para otras aplicaciones.


1

Konstantin dio una buena respuesta; Aquí hay un sabor adicional.

Normalmente definiré las listas como variables y simplemente escribiré dos bucles separados sobre la misma variable:

┌─[jamesph@geror] - [~/temp] - [Sat Jan 13, 10:06]
└─[$]> cat loops-1.yml
- hosts: localhost
  gather_facts: no
  vars:
    menu:
      - Egg and Spam
      - Spam, bacon, sausage and Spam
      - Spam, Spam, Spam, Spam, Spam, Spam, baked beans, Spam, Spam, Spam and Spam
  tasks:
    - debug:
        msg: "We have {{ item }}"
      with_items: "{{ menu }}"
    - debug:
        msg: "I love {{ item }}!"
      with_items: "{{ menu }}"
┌─[jamesph@geror] - [~/temp] - [Sat Jan 13, 10:06]
└─[$]> ansible-playbook loops-1.yml
 [WARNING]: Unable to parse /etc/ansible/hosts as an inventory source

 [WARNING]: No inventory was parsed, only implicit localhost is available

 [WARNING]: Could not match supplied host pattern, ignoring: all

 [WARNING]: provided hosts list is empty, only localhost is available


PLAY [localhost] **********************************************************************************************************************

TASK [debug] **************************************************************************************************************************
ok: [localhost] => (item=Egg and Spam) => {
    "changed": false,
    "item": "Egg and Spam",
    "msg": "We have Egg and Spam"
}
ok: [localhost] => (item=Spam, bacon, sausage and Spam) => {
    "changed": false,
    "item": "Spam, bacon, sausage and Spam",
    "msg": "We have Spam, bacon, sausage and Spam"
}
ok: [localhost] => (item=Spam, Spam, Spam, Spam, Spam, Spam, baked beans, Spam, Spam, Spam and Spam) => {
    "changed": false,
    "item": "Spam, Spam, Spam, Spam, Spam, Spam, baked beans, Spam, Spam, Spam and Spam",
    "msg": "We have Spam, Spam, Spam, Spam, Spam, Spam, baked beans, Spam, Spam, Spam and Spam"
}

TASK [debug] **************************************************************************************************************************
ok: [localhost] => (item=Egg and Spam) => {
    "changed": false,
    "item": "Egg and Spam",
    "msg": "I love Egg and Spam!"
}
ok: [localhost] => (item=Spam, bacon, sausage and Spam) => {
    "changed": false,
    "item": "Spam, bacon, sausage and Spam",
    "msg": "I love Spam, bacon, sausage and Spam!"
}
ok: [localhost] => (item=Spam, Spam, Spam, Spam, Spam, Spam, baked beans, Spam, Spam, Spam and Spam) => {
    "changed": false,
    "item": "Spam, Spam, Spam, Spam, Spam, Spam, baked beans, Spam, Spam, Spam and Spam",
    "msg": "I love Spam, Spam, Spam, Spam, Spam, Spam, baked beans, Spam, Spam, Spam and Spam!"
}

PLAY RECAP ****************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0

Esto funciona muy bien con precedencia variable , por ejemplo, definiendo diferentes conjuntos de servidores por entorno. También funciona cuando necesita realizar varias otras tareas no en bucle entre los dos bucles.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.