【问题标题】:Match a key to value from a dict and replace a value matching another dictionary using ansible将键与字典中的值匹配,并使用 ansible 替换与另一个字典匹配的值
【发布时间】:2021-04-23 14:24:22
【问题描述】:

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

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”时遇到问题。

【问题讨论】:

    标签: list dictionary ansible json-query


    【解决方案1】:

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

        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
    

    【讨论】:

    • 谢谢,我尝试了这个解决方案,它几乎开箱即用,结果更干净:)
    【解决方案2】:

    简而言之,以下剧本:

    ---
    - 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 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-08-17
      • 2018-01-02
      • 2021-06-24
      • 1970-01-01
      • 1970-01-01
      • 2017-08-05
      • 1970-01-01
      相关资源
      最近更新 更多