问题
I know this question has been asked many times before but I must be missing something here!
This is a minimal playbook to reproduce the issue.
Here is the playbook:
---
- hosts:
- localhost
gather_facts: false
vars:
zones_hash:
location1:
id: 1
control_prefix: '10.1.254'
data_prefix: '10.1.100'
location2:
id: 2
control_prefix: '10.2.254'
data_prefix: '10.2.100'
tasks:
- name: "test1"
debug: var="zones_hash"
- name: "test2"
debug: var="item"
with_dict:
- "{{ zones_hash }}"
Here is the output:
$ ansible --version
ansible 2.3.1.0
config file = /home/configs/_ansible/ansible.cfg
configured module search path = Default w/o overrides
python version = 2.7.5 (default, Nov 6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
$ ansible-playbook playbook.yml
PLAY [localhost] *******************************************************************************
TASK [test1] ***********************************************************************************
ok: [localhost] => {
"zones_hash": {
"location1": {
"control_prefix": "10.1.254",
"data_prefix": "10.1.100",
"id": 1
},
"location2": {
"control_prefix": "10.2.254",
"data_prefix": "10.2.100",
"id": 2
}
}
}
TASK [test2] ***********************************************************************************
fatal: [localhost]: FAILED! => {"failed": true, "msg": "with_dict expects a dict"}
PLAY RECAP *************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=1
I would expect the item variable printed in task2 to contain (for example):
key: location1
value: {
id: 1
control_prefix: '10.1.254'
data_prefix: '10.1.100'
}
What are we missing?
回答1:
Looks like Ansible's documentation needs updated or you've found a bug. http://docs.ansible.com/ansible/latest/playbooks_loops.html#looping-over-hashes uses your with_dict
syntax but it seems like that doesn't work anymore. The dictionary needs to be on the same line as with_dict
.
- name: "test2"
debug: var="item"
with_dict: "{{ zones_hash }}"
回答2:
with_dict:
- "{{ zones_hash }}"
declares a list with a dict as the first index, and Ansible rightfully complains since it expects a dict.
The solution kfreezy mentioned works since it actually gives a dictionary to with_dict
and not a list:
with_dict: "{{ zones_hash }}"
回答3:
This question is already answered, however I have solved my problem another way. It might be helpful for others.
Name of the dictionary could be a problem also. I named my dictionary name hdfs_dirs
, and I was seeing with_dict expects a dict
error. Apparently the same name is defined in the common vars and using the same name is not okay.
When I changed the dictionary name to hdfs_paths
, it worked.
Double check the name of your dictionary also.:)
回答4:
The issue you are facing is more about YAML syntax!
Actually, a dash/hyphen indicates that what follows is an item of a list. So when you write - "{{ zones_hash }}"
, you have a 'list of dict' (with only one item) and not a 'dict'.
To provide your 'dict', here is what you need to write:
with_dict:
"{{ zones_hash }}"
Either on one or two lines, it's the absence of the dash that matters (not like it has been said in an other answer here).
When you start with Ansible and you are not familiar with YAML, it's not always easy to understand when you need to start your declaration with a dash/hyphen. You have some explanation oriented on that topic here on StackOverflow.
Another good trick to help you to understand and visualize the difference is to convert your YAML code in JSON. Here is a tool to do that:
- https://www.json2yaml.com/
来源:https://stackoverflow.com/questions/45377692/ansible-with-dict-expects-a-dict