将键与字典中的值匹配,并使用 ansible 替换与另一个字典匹配的值
Match a key to value from a dict and replace a value matching another dictionary using ansible
我有一本包含以下项目的字典。
PID:
Cisco:
- A9K-MOD80-TR
- A9K-RSP440-TR
- ASR9001-LC
- SFP-10G-SR
上面的字典我想用下面的逻辑与下面的列表匹配,如果“SFP-10G-SR”(或任何其他值存在)存在于下面的任何part_id中,然后将 'Manufacturer' 替换为 Cisco(在这种情况下,Cisco 是字典 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”时遇到问题。
简而言之,以下剧本:
---
- 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
你的方法是正确的,尽管它可能看起来很丑陋和奇怪。让我们简化数据,例如
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
我有一本包含以下项目的字典。
PID:
Cisco:
- A9K-MOD80-TR
- A9K-RSP440-TR
- ASR9001-LC
- SFP-10G-SR
上面的字典我想用下面的逻辑与下面的列表匹配,如果“SFP-10G-SR”(或任何其他值存在)存在于下面的任何part_id中,然后将 'Manufacturer' 替换为 Cisco(在这种情况下,Cisco 是字典 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”时遇到问题。
简而言之,以下剧本:
---
- 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
你的方法是正确的,尽管它可能看起来很丑陋和奇怪。让我们简化数据,例如
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