Os manipuladores Ansible definidos nas funções são executados após o manual inteiro ou a função?

12

Estou executando o Ansible 2.0, e poderia executar isso, mas também poderia ser enganado em acreditar em algo que não é verdade nos meus testes empíricos e não encontro documentação para me dizer quando os manipuladores devem ser executados.

Se os manipuladores não forem executados no final de suas tarefas, esse é o meu enigma. Eu tenho um manual com cinco funções, quero adicionar uma função 6 ao final que precisa ter os manipuladores da quarta função concluídos antes que ela possa começar.

Existe alguma maneira de executar o Ansible para confiar na conclusão de um manipulador (ou seja, uma função sendo concluída) antes de fazer outra coisa ou estou usando manipuladores incorretamente?

Peter Turner
fonte

Respostas:

15

Manipuladores são executados:

  • no final de uma peça (não manual)
  • na execução da meta: flush_handlerstarefa

Portanto, " para adicionar uma função 6 ao final, que precisa ter os manipuladores da quarta função ", você precisa:

  • dividir a atribuição de papéis em peças separadas;
  • ou adicione uma meta tarefa e inclua a sexta função no include_rolemódulo :

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

Para o seu caso de uso, sugiro o primeiro método, pois o include_rolemódulo ainda é muito recente e existem peculiaridades ao usá-lo (consulte esta pergunta no SO ).


Além disso, observe que os nomes dos manipuladores e as chamadas de escuta são globais; portanto, dois manipuladores em funções separadas estarão em conflito se tiverem o mesmo nome e ambas as funções foram atribuídas em uma única peça. (ref. Manipuladores: Executando operações em mudança )

Os manipuladores [] são referenciados por um nome globalmente exclusivo e são notificados pelos notificadores. [] um manipulador, ele será executado apenas uma vez, depois de todas as tarefas concluídas em uma jogada específica.

Os nomes de manipuladores e os tópicos de escuta ficam em um espaço para nome global.


  • Prova empírica (execute este shell script para confirmar que os manipuladores são executados no final da peça - houve comentários e respostas contraditórios aqui):

    #!/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"
    
  • Jogo modificado para conter 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"
    

    O 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
fonte
2

Manipuladores são listas de tarefas, não muito diferentes das tarefas regulares, que são referenciadas por um nome globalmente exclusivo e são notificadas pelos notificadores. Se nada notificar um manipulador, ele não será executado. Independentemente de quantas tarefas notificarem um manipulador, ele será executado apenas uma vez, depois que todas as tarefas forem concluídas em uma jogada específica. documento ansível

1) Os manipuladores que fazem a mesma coisa devem ter o mesmo nome.
restart nginxSEMPRE reinicia o nginx, não handler1ehandler2

2) Os manipuladores são executados no final de toda a "peça" de uma peça com escopo definido para suas seções.

3) Eu usaria as funções registere whenpara tarefas que devem ser reiniciadas; observe que este var deve levar consigo.

Código Fonte

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

Muitas maneiras de fazer a mesma tarefa. Os manipuladores foram projetados para impedir a reinicialização do mesmo processo várias vezes, como várias alterações em um servidor nginx que possui sites, certificados SSL e outras tarefas que precisam de reinicialização do serviço.

Jacob Evans
fonte
Você está citando " executar apenas uma vez, depois de todas as tarefas concluídas em uma peça específica " e, em seguida, afirma algo completamente diferente " executar uma tarefa no final de cada função ". Sua reivindicação também é diferente da realidade.
techraf
não, você não entende, se eu chamar o mesmo manipulador da função de servidor 4 vezes da meta. ele só é executado uma vez
Jacob Evans
A questão é clara: quando os manipuladores são executados? Não quantas vezes eles são executados. E eles são exibidos no final de uma peça, não no final de um papel. Período. Você é uma terceira pessoa que afirma o contrário, mesmo que tenha feito isso depois que eu publiquei minha resposta com exemplos mostrando que essa afirmação é falsa.
techraf
e minha resposta é: use tarefas e não manipuladores para itens que devem ser reiniciados dentro de sua função.
Jacob Evans
@techraf aí está você.
Jacob Evans