I'm trying to set a variable TOKEN with a value of a IMDSv2 (AWS instance metadata) token to get an instance IP address.
Executing a set of commands through the salt CLI yields desired results: Here's the command below:
salt-ssh 'name.of.host' cmd.run cmd='TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -s -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") && curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/public-ipv4'
However, I'm trying to execute the same command through an evaluated expression like so:
{{ salt["cmd.run"](cmd='TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -s -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") && curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/public-ipv4')}}
and the following error shows up:
FileNotFoundError: [Errno 2] No such file or directory: 'TOKEN=$(curl': 'TOKEN=$(curl'
My thinking is that the way salt evaluates command expressions through CLI is different from a jinja esque evaluation. I also understand that spaces are a factor in shell expressions for salt. I tried different combinations of putting escape characters behind the equal, dollar and parenthesis, but no such luck. I still think it has to do with special characters, but can't pinpoint what.
Any thoughts? Much appreciated.
As per the documentation, the cmd.run
does not process commands through Shell by default. Quoting a "Warning" from the above link:
This function does not process commands through a shell unless the python_shell flag is set to True. This means that any shell-specific functionality such as 'echo' or the use of pipes, redirection or &&, should either be migrated to cmd.shell or have the python_shell=True flag set here.
So there are two options:
Instead of using cmd.run
use cmd.shell
. E.g.:
{{ salt.cmd.shell('TOKEN=$(curl -X PUT ...)') }}
Or add python_shell=True
to cmd.run
. E.g.:
{{ salt.cmd.run('TOKEN=$(curl -X PUT ...)', python_shell=True) }}