Ansible:如何基于所有主机已注册facts修改变量并全局生效?
解决方法
核心要做的就是先汇总所有主机的settings_config状态,再基于整体结果判断邮件主题,不能只依赖单台主机的fact:
1. 汇总所有主机的变更状态
新增一个仅在本地执行一次的任务,收集所有目标主机的settings_config值,判断是否存在至少一台主机有变更(即settings_config不为false):
- name: 汇总所有主机的配置变更状态 set_fact: any_host_changed: "{{ ansible_play_hosts | map('extract', hostvars, 'settings_config') | select('equalto', true) | list | length > 0 }}" delegate_to: localhost run_once: true
逻辑说明:
ansible_play_hosts:获取当前play中的所有目标主机map('extract', hostvars, 'settings_config'):提取每台主机的settings_config变量select('equalto', true):筛选出存在变更的主机(settings_config为true的主机)- 通过判断筛选结果的长度是否大于0,得到全局的变更标记
2. 基于全局状态设置邮件主题
修改原邮件主题设置任务,改用全局变更标记,同时修正原代码的拼写错误(sujectmail→subjectmail):
- name: 设置邮件主题 set_fact: subjectmail: "{{ 'Ansible email Summary Status:green' if not any_host_changed else 'Ansible email Report Status: red!' }}" delegate_to: localhost run_once: true
3. 修正报告和邮件任务的变量引用
确保task10和task11使用正确的全局变量,同时修正原代码的文件路径变量错误(config_check_report_file→settings_report_file):
- name: task10 生成基础设施HTML报告 template: src: "{{ settings_report_template }}" dest: "{{ settings_report_file }}" delegate_to: localhost run_once: true check_mode: no - name: task11 发送邮件报告 mail: host: "{{ mail_gateway }}" port: "{{ mail_gateway_port }}" sender: "{{ mail_sender }}" subtype: html to: "{{ mail_recipients }}" subject: "{{ subjectmail }}" body: "{{ lookup('file', settings_report_file) }}" secure: starttls register: mail_output delegate_to: localhost run_once: true check_mode: no
完整修改后的代码
# 此处放置原有的task01、task02等任务(需注册task01、task02的changed状态) - name: Task05: 标记单主机无变更状态 set_fact: settings_config: false when: task01.changed == false and task02.changed == false # 新增的全局状态汇总任务 - name: 汇总所有主机的配置变更状态 set_fact: any_host_changed: "{{ ansible_play_hosts | map('extract', hostvars, 'settings_config') | select('equalto', true) | list | length > 0 }}" delegate_to: localhost run_once: true - name: 设置邮件主题 set_fact: subjectmail: "{{ 'Ansible email Summary Status:green' if not any_host_changed else 'Ansible email Report Status: red!' }}" delegate_to: localhost run_once: true - name: task10 生成基础设施HTML报告 template: src: "{{ settings_report_template }}" dest: "{{ settings_report_file }}" delegate_to: localhost run_once: true check_mode: no - name: task11 发送邮件报告 mail: host: "{{ mail_gateway }}" port: "{{ mail_gateway_port }}" sender: "{{ mail_sender }}" subtype: html to: "{{ mail_recipients }}" subject: "{{ subjectmail }}" body: "{{ lookup('file', settings_report_file) }}" secure: starttls register: mail_output delegate_to: localhost run_once: true check_mode: no
关键说明
- 原
settings_config是单主机标记,仅代表当前主机是否无变更;新增的any_host_changed是全局标记,覆盖所有主机的变更状态 - 所有全局变量的设置任务都添加了
delegate_to: localhost和run_once: true,确保只执行一次,生成统一的全局结果 - 同步修正了原代码中的变量拼写错误和文件路径不匹配问题
内容的提问来源于stack exchange,提问作者Erickson
相关产品推荐
相关产品推荐

