Wykonuj wiele zadań Ansible przy użyciu tej samej listy elementów

13

Korzystam z odpowiedniego podręcznika, aby skonfigurować Apache dla listy witryn. Poradnik musi skopiować szablon konfiguracji hosta wirtualnego dla każdej witryny na miejsce, a następnie włączyć każdą witrynę za pomocą 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

Nie lubię powtarzać tej samej listy dla każdego zadania. Jak skonfigurować podręcznik, aby wykonywać oba zadania z tą samą listą przedmiotów?

Stephen Ostermiller
źródło

Odpowiedzi:

15

Utwórz osobny plik zadań 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

A w twoim poradniku:

- include_tasks: make_site.yml
  with_items:
    - sitea
    - siteb
    - sitec
    - sited
  loop_control:
    loop_var: site
Konstantin Suworow
źródło
Miałem nadzieję znaleźć rozwiązanie bez konieczności tworzenia osobnego pliku. Coś jak loopna blockbloku. Wydaje się, że jest to wymagane, ale odrzucone przez numer 13262 Ansible GH . :-(
gertvdijk
2

Znalazłem rozwiązanie za pomocą globów plików. Ponieważ mam plik konfiguracyjny dla każdej witryny, mogę po prostu użyć listy tych plików, aby wykonać iterację po wszystkich. W ten sposób nie mam listy witryn w moim pliku zadań ani razu, ani tym bardziej dwukrotnie. Wszystko, co muszę zrobić, aby dodać stronę, to dodać plik.

Aby trochę ułatwić, stworzyłem katalog szablonów:

  • 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

Następnie roles/webserver/tasks/main.ymlmogę użyć tej listy plików i niektórych wyrażeń regularnych:

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

Tę technikę można nawet zastosować przy pustych plikach zastępczych, aby utworzyć listę dla innych aplikacji.

Stephen Ostermiller
źródło
1

Konstantin udzielił dobrej odpowiedzi; tutaj jest dodatkowy smak.

Zwykle będę definiować listy jako zmienne i po prostu napiszę dwie osobne pętle nad tą samą zmienną:

┌─[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

Działa to dobrze ze zmiennym priorytetem , na przykład poprzez definiowanie różnych zestawów serwerów dla środowiska. Działa również, gdy trzeba wykonać różne inne niepętlowe zadania pomiędzy dwiema pętlami.

Bojkot SE dla Moniki Cellio
źródło