¿Los manejadores de Ansible están definidos en roles ejecutados después de todo el libro de jugadas o el rol?

12

Estoy ejecutando Ansible 2.0, y podría ejecutar esto, pero también podría ser engañado para creer algo que no es cierto por mis pruebas empíricas y no puedo encontrar documentación que me diga cuándo se supone que deben ejecutarse los controladores.

Si los controladores no se ejecutan al final de sus tareas, este es mi enigma. Tengo un libro de jugadas con 5 roles, quiero agregar un rol 6 al final que necesita tener los controladores del cuarto rol completado antes de que pueda comenzar.

¿Hay alguna forma de ejecutar Ansible para confiar en que se complete un controlador (es decir, un rol que se haya completado por completo) antes de hacer otra cosa o estoy usando los controladores incorrectamente?

Peter Turner
fuente

Respuestas:

15

Los manejadores se ejecutan:

  • al final de una obra de teatro (no libro de jugadas)
  • al ejecutar la meta: flush_handlerstarea

Entonces, " para agregar un rol 6 al final que necesita tener los controladores del cuarto rol " que necesita:

  • ya sea para dividir la asignación de roles en juegos separados;
  • o agregue una metatarea e incluya el sexto rol con el include_rolemódulo :

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

Para su caso de uso, sugeriría el primer método, ya que el include_rolemódulo aún es muy nuevo y hay peculiaridades al usarlo (consulte esta pregunta en SO ).


Además, tenga en cuenta que los nombres de los manejadores y las llamadas de escucha son globales, por lo que dos manejadores en roles separados estarán en conflicto si tenían el mismo nombre y ambos roles fueron asignados en una sola obra. (ref. Manejadores: Ejecutar operaciones en cambio )

Los controladores [] están referenciados por un nombre único global y los notificadores los notifican. [] un controlador, se ejecutará solo una vez, después de completar todas las tareas en una jugada en particular.

Los nombres de los manejadores y escuchar temas en vivo en un espacio de nombres global.


  • Prueba empírica (ejecute este script de shell para confirmar que los controladores se ejecutan al final de la jugada; aquí hubo comentarios y respuestas contradictorias):

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

    Resultado:

    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"
    
  • Juego modificado para contener 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"
    

    El resultado:

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

Los controladores son listas de tareas, no muy diferentes de las tareas normales, a las que se hace referencia con un nombre único global y que los notificadores notifican. Si nada notifica a un controlador, no se ejecutará. Independientemente de cuántas tareas notifiquen a un controlador, se ejecutará solo una vez, después de que todas las tareas se completen en una jugada en particular. doc. ansible

1) Los controladores que hacen lo mismo deben llamarse iguales.
restart nginxSIEMPRE reinicia nginx, no handler1yhandler2

2) Los controladores se ejecutan al FINAL de toda la "Obra", una jugada que se enfoca en sus secciones.

3) Usaría las funciones registery whenpara las tareas que deberían reiniciarse, tenga en cuenta que esta var debería llevarla con usted.

Código fuente

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

Muchas formas de hacer la misma tarea. Los controladores se diseñaron para evitar reiniciar el mismo proceso varias veces, como cambios múltiples en un servidor nginx que tiene sitios web, certificados SSL y otras tareas que necesitan reiniciar el servicio.

Jacob Evans
fuente
Estás citando " ejecutar solo una vez, después de completar todas las tareas en una jugada en particular " y luego reclamar algo completamente diferente " ejecutar una tarea al final de cada rol ". Su reclamo también es diferente de la realidad.
techraf
no, no lo malinterpretas, si llamo al mismo controlador desde la función del servidor 4 veces desde meta. solo se ejecuta una vez
Jacob Evans
La pregunta es clara: ¿ cuándo se ejecutan los controladores? No cuántas veces se corren. Y se ejecutan al final de una obra, no al final de un papel. Período. Usted es una tercera persona que afirma lo contrario, aunque lo hizo después de que publiqué mi respuesta con ejemplos que muestran que esta afirmación es falsa.
techraf
y mi respuesta es, use tareas, no manejadores, para elementos que deben reiniciarse dentro de su rol.
Jacob Evans
@techraf ahí estás.
Jacob Evans