我正在构建一个 Ansible 剧本,我想在其中检索软件的最新版本。为此,我在 Ansible 中使用了“排序”过滤器。然而,当使用版本号时,这变得有点困难,版本号更复杂并且不是真正的数字,例如
0.2.1
,0.10.1
。
这就是我现在正在做的事情:
- name: Set version to compare
set_fact:
versions:
- "0.1.0"
- "0.1.5"
- "0.11.11"
- "0.9.11"
- "0.9.3"
- "0.10.2"
- "0.6.1"
- "0.6.0"
- "0.11.0"
- "0.6.5"
- name: Sorted list
debug:
msg: "{{ versions | sort }}"
- name: Show the latest element
debug:
msg: "{{ versions | sort | last }}"
只要版本号保持在数字 10 以下(例如 0.9.3,但不是 0.10.2),上面的剧本就可以工作。
显示问题:
TASK [Set version to compare] ***************************************************************************************************************
ok: [localhost]
TASK [Sorted list] **************************************************************************************************************************
ok: [localhost] => {
"msg": [
"0.1.0",
"0.1.5",
"0.10.2",
"0.11.0",
"0.11.11",
"0.6.0",
"0.6.1",
"0.6.5",
"0.9.11",
"0.9.3"
]
}
TASK [Show the latest element] **************************************************************************************************************
ok: [localhost] => {
"msg": "0.9.3"
}
在此示例中,所需值为
0.11.11
有人知道在 Ansible 中对复杂版本号进行排序的好方法吗? 任何帮助,将不胜感激。谢谢。
一个选择是编写一个过滤器插件。例如,
shell> cat filter_plugins/sort_versions.py
from distutils.version import LooseVersion
def sort_versions(value):
return sorted(value, key=LooseVersion)
class FilterModule(object):
def filters(self):
return {
'sort_versions': sort_versions,
}
然后是下面的任务
- debug:
msg: "{{ versions|sort_versions }}"
给予
msg:
- 0.1.0
- 0.1.5
- 0.6.0
- 0.6.1
- 0.6.5
- 0.9.3
- 0.9.11
- 0.10.2
- 0.11.0
- 0.11.11
如果您可以安装集合community.general,则无需编写过滤器。使用过滤器community.general.version_sort。然后,下面的任务给出相同的结果
- debug:
msg: "{{ versions|community.general.version_sort }}"
用于测试的完整剧本示例
- hosts: all
vars:
versions:
- '0.1.0'
- '0.1.5'
- '0.11.11'
- '0.9.11'
- '0.9.3'
- '0.10.2'
- '0.6.1'
- '0.6.0'
- '0.11.0'
- '0.6.5'
tasks:
- debug:
msg: "{{ versions|sort_versions }}"
- debug:
msg: "{{ versions|community.general.version_sort }}"
您可以使用Jinja2比较版本而不是安装过滤器插件
- name: test
set_fact:
max_number: "{{ item }}"
when: max_number |default('0') is version(item, '<')
loop: "{{ master_version }}"
只需按照 Playbook 测试比较版本。
version
测试,但是,它建立在用户只想进行一个比较的想法之上。因此,您需要做一些粘合才能找到“最新”的:
- set_fact:
max_version: >-
{%- set vmax = {} -%}
{%- for v_1 in versions -%}
{%- for v_2 in versions -%}
{%- if v_1 is version(v_2, ">") and v_1 is version(vmax.get("max", "0.0.0"), ">") -%}
{%- set _ = vmax.update({"max": v_1}) -%}
{%- endif -%}
{%- endfor -%}
{%- endfor -%}
{{ vmax.max }}
(我不假装这是最佳解决方案,因为它很可能多次比较版本,但对于小版本列表应该可以正常工作)
我有一个类似的用例,我有一个版本,需要从版本列表中获取以前的版本。
---
- name: previous_version_filter
hosts: localhost
gather_facts: false
vars:
versions:
- "21.7.1"
- "21.13.0"
- "21.7.2"
- "21.13.1"
- "21.8.0"
- "21.7.0"
version: "21.13.0"
newer_versions: []
tasks:
- name: Create newer_versions list
set_fact:
newer_versions: "{{ newer_versions + [item] }}"
when: item is version(version, '>')
loop: "{{ versions }}"
- name: Create previous_versions list
set_fact:
previous_versions: "{{ versions | difference(newer_versions) | difference([ version ]) }}"
- name: Obtain previous_version
set_fact:
previous_version: "{{ item }}"
when: previous_version | default('0') is version(item, '<')
loop: "{{ previous_versions }}"
- debug:
msg: "{{ previous_version }}"