我正在构建一个 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),上面的 playbook 就可以工作,因为排序像字符串一样执行。当版本号必须排序时,例如 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 中对版本号进行排序的好方法?
答:使用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
仅当更新变量为 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
这里的所有答案都提供了一种自定义的版本排序方式,我想指出的是,股票 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
当前接受的答案提供了一个非常好的解决方案,使用 filter_plugin
.不幸的是,使用的distutils
Python包似乎已被弃用。一些谷歌搜索将我带到了打包包,它提供了一个类似的版本类。这是一个不使用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
}
它对我们来说效果很好,但我不想保证在每种情况下的行为都会完全相同。