Czy procedury obsługi Ansible są zdefiniowane w rolach uruchamianych po całym podręczniku lub roli?

13

Korzystam z Ansible 2.0 i mógłbym to po prostu uruchomić, ale może mnie również skłonić do uwierzenia w coś, co nie jest prawdą w moich testach empirycznych i nie mogę znaleźć żadnej dokumentacji, która powiedziałaby mi, kiedy należy obsługiwać programy obsługi.

Jeśli programy obsługi nie zostaną uruchomione po zakończeniu ich zadań, to moja zagadka. Mam podręcznik z 5 rolami. Na końcu chcę dodać rolę 6, która musi zakończyć obsługę czwartej roli przed jej uruchomieniem.

Czy jest jakiś sposób na uruchomienie Ansible, aby polegać na zakończeniu procedury obsługi (tj. Roli całkowicie ukończonej) przed zrobieniem czegoś innego, czy też źle korzystam z procedur obsługi?

Peter Turner
źródło

Odpowiedzi:

17

Programy obsługi są wykonywane:

  • na koniec gry (nie podręcznik)
  • po wykonaniu meta: flush_handlerszadania

Tak więc „ aby dodać na końcu rolę 6, która musi mieć moduły obsługi 4 roli ”, potrzebujesz:

  • albo podzielić przypisanie roli na osobne sztuki;
  • lub dodaj meta zadanie i dołącz szóstą rolę do include_rolemodułu :

    roles:
      - role4
    tasks:
      - meta: flush_handlers
      - include_role:
          name: role6
    

W twoim przypadku sugeruję pierwszą metodę, ponieważ include_rolemoduł jest wciąż bardzo świeży i podczas korzystania z niego występują dziwactwa (zobacz to pytanie w SO ).


Ponadto należy zauważyć, że nazwy osób obsługujących i połączeń nasłuchujących mają charakter globalny, więc dwóch osób obsługujących w oddzielnych rolach będzie w konflikcie, jeśli będą miały tę samą nazwę i obie role zostaną przypisane w jednej grze. (zob. Programy obsługi: Uruchamianie operacji po zmianie )

Do programów obsługi [] przypisuje się globalnie unikalną nazwę i są powiadamiani przez powiadamiających. [] program obsługi, uruchomi się tylko raz, po zakończeniu wszystkich zadań w konkretnej grze.

Nazwy programów obsługi i odsłuchiwane tematy są wyświetlane w globalnej przestrzeni nazw.


  • Dowód empiryczny (uruchom ten skrypt powłoki, aby potwierdzić, że procedury obsługi są wykonywane na końcu gry - tutaj były sprzeczne komentarze i odpowiedzi):

    #!/bin/bash
    
    mkdir -p ./sf831880/roles/role1
    mkdir -p ./sf831880/roles/role1/handlers
    mkdir -p ./sf831880/roles/role1/tasks
    mkdir -p ./sf831880/roles/role2
    mkdir -p ./sf831880/roles/role2/handlers
    mkdir -p ./sf831880/roles/role2/tasks
    
    cat >./sf831880/roles/role1/tasks/main.yml <<TASKS1_END
    ---
    - name: Always true in role1
      command: echo role1
      notify: handler1
    TASKS1_END
    
    cat >./sf831880/roles/role2/tasks/main.yml <<TASKS2_END
    ---
    - name: Always true in role2
      command: echo role2
      notify: handler2
    TASKS2_END
    
    cat >./sf831880/roles/role1/handlers/main.yml <<HANDLERS1_END
    ---
    - name: handler1
      debug:
        msg: "This is a handler in role1"
    HANDLERS1_END
    
    cat >./sf831880/roles/role2/handlers/main.yml <<HANDLERS2_END
    ---
    - name: handler2
      debug:
        msg: "This is a handler in role2"
    HANDLERS2_END
    
    cat >./sf831880/playbook.yml <<PLAYBOOK_END
    ---
    - hosts: localhost
      gather_facts: no
      connection: local
      roles:
        - role1
        - role2
      tasks:
        - debug:
            msg: "This is a task in a play"
    PLAYBOOK_END
    
    ansible-playbook ./sf831880/playbook.yml
    

    Wynik:

    PLAY [localhost] ***************************************************************
    
    TASK [role1 : Always true in role1] ********************************************
    changed: [localhost]
    
    TASK [role2 : Always true in role2] ********************************************
    changed: [localhost]
    
    TASK [debug] *******************************************************************
    ok: [localhost] => {
        "msg": "This is a task in a play"
    }
    
    RUNNING HANDLER [role1 : handler1] *********************************************
    ok: [localhost] => {
        "msg": "This is a handler in role1"
    }
    
    RUNNING HANDLER [role2 : handler2] *********************************************
    ok: [localhost] => {
        "msg": "This is a handler in role2"
    
  • Odtwórz zmodyfikowany, aby zawierał meta: flush_handlers:

    ---
    - hosts: localhost
      gather_facts: no
      connection: local
      roles:
        - role1
        - role2
      tasks:
        - meta: flush_handlers
        - debug:
            msg: "This is a task in a play"
    

    Wynik:

    PLAY [localhost] ***************************************************************
    
    TASK [role1 : Always true in role1] ********************************************
    changed: [localhost]
    
    TASK [role2 : Always true in role2] ********************************************
    changed: [localhost]
    
    RUNNING HANDLER [role1 : handler1] *********************************************
    ok: [localhost] => {
        "msg": "This is a handler in role1"
    }
    
    RUNNING HANDLER [role2 : handler2] *********************************************
    ok: [localhost] => {
        "msg": "This is a handler in role2"
    }
    
    TASK [debug] *******************************************************************
    ok: [localhost] => {
        "msg": "This is a task in a play"
    
techraf
źródło
2

Programy obsługi to listy zadań, które tak naprawdę nie różnią się od zwykłych zadań, do których odwołuje się globalnie unikalna nazwa i które są powiadamiane przez powiadamiających. Jeśli nic nie powiadomi programu obsługi, nie uruchomi się. Niezależnie od tego, ile zadań powiadomi przewodnik, uruchomi się tylko raz, po zakończeniu wszystkich zadań w konkretnej grze. ansible doc

1) Programy obsługi, które robią to samo, powinny mieć takie same nazwy.
restart nginxZAWSZE restartuje nginx, nie handler1ihandler2

2) Manipulatory są uruchamiane na KONIEC całego „Play” spektaklu o zasięgu do twoich sekcji.

3) Użyłbym funkcji registeri whendo zadań, które powinny zostać zrestartowane, zwróć uwagę, że ten var powinien nosić przy sobie.

Źródło kodu

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

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "Play 1"
}

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role2 : Run if change in task c of role 1] *******************************
changed: [localhost]

TASK [role2 : Always true in role2] ********************************************
changed: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "This is a task in a play"
}

RUNNING HANDLER [role1 : handler] **********************************************
ok: [localhost] => {
    "msg": "This is a handler in role1"
}

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

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "Play 2"
}

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role2 : Run if change in task c of role 1] *******************************
changed: [localhost]

TASK [role2 : Always true in role2] ********************************************
changed: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "This is a task in a play"
}

RUNNING HANDLER [role1 : handler] **********************************************
ok: [localhost] => {
    "msg": "This is a handler in role1"
}

PLAY RECAP *********************************************************************
localhost                  : ok=20   changed=14   unreachable=0    failed=0

Wiele sposobów na wykonanie tego samego zadania. Programy obsługi zostały zaprojektowane w taki sposób, aby zapobiec wielokrotnemu ponownemu uruchamianiu tego samego procesu, np. Wiele zmian w serwerze nginx, który ma strony internetowe, certyfikaty ssl i inne zadania wymagające ponownego uruchomienia usługi.

Jacob Evans
źródło
Cytujesz „ uruchom tylko raz, po wykonaniu wszystkich zadań w konkretnej grze ”, a następnie twierdzisz, że coś zupełnie innego „ uruchom zadanie na końcu każdej roli ”. Twoje roszczenie różni się również od rzeczywistości.
techraf
nie, źle zrozumiałeś, jeśli zadzwonię do tego samego modułu obsługi z roli serwera 4 razy z meta. działa tylko raz
Jacob Evans
Pytanie jest jasne: kiedy uruchamiane są programy obsługi? Nie ile razy są uruchamiane. I są uruchamiane na końcu sztuki, a nie na końcu roli. Kropka. Jesteś osobą trzecią, która twierdzi, że jest inaczej, nawet jeśli zrobiłeś to po tym, jak opublikowałem moją odpowiedź z przykładami pokazującymi, że to twierdzenie jest fałszywe.
techraf
i moja odpowiedź brzmi: użyj zadań, a nie modułów obsługi dla elementów, które muszą zostać zrestartowane w ramach ich roli.
Jacob Evans
@techraf tam jesteś.
Jacob Evans