如何从 Ansible 字典中删除单个键?

问题描述 投票:0回答:7

我想从 Ansible 的字典中删除单个键。

例如,我想要这样:

- debug: var=dict2
  vars:
    dict:
      a: 1
      b: 2
      c: 3
    dict2: "{{ dict | filter_to_remove_key('a') }}"

打印此内容:

ok: [localhost] => {
    "dict2": {
        "b": 2,
        "c": 3
    }
}

请注意,字典是从 json 文件加载的,我将其发布到 Grafana REST API。我希望允许在文件中保存“id”密钥并在发布之前删除该密钥。

这更接近我移除的实际用途:

- name: Install Dashboards   
  uri:
    url: "{{ grafana_api_url }}/dashboards/db"
    method: POST
    headers:
      Authorization: Bearer {{ grafana_api_token }}
    body:
      overwrite: true
      dashboard:
        "{{ lookup('file', item) | from_json | removekey('id') }}"
    body_format: json   with_fileglob:
    - "dashboards/*.json"
    - "../../../dashboards/*.json"
dictionary ansible
7个回答
14
投票
- set_fact:
    dict:
      a: 1
      b: 2
      c: 3
    dict2: {}

- set_fact:
    dict2: "{{dict2 |combine({item.key: item.value})}}"
  when: "{{item.key not in ['a']}}"
  with_dict: "{{dict}}"

- debug: var=dict2

或者创建一个过滤器插件并使用它。


9
投票

您可以通过使用来完成此操作 合并省略

- set_fact:
    dict:
      a: 1
      b: 2
      c: 3

- debug:
    var: dict

- debug:
    msg: "{{ dict | combine({ 'a': omit }) }}"
TASK [test : set_fact] 
ok: [server]

TASK [test: debug] 
ok: [server] => {
    "dict": {
        "a": 1,
        "b": 2,
        "c": 3
    }
}

TASK [test : debug] 
ok: [server] => {
    "msg": {
        "b": 2,
        "c": 3
    }
}

6
投票
  - debug: var=dict2
    vars:
      dict:
        a: 1
        b: 2
        c: 3
      dict2: '{{ dict | dict2items | rejectattr("key", "eq", "a") | list | items2dict }}'
      #dict2: '{{ dict | dict2items | rejectattr("key", "match", "^(a|b)$") | list | items2dict }}'

输出:

ok: [localhost] => {
    "dict2": {
        "b": 2,
        "c": 3
    }
}

5
投票

这是一种受 John Mazzitelli 的文章启发的方法,可以内联使用,无需额外的

set_fact
任务等:

任务:

tasks:
- debug: var=dict2
  vars:
    dict:
      a: 1
      b: 2
      c: 3
    # It is important that there be NO WHITESPACE outside of `{% ... %}` and `{{ ... }}`
    # or else the var will be converted to a string.  The copy() step optionally prevents
    # modifying the original. If you don't care, then: "{% set removed=dict.pop('a') %}{{dict}}"
    dict2: "{% set copy=dict.copy() %}{% set removed=copy.pop('a') %}{{ copy }}"

输出:

TASK [debug] ***********
ok: [localhost] => {
    "dict2": {
        "b": 2,
        "c": 3
    }
}

5
投票

您可以使用 ansible.utils.remove_keys 过滤器。它将删除all嵌套层上的给定键。所以它可能并不适合所有场景:

- debug: var=dict2
  vars:
    dict:
      a: 1
      b: 2
      c: 3
    dict2: "{{ dict | ansible.utils.remove_keys(target=['a']) }}"

输出:

ok: [localhost] => 
  dict2:
    b: 2
    c: 3

如果您想删除特定图层上的特定键,您可以像这样弹出该键:

- debug: var=dict2
  vars:
    dict:
      a: 1
      b: 2
      c: 3
    dict2: |
      {% set a = dict.pop('a') %}
      {{ dict }}

更深层次嵌套的示例:

- debug: var=dict2
  vars:
    dict:
      sub_dict:
        a: 1
        b: 2
        c: 3
    dict2: |
      {% set a = dict.sub_dict.pop('a') %}
      {{ dict }}

2
投票

如果您对过滤器感兴趣(我认为这是删除字典中项目的最干净的方法),则在您的剧本所在的目录中创建

filter_plugins/dicts.py
,并填充它:

'''Custom ansible filters for dicts'''

import copy


class FilterModule(object):

    def filters(self):
        return {
            'del_by_list': self.del_by_list
        }

    def del_by_list(self, dict_to_reduce, list_of_keys):
        '''Deletes items of dict by list of keys provided'''
        dict_to_return = copy.deepcopy(dict_to_reduce)
        for item in list_of_keys:
            if item in dict_to_return:
                del dict_to_return[item]
        return dict_to_return

你可以走了:

---
- hosts: hadoop
  gather_facts: no
  tasks:

    - debug:
        msg: "{{ {123: 456, 789: 123} | del_by_list([123]) }}"

这将产生

{789: 123}


0
投票

另一种可能的解决方案,不使用过滤器,仍然只删除第一层(或可控层深度)是使用 dict2items 和 items2dict

- set_fact:
    temp:
      a: 1
      b:
        c: 2
      d:
        - 3
- debug:
    var: temp | dict2items | selectattr('key', 'ne', 'b') | items2dict

这将导致:

a: 1
d:
  - 3

使用此选择属性,您还可以定义更好的检查以删除哪些键。

© www.soinside.com 2019 - 2024. All rights reserved.