Ansible:能否在when条件中使用循环内动态变化的两个变量?
问题
想在Ansible的when条件中测试循环内动态变化的两个值:
disksizefromjson:从JSON文件提取的变量(移除when条件时可正常赋值)item['Size']:通过前序PowerShell任务提取的变量
编写的Playbook如下:
--- - name: get disk info on windows vm ansible.windows.win_powershell: script: | Get-ciminstance win32_volume -Filter DriveType=3 | where-object{$_.Label -notlike "*Reserved*" -and $_.SystemVolume -ne $true} | Select-Object Name, Label, FileSystem, BlockSize, @{'Name'='Size'; 'Expression'={[math]::Ceiling($_.Capacity / 1GB)}}, @{'Name'='Freespace'; 'Expression'={[math]::Ceiling($_.Freespace / 1GB)}}, @{'Name'='Free'; 'Expression'={[math]::Ceiling(($_.Freespace * 100)/$_.Capacity)}} | Sort-Object Name register: diskNewVm - name: test disk size set_fact: disksizefromjson: "{{ diskinfosfromjson | from_json | selectattr('Name', 'equalto', item['Name']) | map(attribute='Size') | first | default(10) }}" when: item['Size'] > disksizefromjson loop: "{{ diskNewVm.output }}"
执行时出现错误:
The conditional check 'item['Size'] > disksizefromjson' failed. The error was: error while evaluating conditional (item['Size'] > disksizefromjson): 'disksizefromjson' is undefined
移除when条件后,disksizefromjson可正常定义,询问是否可以在when条件中使用这两个变量?
解答
问题核心是**when条件的执行时机早于set_fact的变量赋值**。
Ansible的任务逻辑里,when条件会在任务执行(包括set_fact赋值)之前先评估。你当前写法中,disksizefromjson是在这个set_fact任务里才定义的,第一次循环评估when条件时,变量还不存在,因此抛出"undefined"错误。
要实现需求,必须在when条件评估前拿到当前item对应的disksizefromjson值,不能依赖后续set_fact的赋值,以下是两种可行方案:
方案1:直接在when中计算对比值
把set_fact里的计算逻辑直接嵌入when条件,确保评估条件时能拿到当前item对应的JSON中Size值:
- name: test disk size set_fact: disksizefromjson: "{{ diskinfosfromjson | from_json | selectattr('Name', 'equalto', item['Name']) | map(attribute='Size') | first | default(10) }}" when: item['Size'] > (diskinfosfromjson | from_json | selectattr('Name', 'equalto', item['Name']) | map(attribute='Size') | first | default(10)) loop: "{{ diskNewVm.output }}"
方案2:预计算所有磁盘的对比数据
先将JSON中的磁盘信息转换成字典,后续循环可直接通过磁盘名快速取值,避免重复解析过滤,性能更优:
- name: 预转换JSON磁盘信息为字典 set_fact: disk_info_dict: "{{ (diskinfosfromjson | from_json) | items2dict(key_name='Name', value_name='Size') }}" - name: test disk size set_fact: disksizefromjson: "{{ disk_info_dict[item['Name']] | default(10) }}" when: item['Size'] > (disk_info_dict[item['Name']] | default(10)) loop: "{{ diskNewVm.output }}"
两种方案都能实现when条件中动态对比两个值的需求,方案2更适合磁盘数量较多的场景。
内容的提问来源于stack exchange,提问作者Yoann Lesueur
相关产品推荐
相关产品推荐

