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

时间:2019-05-09 16:13:40

标签: sorting ansible jinja2

我正在构建一本Ansible剧本,我想在其中检索软件的最新版本。为此,我在Ansible中使用了“排序”过滤器。然而,当使用版本号时,这变得更加困难,版本号更复杂并且不是真正的数字,例如。 0.2.10.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中对复杂版本号进行排序的好方法吗? 任何帮助,将不胜感激。谢谢。

4 个答案:

答案 0 :(得分:1)

一种选择是写一个filter plugin

> cat filter_plugins/sort_versions.py
from distutils.version import LooseVersion


def filter_sort_versions(value):
    return sorted(value, key=LooseVersion)


class FilterModule(object):
    filter_sort = {
        'sort_versions': filter_sort_versions,
    }

    def filters(self):
        return self.filter_sort

然后在下面进行简单播放

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

答案 1 :(得分:0)

您要寻找的部分内容是version test,但是它建立在用户只想要一个比较的想法上。因此,您需要做一些胶合才能找到“最新”的胶粘剂:

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

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

答案 2 :(得分:0)

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

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

您可以按照以下步骤进行: https://docs.ansible.com/ansible/latest/user_guide/playbooks_tests.html#version-comparison

答案 3 :(得分: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 }}"