简体   繁体   English

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

[英]How to sort complex version numbers in Ansible

I'm building an Ansible playbook in which I want to retrieve the latest version of a software.我正在构建一个 Ansible 剧本,我想在其中检索最新版本的软件。 For this I used "sort" filter in Ansible.为此,我在 Ansible 中使用了“排序”过滤器。 That, however, becomes a bit harder, when using version numbers, that are more complex and are not really numbers, eg 0.2.1<\/code> , 0.10.1<\/code> .然而,当使用更复杂且不是真正数字的版本号时,这变得有点困难,例如0.2.1<\/code> 、 0.10.1<\/code> 。

This is what I'm doing right now:这就是我现在正在做的事情:

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

An option would be to write a 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

Then the simple play below那么下面的简单玩法

- debug:
    msg: "{{ versions | sort_versions }}"

gives:给出:

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

You can use Jinja2 compare version instead of installing a filter plugin您可以使用 Jinja2 比较版本而不是安装过滤器插件

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

Part of what you are looking for is the version test , however, it is built on the idea that a user just wants one comparison.您正在寻找的部分内容是version测试,但是,它建立在用户只想要一个比较的想法之上。 So, you'll need to do some glue to find the "latest" one:所以,你需要做一些胶水来找到“最新”的:

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

(I don't pretend that's the optimal solution, as it is very likely comparing versions against each other more than once, but it should work fine for small version lists) (我不会假装这是最佳解决方案,因为它很可能会多次比较版本,但它应该适用于小版本列表)

I had a similar use case where I had a version and needed to obtain the previous version from a list of versions.我有一个类似的用例,我有一个版本,需要从版本列表中获取以前的版本。

---

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM