Sind Ansible-Handler in Rollen definiert, die nach dem gesamten Playbook oder der Rolle ausgeführt werden?


12

Ich verwende Ansible 2.0, und ich könnte dies einfach ausführen, aber ich könnte auch dazu verleitet werden, etwas zu glauben, das durch meine empirischen Tests nicht wahr ist, und ich kann keine Dokumentation finden, die mir sagt, wann Handler ausgeführt werden sollen.

Wenn Handler am Ende ihrer Aufgaben nicht ausgeführt werden, ist dies mein Rätsel. Ich habe ein Playbook mit 5 Rollen. Ich möchte dem Ende eine 6-Rolle hinzufügen, damit die Handler der 4. Rolle fertig sind, bevor es beginnen kann.

Gibt es eine Möglichkeit, Ansible auszuführen, um sich darauf zu verlassen, dass ein Handler abgeschlossen ist (dh eine Rolle vollständig abgeschlossen ist), bevor ich etwas anderes tue, oder verwende ich Handler falsch?

Antworten:


15

Handler werden ausgeführt:

  • am Ende eines Stückes (nicht Spielbuch)
  • bei der Ausführung der meta: flush_handlersAufgabe

Also " um eine 6 Rolle zum Ende hinzuzufügen, die die Handler der 4. Rolle haben muss ", benötigen Sie:

  • entweder um die Rollenzuweisung in separate Spiele aufzuteilen;
  • oder fügen Sie eine Meta-Aufgabe hinzu und fügen Sie die 6. Rolle mit include_roleModul hinzu :

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

Für Ihren Anwendungsfall würde ich die erste Methode vorschlagen, da das include_roleModul noch sehr frisch ist und es bei der Verwendung Macken gibt (siehe diese Frage zu SO ).


Beachten Sie außerdem, dass die Namen und Abhöranrufe der Handler global sind, sodass zwei Handler in unterschiedlichen Rollen in Konflikt stehen, wenn sie denselben Namen haben und beide Rollen in einem Spiel zugewiesen wurden. ( Siehe Handler: Ausführen von Vorgängen bei Änderung. )

Handler [] werden durch einen global eindeutigen Namen referenziert und von Notifizierern benachrichtigt. [] Ein Handler wird nur einmal ausgeführt, nachdem alle Aufgaben in einem bestimmten Spiel abgeschlossen wurden.

Handlernamen und Listen-Themen befinden sich in einem globalen Namespace.


  • Empirischer Beweis (führen Sie dieses Shell-Skript aus, um zu bestätigen, dass die Handler am Ende des Spiels ausgeführt werden - hier gab es widersprüchliche Kommentare und Antworten):

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

    Ergebnis:

    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"
    
  • Spiel geändert, um zu enthalten 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"
    

    Das Ergebnis:

    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"
    

2

Handler sind Listen von Aufgaben, die sich nicht wirklich von normalen Aufgaben unterscheiden, auf die durch einen global eindeutigen Namen verwiesen wird und die von Benachrichtigern benachrichtigt werden. Wenn ein Handler nicht benachrichtigt wird, wird er nicht ausgeführt. Unabhängig davon, wie viele Tasks einen Handler benachrichtigen, wird er nur einmal ausgeführt, nachdem alle Tasks in einem bestimmten Spiel abgeschlossen wurden. Ansible doc

1) Handler, die dasselbe tun, sollten den gleichen Namen haben.
restart nginxStartet Nginx IMMER neu, nicht handler1undhandler2

2) Handler werden am ENDE des gesamten "Spiels" ausgeführt, ein Spiel, das sich auf Ihre Abschnitte bezieht.

3) Ich würde die registerund whenFunktionen für Aufgaben verwenden, die neu gestartet werden sollten, beachten Sie, dass diese var mit sich führen sollte.

Code-Quelle

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

Viele Möglichkeiten, die gleiche Aufgabe zu erledigen. Handler sollten verhindern, dass derselbe Prozess mehrmals neu gestartet wird, z. B. mehrfache Änderungen an einem Nginx-Server mit Websites, SSL-Zertifikaten und anderen Aufgaben, die einen Neustart des Dienstes erfordern.


Sie zitieren " nur einmal ausführen, nachdem alle Aufgaben in einem bestimmten Spiel abgeschlossen sind " und behaupten dann, etwas völlig anderes " eine Aufgabe am Ende jeder Rolle ausführen ". Ihr Anspruch unterscheidet sich auch von der Realität.
Techraf

nein du missverstehst, wenn ich den gleichen handler von der serverrolle 4 mal aus meta aufrufe. es läuft nur einmal
Jacob Evans

Die Frage ist klar: Wann werden die Handler ausgeführt? Nicht wie oft sie ausgeführt werden. Und sie werden am Ende eines Stücks gespielt, nicht am Ende einer Rolle. Zeitraum. Sie sind eine dritte Person, die etwas anderes behauptet, obwohl Sie es getan haben, nachdem ich meine Antwort mit Beispielen gepostet habe, die zeigen, dass diese Behauptung falsch ist.
Techraf

Und meine Antwort lautet: Verwenden Sie Tasks und keine Handler für Elemente, die innerhalb ihrer Rolle neu gestartet werden müssen.
Jacob Evans

@techraf da bist du.
Jacob Evans
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.