获取起始字典



我在Ansible中使用Jinja模板有一个问题。我有这个嵌套字典:

"fruits": {
"summer": {
"june": {
"fruit": {
"cherry": "cherry"
},
"vars": {}
},
"july": {
"fruit": {
"peach": "peach"
},
"vars": {}
},
"august": {
"fruit": {
"watermelon": "watermelon",
"strawberry": "strawberry"
},
"vars": {}
}
}}

,我想删除对象"peach"。我试过pop方法,它工作,但我想使用过滤器rejecattr

我试着:

tasks:
- set_fact:
test: |
{%- for x,y in fruits.items() -%}
{%- for j,k in y.items() -%}
{{ k.fruit | dict2items | rejectattr ('key', 'eq', 'peach') | items2dict }}
{%- endfor -%}
{%- endfor -%}`

它给了我以下内容:

"test": "{
"cherry": "cherry"}
{}
{"watermelon": "watermelon", "strawberry": "strawberry"}"

但是我想要得到开始的结构,less "peach"对象。

任何建议吗?谢谢你

Ansible对于修改深度嵌套的数据结构(或者一般来说修改数据结构)来说不是一个很好的工具。虽然我确信有人会带着一个聪明的json_query过滤器或其他东西来,但通过编写一个自定义过滤器插件来解决这个问题是微不足道的。如果我们在filter_plugins/badfruit.py中输入以下内容:

def filter_badfruit(v, *exclude):
for months in v.values():
for data in months.values():
data["fruit"] = {k: v for k, v in data["fruit"].items() if k not in exclude}
return v

class FilterModule(object):
filter_map = {"badfruit": filter_badfruit}
def filters(self):
return self.filter_map

那么我们可以这样写剧本:

- hosts: localhost
gather_facts: false
vars:
"fruits": {
"summer": {
"june": {
"fruit": {
"cherry": "cherry"
},
"vars": {}
},
"july": {
"fruit": {
"peach": "peach"
},
"vars": {}
},
"august": {
"fruit": {
"watermelon": "watermelon",
"strawberry": "strawberry"
},
"vars": {}
}
}}
tasks:
- debug:
var: >-
fruits|badfruit('peach')

得到如下输出:

PLAY [localhost] ***************************************************************
TASK [debug] *******************************************************************
ok: [localhost] => {
"fruits|badfruit('peach')": {
"summer": {
"august": {
"fruit": {
"strawberry": "strawberry",
"watermelon": "watermelon"
},
"vars": {}
},
"july": {
"fruit": {},
"vars": {}
},
"june": {
"fruit": {
"cherry": "cherry"
},
"vars": {}
}
}
}
}
PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

过滤器的编写使得我们可以提供多个键来排除:

- debug:
var: >-
fruits|badfruit('peach', 'strawberry')

Q:"我想使用过滤器rejecattr .">

A:代码中的rejecattr行可以原样使用。组合字典

test_str: |
summer:
{% for i in fruits.summer|dict2items %}
{{ i.key }}:
{{ i.value|combine({'fruit': i.value.fruit|dict2items|rejectattr('key', 'eq', 'peach')|items2dict}) }}
{% endfor %}
test: "{{ test_str|from_yaml }}"

给出预期结果

test:
summer:
august:
fruit:
strawberry: strawberry
watermelon: watermelon
vars: {}
july:
fruit: {}
vars: {}
june:
fruit:
cherry: cherry
vars: {}

可选,将排除的项放入字典中,例如

exclude:
fruit: ['peach']

走在树上。变量test也将展开为预期的结果

test_str: |
{% for season,sa in fruits.items() %}
{{ season }}:
{% for month,ma in sa.items() %}
{{ month }}:
{% for a,b in ma.items() %}
{{ a }}:
{
{% for k,v in b.items() %}
{% if k not in exclude[a] %}
{{ k }}: {{ v }},
{% endif %}
{% endfor %}
}
{% endfor %}
{% endfor %}
{% endfor %}
test: "{{ test_str|from_yaml }}"

相关内容

  • 没有找到相关文章

最新更新