【发布时间】:2021-11-12 18:53:00
【问题描述】:
Ansible 已经完成了“事实收集”,hostvars 中的每个主机都已经设置了 ansible_memory_mb.real.total。
如何选择数量高于平均水平的主机?一定有一个 Jinja 过滤单线,我想不通...
【问题讨论】:
标签: ansible jinja2 json-query
Ansible 已经完成了“事实收集”,hostvars 中的每个主机都已经设置了 ansible_memory_mb.real.total。
如何选择数量高于平均水平的主机?一定有一个 Jinja 过滤单线,我想不通...
【问题讨论】:
标签: ansible jinja2 json-query
例如,提取你想要的变量
mems: "{{ ansible_play_hosts|
map('extract', hostvars, 'ansible_memfree_mb')|
list }}"
mems:
- 99
- 84
- 86
注意:要提取ansible_memory_mb.real.total试试
mems: "{{ ansible_play_hosts|
map('extract', hostvars, ['ansible_memmory_mb','real','total'])|
list }}"
并创建字典
hosts_mems: "{{ dict(ansible_play_hosts|zip(mems)) }}"
hosts_mems:
host01: 99
host02: 84
host03: 86
计算平均值
mems_average: "{{ hosts_mems.values()|sum / hosts_mems.values()|length }}"
mems_average: '89.66666666666667'
并选择内存大于平均水平的主机
hosts_mems_high: "{{ hosts_mems|dict2items|
selectattr('value', 'gt', mems_average|int)|items2dict }}"
hosts_mems_high:
host01: 99
如果您想要“Jinja 过滤单线”,即如果您想减少变量的数量,请随意替换。
【讨论】:
hostvars | json_query(......)?
这就是我最终如何做到的。不完全是 one-liner - 我需要先计算平均 RAM,我所做的非常像 @Vladimir-Botka 在他的回答中建议的那样。
我的方法避免了dict2items 和zip,但是,在我看来,这使它更胜一筹:
- name: Figure out, if there is a business server with spare RAM
set_fact:
spareserver: >-
{{ (groups.business |
map('extract', hostvars) |
selectattr('ansible_memory_mb.real.total', 'gt', avgram | float) |
first).ansible_hostname }}
vars:
ramsizes: >-
{{ groups.business |
map('extract', hostvars, [
'ansible_memory_mb', 'real', 'total'
]) |
list }}
avgram: '{{ (ramsizes | sum) / (ramsizes | length) }}'
观察:
float 要么是一个错误,要么是一个非常烦人的“功能”。 avgram 的值是算术表达式的结果——为什么临时任务变量记录为 string,必须再次强制返回 float?还可能损失精度?hostvars 申请了两次map('extract') -- 我不喜欢这样,但我不知道如何避免 -- 欢迎提出建议。json_query 不起作用。下面没有产生任何错误 - 但spareserver 是空。- set_fact:
spareserver: >-
{{ hostvars | json_query('[?ansible_memory_mb.real.total > `{{ avgram }}`]') }}
【讨论】: