Inside my playbook I'd like to create a variable holding the output of an external command. Afterwards I want to make use of that variable in a couple of templates.
Here are the relevant parts of the playbook:
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
and let's say this is my template:
[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
(Notice the {{ string_to_echo }}
)
So what I'm basically looking for is a way to store the contents of command_output.stdout
(which is generated/retrieved during the first task) in a new variable string_to_echo
.
That variable I'd like to use in multiple templates afterwards.
I guess I could just use {{command_output.stdout}}
in my templates, but I want to get rid of that .stdout
for readability.
The command module runs the shell command, and the registar argument then accepts the results and puts them in "command_output". We then take the standard output of that and put it into the ansible variable "string_to_echo" which can then be used later in the ansible playbooks.
To achieve this, we use the 'register' parameter to record the output to a variable. Then use the 'debug' module to display the variable's content to standard out.
stdout. Some modules execute command line utilities or are geared for executing commands directly (raw, shell, command, and so on). This field contains the normal output of these utilities. "stdout": "foo!"
To do this, you have to specify which variable to save the results into. Do this with the register parameter, independently of the module used. Here register tells ansible to save the response of the module into the shell_result variable, and then we use the debug module to print the variable out.
You have to store the content as a fact:
- set_fact:
string_to_echo: "{{ command_output.stdout }}"
There's no need to set a fact.
- shell: cat "hello"
register: cat_contents
- shell: echo "I cat hello"
when: cat_contents.stdout == "hello"
A slight modification beyond @udondan's answer. I like to reuse the registered variable names with the set_fact
to help keep the clutter to a minimum.
So if I were to register using the variable, psk
, I'd use that same variable name with creating the set_fact
.
- 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
Then when I run it:
$ 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
I'm a newbie in Ansible, but I would suggest next solution:
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 }}"
It should work (and works for me) because Ansible uses lazy evaluation. But it seems it checks validity before the launch, so I have to define command_output_full.stdout
in vars.
And, of course, if it is too many such vars in vars
section, it will look ugly.
In case than you want to store a complex command to compare text result, for example to compare the version of OS, maybe this can help you:
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
If you want to go further and extract the exact information you want from the Playbook results, use JSON query language like jmespath, an example:
- 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') }}"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With