I am trying to execute a command on docker on other machine from my machine. When I execute this command:
- name: Add header
command: docker exec cli bash -l -c "echo '{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":'$(cat jaguar_update.json)'}}}' | jq . > jaguar_update_in_envelope.json"
through ansible playbook, I am getting the error shown below.
fatal:[
command-task
]:FAILED! =>{
"changed":true,
"cmd":[ ],
"delta":"0:00:00.131115",
"end":"2019-07-11 17:32:44.651504",
"msg":"non-zero return code",
"rc":4,
"start":"2019-07-11 17:32:44.520389",
"stderr":"mesg: ttyname
failed: Inappropriate ioctl for device\nparse error: Invalid numeric
literal at line 1, column 9",
"stderr_lines":[
"mesg: ttyname failed:
Inappropriate ioctl for device",
"parse error: Invalid numeric literal
at line 1, column 9"
],
"stdout":"",
"stdout_lines":[
]
}
But if I manually execute command in the docker container, it works fine and I don't get any issue.
EDIT:
As suggested i tried with shell
module
shell: docker exec cli -it bash -l -c "echo '{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":'$(cat jaguar_update.json)'}}}' | jq . > jaguar_update_in_envelope.json"
But i get below error as
fatal: [command-task]: FAILED! => {"changed": true, "cmd": "docker exec cli -it bash -l -c echo '{\"payload\":{\"header\":{\"channel_header\":{\"channel_id\":\"gll\", \"type\":2}},\"data\":{\"config_update\":'$(cat jaguar_update.json)'}}}' | jq . > jaguar_update_in_envelope.json", "delta": "0:00:00.110341", "end": "2019-07-12 10:21:45.204049", "msg": "non-zero return code", "rc": 4, "start": "2019-07-12 10:21:45.093708", "stderr": "cat: jaguar_update.json: No such file or directory\nparse error: Invalid numeric literal at line 1, column 4", "stderr_lines": ["cat: jaguar_update.json: No such file or directory", "parse error: Invalid numeric literal at line 1, column 4"], "stdout": "", "stdout_lines": []}
All the files 'jaguar_update.json' present in the working directory. I have confirmed the working directory.
Above commands works if i put it in a shell script file then execute the shell script from ansible.
Troubleshooting Ansible can be tricky but using a methodical approach combined with the built-in problem-solving tools you can make it far easier on yourself. Confirm the Ansible environment and task flow, then look for proper data types, and finally consider pausing and stepping through each task.
Ignoring failed commands By default Ansible stops executing tasks on a host when a task fails on that host. You can use ignore_errors to continue on in spite of the failure. The ignore_errors directive only works when the task is able to run and returns a value of 'failed'.
Ansible Playbooks are lists of tasks that automatically execute against hosts. Groups of hosts form your Ansible inventory. Each module within an Ansible Playbook performs a specific task. Each module contains metadata that determines when and where a task is executed, as well as which user executes it.
The playbook sets three of the seven values from the command line above: the group (hosts: all), the connection method (connection: ansible.netcommon.network_cli) and the module (in each task). With those values set in the playbook, you can omit them on the command line. The playbook also adds a second task to show the config output.
If you are running Ansible in a virtual environment, you will also need to add the variable ansible_python_interpreter=/path/to/venv/bin/python Create and run your first network Ansible Playbook ¶ If you want to run this command every day, you can save it in a playbook and run it with ansible-playbook instead of ansible .
Put the concepts you learned to work with this quick tutorial. Install Ansible, execute a network configuration command manually, execute the same command with Ansible, then create a playbook so you can execute the command any time on multiple network devices.
You can omit -k flag. If you are running Ansible in a virtual environment, you will also need to add the variable ansible_python_interpreter=/path/to/venv/bin/python If you want to run this command every day, you can save it in a playbook and run it with ansible-playbook instead of ansible.
As everyone has mentioned this does need you to use shell
instead of command
. Now you want to simplify this command so it can run first in bash. Which can be done easily using printf
$ printf "%s%s%s" '{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":' $(<jaguar_update.json'}}}' | jq . > jaguar_update_in_envelope.json
$ cat jaguar_update_in_envelope.json
{
"payload": {
"header": {
"channel_header": {
"channel_id": "gll",
"type": 2
}
},
"data": {
"config_update": {
"name": "tarun"
}
}
}
}
So now our commands runs without issues. Next is to move it with bash -l -c
format. So instead using -c
which requires us to pass the whole command as one parameter, we use the multiline commands
$ bash -l <<EOF
printf "%s%s%s" '{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":' $(<jaguar_update.json) '}}}' | jq . > jaguar_update_in_envelope.json
EOF
But this fails with an error
{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":{bash: line 2: name:: command not found
bash: line 3: syntax error near unexpected token `}'
bash: line 3: `} '}}}' | jq . > jaguar_update_in_envelope.json'
This is because the EOF
format will treat each new line as a different command. So we need to replace all new line characters
bash -l <<EOF
printf "%s%s%s" '{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":' $(sed -E 's|"|\\"|g' jaguar_update.json | tr -d '\n') '}}}' | jq . > jaguar_update_in_envelope.json
EOF
And now in ansible
- name: a play that runs entirely on the ansible host
hosts: 127.0.0.1
connection: local
tasks:
- name: Solve the problem
shell: |
bash -l <<EOF
printf "%s%s%s" '{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":' $(sed -E 's|"|\\"|g' jaguar_update.json | tr -d '\n') '}}}' | jq . > jaguar_update_in_envelope.json
EOF
And the result
$ ansible-playbook test.yml
PLAY [a play that runs entirely on the ansible host] *********************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************************************************
ok: [127.0.0.1]
TASK [Solve the problem] *************************************************************************************************************************************************************
changed: [127.0.0.1]
PLAY RECAP ***************************************************************************************************************************************************************************
127.0.0.1 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$ cat jaguar_update_in_envelope.json
{
"payload": {
"header": {
"channel_header": {
"channel_id": "gll",
"type": 2
}
},
"data": {
"config_update": {
"name": "tarun"
}
}
}
}
To avoid any complexity, try as in this question to wrap your command in a script, and call that script (with command
or shell
)
- name: Add header
raw: /path/to/script/docker-add-header.sh
And in /path/to/script/docker-add-header.sh
:
docker exec cli -it bash -l -c "echo '{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":'$(cat jaguar_update.json)'}}}' | jq . > jaguar_update_in_envelope.json
Try to make the script work first alone (no Ansible).
See (if it is not working, even outside any Ansible call), to escape nested double-quotes:
docker exec cli -it bash -l -c "echo '{\"payload\":{\"header\":...
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