如何在 Ansible 中对复杂版本号进行排序

问题描述 投票:0回答:4

我正在构建一个 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 中对复杂版本号进行排序的好方法吗? 任何帮助,将不胜感激。谢谢。

sorting ansible jinja2
4个回答
5
投票

一个选择是编写一个过滤器插件。例如,

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 }}"

3
投票

您可以使用Jinja2比较版本而不是安装过滤器插件

- name: test
  set_fact:
    max_number: "{{ item }}"
  when: max_number |default('0') is version(item, '<')
  loop: "{{ master_version }}"

只需按照 Playbook 测试比较版本


0
投票

您正在寻找的部分内容是

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 }}

(我不假装这是最佳解决方案,因为它很可能多次比较版本,但对于小版本列表应该可以正常工作)


0
投票

我有一个类似的用例,我有一个版本,需要从版本列表中获取以前的版本。

---

- 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 }}"
© www.soinside.com 2019 - 2024. All rights reserved.