如何基于多条件为Ansible变量定义多种取值场景
Ansible动态设置patch_plan变量的解决方案
看起来你想要在Ansible的变量文件中,根据外部传入的role和environment变量,动态生成patch_plan的值——核心是给patch_plan_week_and_day匹配对应的场景值。变量文件本身不支持直接用when条件,不过我们有几种优雅的实现方式,完全能满足你的需求(包括14种场景的维护)。
首先先明确你的基础变量和需求:
你当前的变量定义是:
patch_plan: 'foo-{{ patch_plan_week_and_day }}-bar'
需要匹配的核心场景示例:
- 当
role = 'master'且environment = 'srvb'→patch_plan_week_and_day = 'Week1_Monday' - 当
role != 'master'且environment = 'srvb'→patch_plan_week_and_day = 'Week1_Tuesday' - 当
role = 'slave'且environment = 'pro'→patch_plan_week_and_day = 'Week3_Wednesday'
你期望的类when逻辑写法虽然在纯变量文件里不能直接用,但我们可以用以下几种方式实现:
方案1:字典映射(推荐,适合多场景维护)
这种方式把所有场景映射到一个字典里,然后用Jinja2条件逻辑去匹配,可读性和维护性都很强,尤其适合14种场景的情况:
# 第一步:定义所有场景的映射字典,键可以自定义,清晰即可 patch_plan_scenarios: master_srvb: 'Week1_Monday' non_master_srvb: 'Week1_Tuesday' slave_pro: 'Week3_Wednesday' # 在这里继续添加剩下的11种场景,比如: # worker_pro: 'Week2_Thursday' # master_pro: 'Week1_Sunday' # ... # 第二步:动态计算patch_plan_week_and_day的值 patch_plan_week_and_day: >- {% if role == 'master' and environment == 'srvb' %} {{ patch_plan_scenarios.master_srvb }} {% elif environment == 'srvb' and role != 'master' %} {{ patch_plan_scenarios.non_master_srvb }} {% elif role == 'slave' and environment == 'pro' %} {{ patch_plan_scenarios.slave_pro }} {% else %} # 可以设置一个默认值,比如空字符串或者通用值 'Default_Plan' {% endif %} # 最终生成的patch_plan patch_plan: 'foo-{{ patch_plan_week_and_day }}-bar'
如果很多场景是基于environment+role的组合,还可以优化字典的键为"{role}_{environment}",简化条件判断:
patch_plan_scenarios: master_srvb: 'Week1_Monday' slave_srvb: 'Week1_Tuesday' worker_srvb: 'Week1_Tuesday' slave_pro: 'Week3_Wednesday' # 剩余场景... patch_plan_week_and_day: >- {% set combo_key = f"{role}_{environment}" %} {% if combo_key in patch_plan_scenarios %} {{ patch_plan_scenarios[combo_key] }} {% elif environment == 'srvb' and role != 'master' %} {{ patch_plan_scenarios.slave_srvb }} # 统一匹配非master的srvb场景 {% else %} 'Default_Plan' {% endif %} patch_plan: 'foo-{{ patch_plan_week_and_day }}-bar'
方案2:在Playbook中用set_fact(接近你期望的when写法)
如果你更习惯用when条件的写法,可以在Playbook里通过set_fact模块来逐个设置变量,这种方式逻辑直观,和你想要的代码结构几乎一致:
- name: Configure patch plan based on role and environment hosts: your_target_hosts vars: # 基础变量定义 patch_plan: 'foo-{{ patch_plan_week_and_day }}-bar' tasks: - name: Set patch plan for master+srvb set_fact: patch_plan_week_and_day: 'Week1_Monday' when: role == 'master' and environment == 'srvb' - name: Set patch plan for non-master+srvb set_fact: patch_plan_week_and_day: 'Week1_Tuesday' when: role != 'master' and environment == 'srvb' - name: Set patch plan for slave+pro set_fact: patch_plan_week_and_day: 'Week3_Wednesday' when: role == 'slave' and environment == 'pro' # 继续添加剩下的11个场景的set_fact任务... - name: Print final patch plan debug: msg: "Final patch plan: {{ patch_plan }}"
如果14个场景写起来繁琐,还可以把场景数据整理成列表,用循环来处理:
- name: Configure patch plan with loop hosts: your_target_hosts vars: patch_plan: 'foo-{{ patch_plan_week_and_day }}-bar' patch_plan_scenarios: - value: 'Week1_Monday' condition: "role == 'master' and environment == 'srvb'" - value: 'Week1_Tuesday' condition: "role != 'master' and environment == 'srvb'" - value: 'Week3_Wednesday' condition: "role == 'slave' and environment == 'pro'" # 剩余场景... tasks: - name: Set patch plan from scenarios set_fact: patch_plan_week_and_day: "{{ item.value }}" when: item.condition | bool loop: "{{ patch_plan_scenarios }}" - name: Print final patch plan debug: msg: "Final patch plan: {{ patch_plan }}"
方案3:单行Jinja2条件表达式(简洁但适合少场景)
如果场景较少,也可以直接用单行的Jinja2条件表达式写在变量里,不过当场景到14种时,可读性会下降:
patch_plan_week_and_day: >- {{ 'Week1_Monday' if role == 'master' and environment == 'srvb' else 'Week1_Tuesday' if role != 'master' and environment == 'srvb' else 'Week3_Wednesday' if role == 'slave' and environment == 'pro' else 'Default_Plan' }} patch_plan: 'foo-{{ patch_plan_week_and_day }}-bar'
综合来看,方案1的字典映射是最适合你的,因为14种场景需要良好的可维护性,字典+条件逻辑的组合既能清晰管理所有场景,又能在变量文件中直接完成动态赋值。
内容的提问来源于stack exchange,提问作者GBT55
相关产品推荐
相关产品推荐

