我想在使用带有with_items的set_fact时将键添加到字典中。这是一个小POC,它将帮助我完成其他一些工作。我试图概括POC,以便从中删除所有不相关的细节。
当我执行下面的代码时,它会显示一个字典,其中只有一个键对应于with_items的最后一项。它似乎正在重新创建一个新字典,或者可能会覆盖with_items中每个项目的现有字典。我想要一本包含所有键的字典。
代码:
---
- hosts: localhost
connection: local
vars:
some_value: 12345
dict: {}
tasks:
- set_fact: {
dict: "{
{{ item }}: {{ some_value }}
}"
}
with_items:
- 1
- 2
- 3
- debug: msg="{{ dict }}"
答案 0 :(得分:23)
这也可以在不使用Ansible 2.2中测试的插件的情况下完成。
---
- hosts: localhost
connection: local
vars:
some_value: 12345
dict: {}
tasks:
- set_fact:
dict: "{{ dict | combine( { item: some_value } ) }}"
with_items:
- 1
- 2
- 3
- debug: msg="{{ dict }}"
或者,这可以在没有包含文件的复杂单线程的情况下编写。
tasks:
- include: append_dict.yml
with_items: [1, 2, 3]
append_dict.yml:
- name: "Append dict: define helper variable"
set_fact:
_append_dict: "{ '{{ item }}': {{ some_value }} }"
- name: "Append dict: execute append"
set_fact:
dict: "{{ dict | combine( _append_dict ) }}"
输出:
TASK [debug]
*******************************************************************
ok: [localhost] => {
"msg": {
"1": "12345",
"2": "12345",
"3": "12345"
}
}
'
周围的单引号{{ some_value }}
是明确存储字符串值所必需的。
此语法也可用于通过引用dict
和with_dict
使用item.key
从item.value
元素追加。
可以在同一步骤中执行添加前缀和后缀或哈希的操作,例如
set_fact:
dict: "{{ dict | combine( { item.key + key_postfix: item.value + '_' + item.value | hash('md5') } ) }}"
答案 1 :(得分:6)
首先,在您的ansible base目录中创建一个名为filter_plugins/makedict.py
的新文件。
现在创建一个名为“makedict”(或任何你想要的)的新函数,它接受一个值和一个列表并返回一个新的字典,其中键是列表的元素,值总是相同的。
class FilterModule(object):
def filters(self):
return { 'makedict': lambda _val, _list: { k: _val for k in _list } }
现在,您可以使用剧本中的新过滤器来实现所需的结果:
- hosts: 127.0.0.1
connection: local
vars:
my_value: 12345
my_keys: [1, 2, 3]
tasks:
- set_fact: my_dict="{{ my_value | makedict(my_keys) }}"
- debug: msg="{{ item.key }}={{ item.value }}"
with_dict: "{{my_dict}}"
您可以使用filter_plugins
中的ansible.cfg
选项customize the location过滤插件。
答案 2 :(得分:1)
这似乎不再适用于ansible 2.5
---
- hosts: localhost
connection: local
vars:
some_value: 12345
dict: {}
tasks:
- set_fact:
dict: "{{ dict | combine( { item: some_value } ) }}"
with_items:
- 1
- 2
- 3
- debug: msg="{{ dict }}"
仅返回上一个值{"dict":{"3": "some value"}}
我建议你这样做:
- set_fact:
__dict: |
{% for item in [1,2,3] %}
{{item}}: "value"
{% endfor %}
- set_fact:
final_dict: "{{__dict|from_yaml}}"
- debug:
var: final_dict
答案 3 :(得分:0)
另一个解决方案可能是在Ansible 2.9.6中测试过的解决方案。
此解决方案带来了额外的好处,您不必事先在_dict
部分中声明vars
。这是通过| default({})
管道实现的,该管道确保_dict
为空时循环不会在第一次迭代中失败。
此外,由于dict
是为_dict
保留的特殊关键字,因此必须将dict
重命名为<class 'dict'>
。已被引用(不幸的是,仅在devel分支)here。
---
- hosts: localhost
connection: local
vars:
some_value: 12345
tasks:
- set_fact:
_dict: "{{ _dict | default({}) | combine( { item: some_value } ) }}"
with_items:
- 1
- 2
- 3
- debug: msg="{{ _dict }}"