将键与字典中的值匹配,并使用 ansible 替换匹配另一个字典的值

时间:2021-04-23 14:24:22

标签: list dictionary ansible json-query

我有一本包含以下项目的字典。

PID:
  Cisco:
    - A9K-MOD80-TR
    - A9K-RSP440-TR
    - ASR9001-LC
    - SFP-10G-SR

上面的字典我想用下面的逻辑与下面的列表匹配,如果下面的任何part_id中存在“SFP-10G-SR”(或任何其他值),则将“制造商”替换为Cisco(在这种情况下 Cisco 是 dict PID 中的键)。

ok: [localhost] => (item={'hostname': '-', 'device_id': 287, 'serial': '-', 'Name': '-', 'Manufacturer': '', 'part_id': 'ASR9001-LC'})
ok: [localhost] => (item={'hostname': '-', 'device_id': 287, 'serial': '-', 'Name': '-', 'Manufacturer': '', 'part_id': 'SFP-10G-SR'})

我以某种方式设法让它工作,但它很难看,而且下面的代码格式很奇怪。

  - name: test
    set_fact:
      new_merged_list: "{{new_merged_list}} {{ item|combine({'Manufacturer': PID|dict2items|json_query(query)}) }}"
    loop: "{{ merged_list | flatten(levels=1) }}"
    vars:
      query: "[?contains(value, '{{item.part_id }}')].key"

  - debug:
      msg: "{{ new_merged_list }}"

它给了我以下输出

{
    "msg": " 
    {'hostname': '-', 'device_id': 287, 'serial': '-', 'Name': '-', 'Manufacturer': ['Cisco'], 'part_id': 'ASR9001-LC'} 
    {'hostname': '-', 'device_id': 287, 'serial': '-', 'Name': '-', 'Manufacturer': ['Cisco'], 'part_id': 'SFP-10G-SR'} 
}

如果我在“new_merged_list”上运行调试,我会收到以下消息

"msg": "AnsibleUnsafeText"

我想要的是将上述内容保留为字典,任何人都可以提供更好的解决方案或协助将其转换回字典吗?在当前状态下,我在使用“new_merged_list”时遇到问题。

2 个答案:

答案 0 :(得分:0)

简而言之,以下剧本:

---
- hosts: localhost
  gather_facts: false

  vars:
    PID:
      Cisco:
        - A9K-MOD80-TR
        - A9K-RSP440-TR
        - ASR9001-LC
        - SFP-10G-SR
      toto:
        - bla
        - ble
        - bli

    model_brand: >-
      {{
        PID
        | dict2items(key_name='brand', value_name='model_list')
        | selectattr('model_list', 'contains', model | default('none'))
        | map(attribute='brand')
        | default(['Unkown brand'], true)
        | first
      }}

  tasks:
    - name: Show brand for known models (pass as extra param -e model='test')
      debug:
        msg: "Model {{ model | default('none')}} is of brand {{ model_brand }}"

给予

$ ansible-playbook playbook.yml 

PLAY [localhost] ***********************************************************************************************************************************************************************************************************************

TASK [Show brand for known models (pass as extra param -e model='test')] ***************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "Model none is of brand Unkown brand"
}

PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   



$ ansible-playbook playbook.yml -e brand='ASR9001-LC'

PLAY [localhost] ***********************************************************************************************************************************************************************************************************************

TASK [Show brand for known models (pass as extra param -e model='test')] ***************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "Model none is of brand Unkown brand"
}

PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   



$ ansible-playbook playbook.yml -e model='ASR9001-LC'

PLAY [localhost] ***********************************************************************************************************************************************************************************************************************

TASK [Show brand for known models (pass as extra param -e model='test')] ***************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "Model ASR9001-LC is of brand Cisco"
}

PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   



$ ansible-playbook playbook.yml -e model='ble'

PLAY [localhost] ***********************************************************************************************************************************************************************************************************************

TASK [Show brand for known models (pass as extra param -e model='test')] ***************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "Model ble is of brand toto"
}

PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

答案 1 :(得分:0)

您的方法是正确的,尽管它可能看起来很丑陋和奇怪。让我们简化数据,例如

    PID:
      Cisco: [A, B]
      HP: [C, D]
    merged_list:
        - {Manufacturer: '', part_id: A}
        - {Manufacturer: '', part_id: D}

您的代码只需稍作修改

    - set_fact:
        new_merged_list: "{{ new_merged_list|default([]) +
                             [item|combine({'Manufacturer': manufacturer})] }}"
      loop: "{{ merged_list }}"
      vars:
        _dict: "{{ PID|dict2items }}"
        query: "[?contains(value, '{{ item.part_id }}')].key"
        manufacturer: "{{ _dict|json_query(query)|first }}"

给出新列表

  new_merged_list:
  - Manufacturer: Cisco
    part_id: A
  - Manufacturer: HP
    part_id: D