TL;DR
Use ansible.builtin.uri
to fetch the script content, and pass it through stdin
parameter of ansible.builtin.shell
.
Execution environment
- Ansible: 2.10.5
- Python: 3.8.7
Sample case
There are a lot of cases where the install instructions of tool X introduces the remote script to run. For instance, rustup gives the script as the primary method to install it.
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
In the case you install rustup via Ansible, you may want to write lines like the following:
- name: Run rustup
ansible.builtin.shell:
cmd: curl -sSf https://sh.rustup.rs | sh -s -- -y
(I added -s
option to install the script without prompt that blocks the Ansible installation process.)
Ansible warns when it runs the task like this:
TASK [common : Run rustup] **********************************************************************************
[WARNING]: Consider using the get_url or uri module rather than running 'curl'. If you need to use command
because get_url or uri is insufficient you can add 'warn: false' to this command task or set
'command_warnings=False' in ansible.cfg to get rid of this message.
changed: [dev]
Solution
The easiest way to avoid this is to use get_url
to download the shell script and run it.
- name: Download rustup
ansible.builtin.get_url:
url: https://sh.rustup.rs
dest: /tmp/rustup.sh
- name: Run rustup
ansible.builtin.shell:
cmd: cat /tmp/rustup.sh | sh -s -- -y
Otherwise, you can directly pass the script contents into stdin of shell
with stdin
parameter.
- name: Fetch rustup
ansible.builtin.uri:
url: https://sh.rustup.rs
return_content: yes
register: rustup_installer
- name: Run rustup installer
ansible.builtin.shell:
cmd: sh -s -- -y
stdin: "{{ rustup_installer.content }}"
Top comments (1)
Nice solution, no need to download/remove the installer as a temporary file. The only "negative" thing I see is that it is not possible to verify the installer checksum this way.