I have a rather strange problem with an Ansible playbook.
This bug only occurs in my Docker container with Debian:9.9-slim and I've tried with different Docker distributions but it doesn't change the problem.
The errors I'm showing you may have line inconsistencies. This is because I have commented on a whole part of my playbook and I am showing you the playbook without the comments for reasons of professional secrecy.
So, my application is a flask-restplus API that launches playbooks via ansible-runner. In this case, ansible provides a dictionary called "device" via extravars:
{
"admin_password": "password",
"admin_user": "admin",
"dns1_server_ip": "0.0.0.0",
"equipement_name": "DEVICE_NAME",
"hostname": "ANSIBLE_BUG",
"ip": "0.0.0.0",
"port": 80
}
This is my playbook:
- hosts: localhost
connection: local
any_errors_fatal: no
tasks:
- debug:
msg: '{{ device }}'
- debug:
msg: '{{ device["ip"] }}'
I've also try this way:
- hosts: localhost
connection: local
any_errors_fatal: no
tasks:
- debug:
msg: '{{ device }}'
- debug:
msg: '{{ device.ip }}'
And I've this error:
deploy okay [WARNING]: Unable to parse /etc/ansible/hosts as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note
that the implicit localhost does not match 'all'
PLAY [localhost] ***************************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": {
"admin_password": "",
"admin_user": "admin",
"dns1_server_ip": "8.8.8.8",
"equipement_name": "UTM-POULAIN-INET",
"hostname": "POULAIN",
"ip": "212.234.67.114",
"port": 22
}
}
TASK [debug] *******************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'str object' has no attribute 'ip'\n\nThe error appears to have been in '/bfm-app/ansible_svc/app/core/ansible/staging/mff/main.yml': line 60, column 9, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n
- debug:\n ^ here\n"}
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=1
Someone on an other post suggest me to use "from_json" like this:
- debug:
msg: '{{ device | from_json }}'
- debug:
msg: '{{ (device | from_json)["ip"] }}'
And i've got a new error:
deploy okay [WARNING]: Unable to parse /etc/ansible/hosts as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note
that the implicit localhost does not match 'all'
PLAY [localhost] ***************************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [debug] *******************************************************************
fatal: [localhost]: FAILED! => {"msg": "the field 'args' has an invalid value ({'msg': '{{ device | from_json }}'}), and could not be converted to an dict.The error was: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)\n\nThe error appears to have been in '/bfm-app/ansible_svc/app/core/ansible/staging/mff/main.yml': line 56, column 9, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n # #=============================#\n - debug:\n ^ here\n"}
PLAY RECAP *********************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=1
I tried commenting on the first msg debug, but I have the same error.
So I've been trying to iterate on device:
- debug:
msg: '{{ item }}'
with_dict: "{{ device }}"
And it's work:
deploy okay [WARNING]: Unable to parse /etc/ansible/hosts as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note
that the implicit localhost does not match 'all'
PLAY [localhost] ***************************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [debug] *******************************************************************
ok: [localhost] => (item={'value': 'ANSIBLE_BUG', 'key': 'hostname'}) => {
"msg": {
"key": "hostname",
"value": "ANSIBLE_BUG"
}
}
ok: [localhost] => (item={'value': '0.0.0.0', 'key': 'dns1_server_ip'}) => {
"msg": {
"key": "dns1_server_ip",
"value": "0.0.0.0"
}
}
ok: [localhost] => (item={'value': 'password', 'key': 'admin_password'}) => {
"msg": {
"key": "admin_password",
"value": "password"
}
}
ok: [localhost] => (item={'value': 80, 'key': 'port'}) => {
"msg": {
"key": "port",
"value": 80
}
}
ok: [localhost] => (item={'value': 'user', 'key': 'admin_user'}) => {
"msg": {
"key": "admin_user",
"value": "user"
}
}
ok: [localhost] => (item={'value': '0.0.0.0', 'key': 'ip'}) => {
"msg": {
"key": "ip",
"value": "0.0.0.0"
}
}
ok: [localhost] => (item={'value': 'DEVICE_NAME', 'key': 'equipement_name'}) => {
"msg": {
"key": "equipement_name",
"value": "DEVICE_NAME"
}
}
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0
I conclude device is therefore a dictionary.
But I wanted to make sure, so I created a variable to which I assign "device":
- set_fact:
device_dict: '{{ device }}'
- debug:
msg: '{{ device_dict }}'
- debug:
msg: '{{ device_dict["ip"] }}'
And it's work:
deploy okay [WARNING]: Unable to parse /etc/ansible/hosts as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note
that the implicit localhost does not match 'all'
PLAY [localhost] ***************************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [set_fact] ****************************************************************
ok: [localhost]
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": {
"admin_password": "password",
"admin_user": "admin",
"dns1_server_ip": "0.0.0.0",
"equipement_name": "DEVICE_NAME",
"hostname": "ANSIBLE_BUG",
"ip": "0.0.0.0",
"port": 80
}
}
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": "0.0.0.0"
}
PLAY RECAP *********************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0
PLAY RECAP *********************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0
As a reminder, this playbook is used in a Docker container. Except if I run it on the host machine running Debian 9, my initial playbook works perfectly.
I could use the last solution exposed above, but this would make me modify a large number of playbooks containing even a large number of tasks, so I will only do this as a last resort.
If you have any questions don't hesitate :)
Do you have any idea what the problem might be?