Exécuter plusieurs tâches Ansible avec la même liste d'éléments

13

J'utilise un playbook ansible pour configurer Apache pour une liste de sites. Le playbook doit copier le modèle de configuration d'hôte virtuel pour chaque site en place, puis activer chaque site en utilisant 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

Je n'aime pas avoir à répéter la même liste pour chaque tâche. Comment configurer le playbook pour exécuter les deux tâches avec la même liste d'éléments?

Stephen Ostermiller
la source

Réponses:

15

Créez un fichier de tâches distinct 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

Et dans votre playbook:

- include_tasks: make_site.yml
  with_items:
    - sitea
    - siteb
    - sitec
    - sited
  loop_control:
    loop_var: site
Konstantin Suvorov
la source
J'espérais trouver une solution sans avoir à créer un fichier séparé. Quelque chose comme un loopsur un blockbloc. Cela semble être demandé, mais rejeté via Ansible GH numéro 13262 . :-(
gertvdijk
2

J'ai trouvé une solution en utilisant des globes de fichiers. Étant donné que j'ai un fichier de configuration pour chaque site, je peux simplement utiliser la liste de ces fichiers pour les parcourir tous. De cette façon, je n'ai même pas une fois la liste des sites dans mon fichier de tâches, et encore moins deux fois. Tout ce que je dois faire pour ajouter un site est d'ajouter un fichier.

Pour rendre les choses un peu plus faciles, j'ai créé un répertoire pour les modèles:

  • 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

Ensuite, roles/webserver/tasks/main.ymlje peux utiliser cette liste de fichiers et quelques expressions régulières:

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

Cette technique pourrait même être utilisée avec des fichiers factices vides pour créer une liste pour d'autres applications.

Stephen Ostermiller
la source
1

Konstantin a donné une bonne réponse; en voici une saveur supplémentaire.

Je définirai généralement les listes comme des variables et j'écrirai simplement deux boucles distinctes sur la même 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

Cela fonctionne bien avec la priorité des variables , par exemple en définissant différents ensembles de serveurs par environnement. Il fonctionne également lorsque vous devez effectuer diverses autres tâches non en boucle entre les deux boucles.

Boycott SE pour Monica Cellio
la source