Ansible: ¿Almacenar la salida estándar del comando en una nueva variable?

85

Dentro de mi libro de jugadas, me gustaría crear una variable que contenga la salida de un comando externo. Luego quiero hacer uso de esa variable en un par de plantillas.

Estas son las partes relevantes del libro de jugadas:

  tasks:
    - name: Create variable from command
      command: "echo Hello"
      register: command_output
    - debug: msg="{{command_output.stdout}}"

    - name: Copy test service
      template: src=../templates/test.service.j2 dest=/tmp/test.service
    - name: Enable test service
      shell: systemctl enable /tmp/test.service
    - name: Start test service
      shell: systemctl start test.service

y digamos que esta es mi plantilla:

[Unit]
Description=MyApp
After=docker.service
Requires=docker.service

[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill busybox1
ExecStartPre=-/usr/bin/docker rm busybox1
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --name busybox1 busybox /bin/sh -c "while true; do echo {{ string_to_echo }}; sleep 1; done"

[Install]
WantedBy=multi-user.target

(Note el {{ string_to_echo }})

Entonces, lo que básicamente estoy buscando es una forma de almacenar el contenido de command_output.stdout(que se genera / recupera durante la primera tarea) en una nueva variable string_to_echo.
Esa variable que me gustaría usar en varias plantillas después.

Supongo que podría usarlo {{command_output.stdout}}en mis plantillas, pero quiero deshacerme de eso .stdoutpara mejorar la legibilidad.

Forivin
fuente

Respuestas:

69

No es necesario establecer un hecho.

    - shell: cat "hello"
      register: cat_contents

    - shell: echo "I cat hello"
      when: cat_contents.stdout == "hello"
Karel Striegel
fuente
13
Esto es útil, pero significa que más adelante, cuando use la variable, debe recordar usarla .stdouttambién.
Tim Malone
20

Una ligera modificación más allá de la respuesta de @ udondan. Me gusta reutilizar los nombres de las variables registradas con el set_factpara ayudar a mantener el desorden al mínimo.

Entonces, si tuviera que registrarme usando la variable, pskusaría el mismo nombre de variable para crear el set_fact.

Ejemplo

- name: generate PSK
  shell: openssl rand -base64 48
  register: psk
  delegate_to: 127.0.0.1
  run_once: true

- set_fact: 
    psk={{ psk.stdout }}

- debug: var=psk
  run_once: true

Luego, cuando lo ejecuto:

$ ansible-playbook -i inventory setup_ipsec.yml

 PLAY                                                                                                                                                                                [all] *************************************************************************************************************************************************************************

 TASK [Gathering                                                                                                                                                                     Facts] *************************************************************************************************************************************************************
 ok: [hostc.mydom.com]
 ok: [hostb.mydom.com]
 ok: [hosta.mydom.com]

 TASK [libreswan : generate                                                                                                                                                          PSK] ****************************************************************************************************************************************************
 changed: [hosta.mydom.com -> 127.0.0.1]

 TASK [libreswan :                                                                                                                                                                   set_fact] ********************************************************************************************************************************************************
 ok: [hosta.mydom.com]
 ok: [hostb.mydom.com]
 ok: [hostc.mydom.com]

 TASK [libreswan :                                                                                                                                                                   debug] ***********************************************************************************************************************************************************
 ok: [hosta.mydom.com] => {
     "psk": "6Tx/4CPBa1xmQ9A6yKi7ifONgoYAXfbo50WXPc1kGcird7u/pVso/vQtz+WdBIvo"
 }

 PLAY                                                                                                                                                                                RECAP *************************************************************************************************************************************************************************
 hosta.mydom.com    : ok=4    changed=1    unreachable=0    failed=0
 hostb.mydom.com    : ok=2    changed=0    unreachable=0    failed=0
 hostc.mydom.com    : ok=2    changed=0    unreachable=0    failed=0
slm
fuente
7

Soy un novato en Ansible, pero sugeriría la siguiente solución:

playbook.yml

...
vars:
  command_output_full:
    stdout: will be overriden below
  command_output: {{ command_output_full.stdout }}
...
...
...
tasks:
  - name: Create variable from command
    command: "echo Hello"
    register: command_output_full
  - debug: msg="{{ command_output }}"

Debería funcionar (y funciona para mí) porque Ansible usa la evaluación perezosa. Pero parece que verifica la validez antes del lanzamiento, así que tengo que definirlo command_output_full.stdouten vars.

Y, por supuesto, si hay demasiadas vars en la varssección, se verá feo.

Dmitry
fuente
7

En caso de que desee almacenar un comando complejo para comparar el resultado del texto, por ejemplo, para comparar la versión del sistema operativo, tal vez esto pueda ayudarlo:

tasks:
       - shell: echo $(cat /etc/issue | awk {'print $7'})
         register: echo_content

       - shell: echo "It works"
         when: echo_content.stdout == "12"
         register: out
       - debug: var=out.stdout_lines
BrennQuin
fuente
1

Si desea ir más allá y extraer la información exacta que desea de los resultados de Playbook, use el lenguaje de consulta JSON como jmespath, un ejemplo:

  - name: Sample Playbook
    // Fill up your task
    no_log: True
    register: example_output

  - name: Json Query
    set_fact:
      query_result:
        example_output:"{{ example_output | json_query('results[*].name') }}"
Santee
fuente