如何在Ansible中按当前主机筛选字典并循环遍历?
问题:灵活遍历Ansible字典,仅处理当前主机相关的证书配置
我需要一种灵活的方式遍历Ansible字典certmgmt_keys_on_srv,要求仅当当前主机名存在于字典的srv列表中时,循环获取对应的证书配置项(包括字典的key、当前主机项、mykey、mycert等值),后续用于向当前服务器加载证书文件。尝试用with_subelements实现但未得到预期结果,寻求技术帮助。
我的字典配置
certmgmt_keys_on_srv: aap.tstglobal.tst.loc: srv: - t28419.tst.loc - t28420.tst.loc - t28421.tst.loc mykey: /etc/tower/tower.key mycert: /etc/tower/tower.cert notify: activate_aap_cert aap2.tstglobal.tst.loc: srv: - t38419.tst.loc - t38420.tst.loc - t38421.tst.loc mykey: /etc/tower/tower3.key mycert: /etc/tower/tower2.cert notify: activate_aap_cert
我尝试的代码
- name: Display my cert_names and file_names to renew ansible.builtin.debug: msg: "Cert_Name: {{ item }}" with_subelements: - "{{ certmgmt_keys_on_srv | community.general.json_query('*') }}" - srv - skip_missing: yes
执行结果
TASK [Display my cert_names and file_names to renew] ************************************************************************************************************************************ ok: [t28419.tst.loc] => (item=[{'key': '/etc/tower/tower.key', 'cert': '/etc/tower/tower.cert', 'notify': 'activate_aap_cert'}, 't28419.tst.loc']) => { "msg": "Cert_Name: [{'key': '/etc/tower/tower.key', 'cert': '/etc/tower/tower.cert', 'notify': 'activate_aap_cert'}, 't28419.tst.loc']" } ok: [t28419.tst.loc] => (item=[{'key': '/etc/tower/tower.key', 'cert': '/etc/tower/tower.cert', 'notify': 'activate_aap_cert'}, 't28420.tst.loc']) => { "msg": "Cert_Name: [{'key': '/etc/tower/tower.key', 'cert': '/etc/tower/tower.cert', 'notify': 'activate_aap_cert'}, 't28420.tst.loc']" } ok: [t28419.tst.loc] => (item=[{'key': '/etc/tower/tower.key', 'cert': '/etc/tower/tower.cert', 'notify': 'activate_aap_cert'}, 't28421.tst.loc']) => { "msg": "Cert_Name: [{'key': '/etc/tower/tower.key', 'cert': '/etc/tower/tower.cert', 'notify': 'activate_aap_cert'}, 't28421.tst.loc']" }
解决方案
当前with_subelements会遍历所有srv列表项,未过滤当前主机。以下两种方法可实现需求:
方法1:dict2items+when条件过滤
先将字典转换为键值对格式,再通过when筛选出包含当前主机的配置项:
- name: 处理当前主机对应的证书配置 ansible.builtin.debug: msg: | 证书名称: {{ item.key }} 当前主机: {{ inventory_hostname }} 密钥路径: {{ item.value.mykey }} 证书路径: {{ item.value.mycert }} loop: "{{ certmgmt_keys_on_srv | dict2items }}" when: inventory_hostname in item.value.srv
方法2:json_query直接筛选
通过json_query一次性过滤出符合条件的配置项,无需额外条件判断:
- name: 处理当前主机对应的证书配置 ansible.builtin.debug: msg: | 证书名称: {{ item.key }} 当前主机: {{ inventory_hostname }} 密钥路径: {{ item.value.mykey }} 证书路径: {{ item.value.mycert }} loop: "{{ certmgmt_keys_on_srv | dict2items | json_query('[?value.srv.contains(@, `' ~ inventory_hostname ~ '`)]') }}"
说明
- 两种方法均只会处理当前主机所在
srv列表的证书配置,避免无效遍历。 - 后续加载证书时,可直接使用
item.value.mykey、item.value.mycert获取路径,还可通过notify: {{ item.value.notify }}触发对应的handler。
内容的提问来源于stack exchange,提问作者Isabella
相关产品推荐
相关产品推荐

