Issue in ansible playbook command? - shell

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.

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\":...

c.f. the docs -
The command(s) will not be processed through the shell, so variables like $HOME and operations like "<", ">", "|", ";" and "&" will not work. Use the shell module if you need these features.
shell pretty literally submits a script to the sh command parser.
Another note - you end the single-quote before the $(cat jaguar_update.json) and restart it after, but don't use any double quoting around it. Your output may handle that, but I wanted to call attention in case it matters.

Related

ansible synchronize module fails to get directory from remote to local - failed: No such file or directory

I wish to copy /web/playbooks/automation/misc/filecopyprod from mysourceuser#mysourcehost to destination mydestuser#mydesthost under the below location /web/playbooks/automation/misc/filecopy/tmpfiles/500/
Evident that both the source and destinations are present and have good permissions.
[mydestuser#mydesthost ~]$ ssh mysourceuser#mysourcehost ls -ld '/web/playbooks/automation/misc/filecopyprod'
##################################################################
# *** This Server is using Centrify *** #
# *** Remember to use your Active Directory account *** #
# *** password when logging in *** #
##################################################################
drwxrwxr-x 3 mysourceuser mysourceuser 209 Sep 26 14:58 /web/playbooks/automation/misc/filecopyprod
[mydestuser#mydesthost ~]$ ls -ld /web/playbooks/automation/misc/filecopy/tmpfiles/500/
drwxr-xr-x 2 mydestuser aces 6 Sep 26 14:13 /web/playbooks/automation/misc/filecopy/tmpfiles/500/
Here is my playbook that runs on the mydesthost and gets me files & folders from a remote server mysourceuser#mysourcehost to local server mydestuser#mydesthost
- name: Copying from "{{ inventory_hostname }}" to this ansible server.
tags: validate
synchronize:
src: "'{{ item }}'"
dest: "{{ playbook_dir }}/tmpfiles/{{ Latest_Build_Number }}/"
mode: pull
copy_links: yes
with_items:
- "{{ source_file_new.splitlines() }}"
To run the above playbook:
ansible-playbook /web/playbooks/automation/misc/filecopy/copyfiles.yml -e "source_file_new='$source_file_new'" -e "Latest_Build_Number='500'"
Output of my run:
TASK [Copying from "mysourcehost" to this ansible server.] **********************
task path: /web/playbooks/automation/misc/filecopy/copyfiles.yml:218
Monday 26 September 2022 14:13:02 -0500 (0:00:00.047) 0:00:03.084 ******
redirecting (type: action) ansible.builtin.synchronize to ansible.posix.synchronize
redirecting (type: action) ansible.builtin.synchronize to ansible.posix.synchronize
<mysourcehost> ESTABLISH LOCAL CONNECTION FOR USER: mydestuser
<mysourcehost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/mydestuser/.ansible/tmp/ansible-local-20463qmilic81 `"&& mkdir "` echo /home/mydestuser/.ansible/tmp/ansible-local-20463qmilic81/ansible-tmp-1664219583.0005133-20679-105296975361597 `" && echo ansible-tmp-1664219583.0005133-20679-105296975361597="` echo /home/mydestuser/.ansible/tmp/ansible-local-20463qmilic81/ansible-tmp-1664219583.0005133-20679-105296975361597 `" ) && sleep 0'
Using module file /home/mydestuser/.ansible/collections/ansible_collections/ansible/posix/plugins/modules/synchronize.py
<mysourcehost> PUT /home/mydestuser/.ansible/tmp/ansible-local-20463qmilic81/tmpxhpyaf0m TO /home/mydestuser/.ansible/tmp/ansible-local-20463qmilic81/ansible-tmp-1664219583.0005133-20679-105296975361597/AnsiballZ_synchronize.py
<mysourcehost> EXEC /bin/sh -c 'chmod u+x /home/mydestuser/.ansible/tmp/ansible-local-20463qmilic81/ansible-tmp-1664219583.0005133-20679-105296975361597/ /home/mydestuser/.ansible/tmp/ansible-local-20463qmilic81/ansible-tmp-1664219583.0005133-20679-105296975361597/AnsiballZ_synchronize.py && sleep 0'
<mysourcehost> EXEC /bin/sh -c '/usr/local/bin/python3.8 /home/mydestuser/.ansible/tmp/ansible-local-20463qmilic81/ansible-tmp-1664219583.0005133-20679-105296975361597/AnsiballZ_synchronize.py && sleep 0'
<mysourcehost> EXEC /bin/sh -c 'rm -f -r /home/mydestuser/.ansible/tmp/ansible-local-20463qmilic81/ansible-tmp-1664219583.0005133-20679-105296975361597/ > /dev/null 2>&1 && sleep 0'
failed: [mysourcehost] (item=/web/playbooks/automation/misc/filecopyprod) => {
"ansible_loop_var": "item",
"changed": false,
"cmd": "/bin/rsync --delay-updates -F --compress --copy-links --archive --rsh=/usr/share/centrifydc/bin/ssh -S none -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null --out-format=<<CHANGED>>%i %n%L mysourceuser#mysourcehost:'/web/playbooks/automation/misc/filecopyprod' /web/playbooks/automation/misc/filecopy/tmpfiles/500/",
"invocation": {
"module_args": {
"_local_rsync_password": null,
"_local_rsync_path": "rsync",
"_substitute_controller": false,
"archive": true,
"checksum": false,
"compress": true,
"copy_links": true,
"delete": false,
"dest": "/web/playbooks/automation/misc/filecopy/tmpfiles/500/",
"dest_port": null,
"dirs": false,
"existing_only": false,
"group": null,
"link_dest": null,
"links": null,
"mode": "pull",
"owner": null,
"partial": false,
"perms": null,
"private_key": null,
"recursive": null,
"rsync_opts": [],
"rsync_path": null,
"rsync_timeout": 0,
"set_remote_user": true,
"src": "mysourceuser#mysourcehost:'/web/playbooks/automation/misc/filecopyprod'",
"ssh_args": null,
"ssh_connection_multiplexing": false,
"times": null,
"verify_host": false
}
},
"item": "/web/playbooks/automation/misc/filecopyprod",
"msg": "Warning: Permanently added 'mysourcehost' (ED25519) to the list of known hosts.\r\n\nThis system is for the use by authorized users only. All data contained\non all systems is owned by the company and may be monitored, intercepted,\nrecorded, read, copied, or captured in any manner and disclosed in any\nmanner, by authorized company personnel. Users (authorized or unauthorized)\nhave no explicit or implicit expectation of privacy. Unauthorized or improper\nuse of this system may result in administrative, disciplinary action, civil\nand criminal penalties. Use of this system by any user, authorized or\nunauthorized, constitutes express consent to this monitoring, interception,\nrecording, reading, copying, or capturing and disclosure.\n\nIF YOU DO NOT CONSENT, LOG OFF NOW.\n\n##################################################################\n# *** This Server is using Centrify *** #\n# *** Remember to use your Active Directory account *** #\n# *** password when logging in *** #\n##################################################################\n\nrsync: change_dir \"/home/mysourceuser//'/web/playbooks/automation/misc\" failed: No such file or directory (2)\nrsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1658) [Receiver=3.1.2]\nrsync: [Receiver] write error: Broken pipe (32)\n",
"rc": 23
}
From the output i got the concerned rsync command and tried to run it manually on my playbook host mydestuser#mydesthost and i get similar error:
"/bin/rsync --delay-updates -F --compress --copy-links --archive --rsh=/usr/share/centrifydc/bin/ssh -S none -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null --out-format=<<CHANGED>>%i %n%L mysourceuser#mysourcehost:'/web/playbooks/automation/misc/filecopyprod' /web/playbooks/automation/misc/filecopy/tmpfiles/500/"
Output:
bash: /bin/rsync --delay-updates -F --compress --copy-links --archive --rsh=/usr/share/centrifydc/bin/ssh -S none -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null --out-format=<<CHANGED>>%i %n%L mysourceuser#mysourcehost:'/web/playbooks/automation/misc/filecopyprod' /web/playbooks/automation/misc/filecopy/tmpfiles/500/: No such file or directory
Upon suggestion from StackOverflow I quoted --out-format but I continue to get the same error. See snapshot of the error in the output below:
"/bin/rsync --delay-updates -F --compress --copy-links --archive --rsh=/usr/share/centrifydc/bin/ssh -S none -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null --out-format='<<CHANGED>>%i %n%L' mysourceuser#mysourcehost:'/tmp/myfolder' /tmp/myfolder1"
Can you please suggest?
Your full command was this
/bin/rsync --delay-updates -F --compress --copy-links --archive --rsh=/usr/share/centrifydc/bin/ssh -S none -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null --out-format=<<CHANGED>>%i %n%L mysourceuser#mysourcehost:'/web/playbooks/automation/misc/filecopyprod' /web/playbooks/automation/misc/filecopy/tmpfiles/500/
You've omitted to quote arguments containing spaces, so when the shell parses the line it splits at those spaces, leading to syntax errors when rsync tries to understand the line.
Fix the --rsh parameter, which contains spaces, by changing it to this:
--rsh='/usr/share/centrifydc/bin/ssh -S none -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
Fix the --out-format parameter, which contains whitespace and shell special characters by changing it to this:
--out-format='<<CHANGED>>%i %n%L'
In a later example, you've put double quotes around the entire command, so the shell is trying to execute the entire command as a single entity. For example, in the first line the shell splits the line at spaces then executes the command echo with a parameter hello. In second line the shell sees the quoted string and treats it as a single entity; it then tries to execute the command called echo hello - not a command echo with a parameter hello but a command with a literal space character in the middle:
echo hello # → hello
"echo hello" # → -bash: echo hello: command not found
Rule: if a command or parameter contains a space or other special shell character and it's to be considered as a single item, it must be quoted.
The playbook works for older versions of rsync.
With the latest version it started to fail as reported here.
Changed
synchronize:
src: "'{{ item }}'"
to
synchronize:
src: "{{ item }}"
and the error was gone issued resolved with the latest rsync.

how to execute multiline command in ansible 2.9.10 in fedora 32

I want to execute a command using ansible 2.9.10 in remote machine, first I tried like this:
ansible kubernetes-root -m command -a "cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"registry-mirrors":[
"https://kfwkfulq.mirror.aliyuncs.com",
"https://2lqq34jg.mirror.aliyuncs.com",
"https://pee6w651.mirror.aliyuncs.com",
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn",
"https://registry.docker-cn.com"
]
}"
obviously it is not working.so I read this guide and tried like this:
- hosts: kubernetes-root
remote_user: root
tasks:
- name: add docker config
shell: >
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"registry-mirrors":[
"https://kfwkfulq.mirror.aliyuncs.com",
"https://2lqq34jg.mirror.aliyuncs.com",
"https://pee6w651.mirror.aliyuncs.com",
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn",
"https://registry.docker-cn.com"
]
}
and execute it like this:
[dolphin#MiWiFi-R4CM-srv playboook]$ ansible-playbook add-docker-config.yaml
[WARNING]: Invalid characters were found in group names but not replaced, use
-vvvv to see details
ERROR! We were unable to read either as JSON nor YAML, these are the errors we got from each:
JSON: Expecting value: line 1 column 1 (char 0)
Syntax Error while loading YAML.
could not find expected ':'
The error appears to be in '/home/dolphin/source-share/source/dolphin/dolphin-scripts/ansible/playboook/add-docker-config.yaml': line 7, column 7, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
cat > /etc/docker/daemon.json <<EOF
{
^ here
is there anyway to achive this?how to fix it?
your playbook should work fine, you just have to add some indentation after the shell clause line, and change the > to |:
here is the updated PB:
---
- name: play name
hosts: dell420
gather_facts: false
vars:
tasks:
- name: run shell task
shell: |
cat > /tmp/temp.file << EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"registry-mirrors":[
"https://kfwkfulq.mirror.aliyuncs.com",
"https://2lqq34jg.mirror.aliyuncs.com",
"https://pee6w651.mirror.aliyuncs.com",
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn",
"https://registry.docker-cn.com"
]
}
EOF
Not sure what is wrong with the ad-hoc command, i tried a few things but didnt manage to make it work.
hope these help
EDIT:
as pointed out by Zeitounator, the ad-hoc command will work if you use shell module instead of command. example:
ansible -i hosts dell420 -m shell -a 'cat > /tmp/temp.file <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"registry-mirrors":[
"https://kfwkfulq.mirror.aliyuncs.com",
"https://2lqq34jg.mirror.aliyuncs.com",
"https://pee6w651.mirror.aliyuncs.com",
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn",
"https://registry.docker-cn.com"
]
}
EOF
'

shell script gives incorrect output when invoked using Ansible shell module

I have check.sh script that I wish to run on the target nodes:
cat check.sh
str=`echo $1 | sed -e 's#[\][\]n# #g'`
echo $str>check.row
It is suppose to replace \n with a single white space from the argument and save it in check.row file.
When I run it manually on the target server i get good output results as shown below:
bash -x ./check.sh '/fin/app/01/scripts\\n/fin/app/01/sql'
++ echo '/fin/app/01/scripts\\n/fin/app/01/sql'
++ sed -e 's#[\][\]n# #g'
+ str='/fin/app/01/scripts /fin/app/01/sql'
+ echo /fin/app/01/scripts /fin/app/01/sql
The check.row generated looks good as below:
[user1#remotehost1 ~]$ cat check.row
/fin/app/01/scripts /fin/app/01/sql
However, when i run the same using ansible shell or command module I do not get the expected results.
Below is my playbook:
tasks:
- copy:
src: "{{ playbook_dir }}/files/check.sh"
dest: "~/"
mode: 0754
- set_fact:
install_dir: "{{ hostvars[\'localhost\'][\'command_result\'].stdout.split('\t')[2] }}"
- shell: "bash -x ~/check.sh '{{ install_dir }}' > ~/check_rollback.log"
See ansible's debug output below:
changed: [10.8.44.55] => {
"changed": true,
"cmd": "bash -x ~/check.sh '/fin/app/01/scripts\\n/fin/app/01/sql' > ~/check_rollback.log",
"delta": "0:00:00.118943",
"end": "2019-09-04 10:50:16.503745",
"invocation": {
"module_args": {
"_raw_params": "bash -x ~/check.sh '/fin/app/01/scripts\\n/fin/app/01/sql' > ~/check_rollback.log",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true,
"warn": true
}
},
"rc": 0,
"start": "2019-09-04 10:50:16.384802",
"stderr": "++ echo '/fin/app/01/scripts\\n/fin/app/01/sql'\n++ sed -e 's#[\\][\\]n# #g'\n+ str='/fin/app/01/scripts\\n/fin/app/01/sql'\n+ echo '/fin/app/01/scripts\\n/fin/app/01/sql'",
"stderr_lines": [
"++ echo '/fin/app/01/scripts\\n/fin/app/01/sql'",
"++ sed -e 's#[\\][\\]n# #g'",
"+ str='/fin/app/01/scripts\\n/fin/app/01/sql'",
"+ echo '/fin/app/01/scripts\\n/fin/app/01/sql'"
],
"stdout": "",
"stdout_lines": [] }
And here is the check.row file output from ansible's run:
[user1#remotehost1 ~]$ cat check.row
/fin/app/01/scripts\\n/fin/app/01/sql
As you can instead of single whitespace it is now printing \n.
I am on the latest version of ansible.
One can replicate this issue easily. Can you please suggest why am I getting this issue and how to fix this?
First of all, you are using the shell module in which only the shell command is specified, you have incorrectly used bash in it.
shell: "bash -x ~/check.sh '{{ install_dir }}' > ~/check_rollback.log"
Secondly, as you can see your task has resulted in an error as seen in your attached output.
Stdout is empty and we can see an error in stderr.
Thirdly, If you want to use bash you can use command module, as shown below,
- command: "bash -x ~/check.sh '{{ install_dir }}' > ~/check_rollback.log"
I also suggest the following changes in your check.sh script,
#!/bin/bash
echo $1 # You can check the value that is passed to the script
str=$(echo "$1" | sed -e 's/\\n/ /g') # Use quotes around your variable
echo "$str" > check.row
And it is working fine.

How do I pass a dictionary to an ansible ad-hoc command?

If I have an ansible ad-hoc command that wants a dictionary or list valued argument, like the queries argument to postgresql_query, how do I invoke that in ansible ad-hoc commands?
Do I have to write a one-command playbook? I'm looking for a way to minimise the numbers of layers of confusing quoting (shell, yaml/json, etc) involved.
The ansible docs mention accepting structured forms for variables. So I tried the yaml and json syntax for the arguments:
ansible -m postgresql_query -sU postgres -a '{"queries":["SELECT 1", "SELECT 2"]}'
... but got ERROR! this task 'postgresql_query' has extra params, which is only allowed in the following modules: ....
the same is true if I #include a file with yaml or json contents like
cat > 'query.yml' <<'__END__'
queries:
- "SELECT 1"
- "SELECT 2"
__END__
ansible -m postgresql_query -sU postgres -a #queries.yml
You can define a dictionary in a JSON variable to pass it as parameter next:
ansible -m module_name -e '{"dict": {"key": "value"}}' -a "param={{ dict }}"
(parameters positions are arbitrary)
I have most of a solution - a way to express something like a shell script or query payload without extra quoting. But it's ugly:
ansible hostname -m postgresql_query -sU postgres -a 'query="{{query}}"' -e #/dev/stdin <<'__END__'
query: |
SELECT 'no special quotes needed' AS "multiline
identifier works fine" FROM
generate_series(1,2)
__END__
Not only is that shamefully awful, but it doesn't seem to work for lists (arrays):
ansible hostname -m postgresql_query -sU postgres -vvv -a 'query="{{query}}"' -e #/dev/stdin <<'__END__'
queries:
- |
SELECT 1
- |
SELECT 2
__END__
fails with
hostname | FAILED! => {
"changed": false,
"err": "syntax error at or near \"<\"\nLINE 1: <bound method Templar._query_lookup of <ansible.template.Tem...\n ^\n",
"invocation": {
"module_args": {
"autocommit": false,
"conninfo": "",
"queries": null,
"query": "<bound method Templar._query_lookup of <ansible.template.Templar object at 0x7f72531c61d0>>"
}
},
"msg": "Database query failed"
}
so it looks like some kind of lazy evaluation is breaking things.

Ansible fortios_config backups not working

I use Fortinet for firewall automation, but i get the error "Error reading running config" . I already followed this website: https://github.com/ansible/ansible/issues/33392
But do not find any solution. Please tell me what am I doing wrong ?
Ansible version: 2.7.0
Python version: 2.7.5
Fortinet: 60E
FortiOS version: 6.0.2
Here is what I am trying:
FortiOS.yml playbook:
---
- name: FortiOS Firewall Settings
hosts: fortiFW
connection: local
vars_files:
- /etc/ansible/vars/FortiOS_Settings_vars.yml
tasks:
- name: Backup current config
fortios_config:
host: 192.168.1.99
username: admin
password: Password#123
backup: yes
backup_path: /etc/ansible/forti_backup
Here is what I get as error:
ok: [192.168.1.99] META: ran handlers Read vars_file
'/etc/ansible/vars/FortiOS_Settings_vars.yml'
TASK [Backup current config]
**************************************************************************************************************************************************************************************************************** task path: /etc/ansible/FortiOS_Settings_test.yml:8 <192.168.1.99>
ESTABLISH LOCAL CONNECTION FOR USER: root <192.168.1.99> EXEC /bin/sh
-c 'echo ~root && sleep 0' <192.168.1.99> EXEC /bin/sh -c '( umask 77 && mkdir -p "echo
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226" && echo
ansible-tmp-1539674386.05-16470854685226="echo
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226" ) &&
sleep 0' Using module file
/usr/lib/python2.7/site-packages/ansible/modules/network/fortios/fortios_config.py
<192.168.1.99> PUT
/root/.ansible/tmp/ansible-local-6154Uq5Dmw/tmpt6JukB TO
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226/AnsiballZ_fortios_config.py
<192.168.1.99> EXEC /bin/sh -c 'chmod u+x
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226/
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226/AnsiballZ_fortios_config.py
&& sleep 0' <192.168.1.99> EXEC /bin/sh -c '/usr/bin/python
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226/AnsiballZ_fortios_config.py
&& sleep 0' <192.168.1.99> EXEC /bin/sh -c 'rm -f -r
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226/ >
/dev/null 2>&1 && sleep 0' The full traceback is: WARNING: The below
traceback may not be related to the actual failure. File
"/tmp/ansible_fortios_config_payload_b6IQmy/main.py", line 132, in
main
f.load_config(path=module.params['filter']) File "/usr/lib/python2.7/site-packages/pyFG/fortios.py", line 212, in
load_config
config_text = self.execute_command(command) File "/usr/lib/python2.7/site-packages/pyFG/fortios.py", line 154, in
execute_command
output = output + self._read_wrapper(o) File "/usr/lib/python2.7/site-packages/pyFG/fortios.py", line 120, in
_read_wrapper
return py23_compat.text_type(data)
fatal: [192.168.1.99]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"backup": true,
"backup_filename": null,
"backup_path": "/etc/ansible/forti_backup",
"config_file": null,
"file_mode": false,
"filter": "",
"host": "192.168.1.99",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"src": null,
"timeout": 60,
"username": "admin",
"vdom": null
}
},
"msg": "Error reading running config" }
When working with this module, I had the same issue. I looked into the source code of the module, and found that this error occurs when filter is set to "" -> empty string. You can get facts about the device when changing filter to something like "firewall address". But then you will only get back the options from exactly that, like if you would've typed "show firewall address" on the CLI of the device.
I'm currently working on a solution to use Ansible for FortiGate automation, but it's not looking good. E.g. FortiGates additionally do not support Netconf, so you can't use Netconf to send commands to the device.
So therefore, you're not doing anything wrong, but the modules is either not optimized, or I guessed that maybe the full-configuration is too big to be read by the module, so that you have to use the filter option to shrink it.

Resources