簡體   English   中英

如何對Ansible中的版本號進行排序

[英]How to sort version numbers in Ansible

我正在構建一個 Ansible 劇本,我想在其中備份數據庫,以防我需要升級軟件。 為此,我想將可用的最高版本號與已安裝的版本號進行比較。 如果最新版本高於安裝的版本,我將備份數據庫。

然而,問題是我找不到在 Ansible 中對版本號進行排序的好方法。標准排序過濾器對字符串而不是數字/版本進行排序。

這就是我現在正在做的事情:

- name: Get package version
  yum:
    list: package
  register: software_version

- name: Read which version is installed and available
  set_fact:
    software_version_installed: "{{ software_version | json_query(\"results[?yumstate=='installed'].version\") | sort | last }}"
    software_version_available: "{{ software_version | json_query(\"results[?yumstate=='available'].version\") | sort | last }}"

- name: Backup old database file on remote host
  copy:
    src: "{{ software.database_path }}"
    dest: "{{ software.database_path }}_{{ ansible_date_time.date }}_v{{ software_version_installed }}"
    remote_src: yes
  when: software_version_installed is version(software_version_available, "<")

只要版本號保持在數字 10 以下(例如 1.2.3,而不是 1.10.1),上面的劇本就可以工作,因為排序就像字符串一樣執行。 當版本號需要排序時,例如 1.2.3 和 1.10.1,它將以 1.2.3 作為最新版本。

顯示問題:

- name: Read which version is installed and available
  set_fact:
    software_versions: [ "2.5.0", "2.9.0", "2.10.0", "2.11.0" ]

- name: Debug
  debug:
    var: software_versions | sort

TASK [grafana : Debug]**********************************
ok: [localhost] => {
    "software_versions | sort": [
        "2.10.0",
        "2.11.0",
        "2.5.0",
        "2.9.0"
    ]
}

有誰知道在 Ansible 中對版本號進行排序的好方法嗎?

問:有誰知道在 Ansible 中排序版本號的好方法嗎?

A:使用filter_plugin。 例如過濾器

shell> cat filter_plugins/version_sort.py
from distutils.version import LooseVersion

def version_sort(l):
    return sorted(l, key=LooseVersion)

class FilterModule(object):

    def filters(self):
        return {
            'version_sort' : version_sort
            }

與劇本

shell> cat test-versions.yml
- name: Sort versions
  hosts: localhost

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

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

為方便起見,該過濾器可在 Github ansible-plugins 獲得


版本比較可以迭代列表並比較項目。 看下面的例子

shell> cat test-versions.yml
- hosts: localhost
    vars:
      version_installed: "1.10.1"
      versions:
        - "1.1.3"
        - "1.2.3"
        - "1.7.5"
        - "1.10.7"
    tasks:
      - debug: msg="{{ item }} is newer than {{ version_installed }}"
        loop: "{{ versions }}"
        when: item is version(version_installed, '>')
shell> ansible-playbook test-versions.yml | grep msg
"msg": "1.10.7 is newer than 1.10.1"

現在用另一種方式解決了。 我沒有對版本進行排序,而是將當前版本與所有可用版本進行了比較。

  • 我首先將更新變量設置為 false
  • 接下來我將安裝的版本與每個可用版本進行了比較
  • 如果已安裝版本 > 當前版本,請將更新變量設置為 true

執行備份的任務只會在更新變量為真時執行。

- name: Get package version
  yum:
    list: package
  register: software_version

- name: Read which version is installed and available
  set_fact:
    software_update: false
    software_version_installed: "{{ software_version | json_query(\"results[?yumstate=='installed'].version\") | last }}"
    software_version_available: "{{ software_version | json_query(\"results[?yumstate=='available'].version\") }}"

- name: Check if upgrade is needed
  set_fact:
    software_update: true
  when: software_version_installed is version(item, "<")
  with_items: "{{ software_version_available }}"

- name: Backup old database file on remote host
  copy:
    src: "{{ software.database_path }}"
    dest: "{{ software.database_path }}_{{ ansible_date_time.date }}_v{{ software_version_installed }}"
    remote_src: yes
  when: software_update

當前接受的答案提供了一個非常好的解決方案,使用filter_plugin 不幸的是,使用的distutils Python package 似乎已被棄用。 一些谷歌搜索讓我找到了包裝package,它提供了一個類似的版本 class。這是一個不使用distutils的更新的filter_plugin

from packaging.version import Version

def version_sort(l):
    return sorted(l, key=Version)

class FilterModule(object):

    def filters(self):
        return {
            'version_sort': version_sort
        }

它對我們來說工作得很好,但我不想 promise 在每種情況下行為都完全相同。

這里的所有答案都提供了一種自定義的版本排序方式,我想指出庫存 ansible 已經可以做到這一點

- name: Sort list by version number
  debug:
    var: ansible_versions | community.general.version_sort
  vars:
    ansible_versions:
      - '2.8.0'
      - '2.11.0'
      - '2.7.0'
      - '2.10.0'
      - '2.9.0'

https://docs.ansible.com/ansible/latest/collections/community/general/docsite/filter_guide_working_with_versions.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM