如何使用Ansible过滤树中每个文件的最新版本?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用Ansible过滤树中每个文件的最新版本?相关的知识,希望对你有一定的参考价值。
我有一个带有各种文件的中型目录树:
- / some / place / distfiles / foo-1.2.jar
- / some / place / distfiles / subdir / foo-1.3.jar
- / some / place / distfiles / bar-1.1.jar
- / some / place / distfiles / bar-1.1.2.jar
我使用find-module获取完整列表,但对于每个foo和bar,我只需要latest版本。例如,以上设置需要减少为:
- / some / place / distfiles / subdir / foo-1.3.jar
- / some / place / distfiles / bar-1.1.2.jar
不,我不能依赖文件的时间戳-仅依赖文件名的数字部分...
有人可以建议一种优雅的方式吗?
答案
这将是不平凡的jinja2,因此您可能更愿意编写自定义模块,从而可以使用实际的编程语言进行工作(您仍然可以使用find:
和register:
来捕获文件名列表,然后将其提供给您的自定义模块,以根据您的规则汇总每个文件的“最新”)
也就是说,在将项目从其基础名称拆分为version
test到其版本号后,我想version
可用于查找最新的项目:
tuple[str, str]
另一答案
首先为此目的转换数据。例如
- find:
paths:
- /some/place/distfiles
# etc
register: my_jars
- set_fact:
versions_by_filename: >-
{%- set results = {} -%}
{%- for f in my_jars.files -%}
{%- set bn = f.path | basename
| regex_replace(ver_regex, '\\1') -%}
{%- set v = f.path | regex_replace(ver_regex, '\\2') -%}
{%- set _ = results.setdefault(bn, []).append(v) -%}
{%- endfor -%}
{{ results }}
vars:
ver_regex: '(.*)-([0-9.-]+)\.jar'
- set_fact:
most_recent: >-
{%- set results = {} -%}
{%- for fn, ver_list in versions_by_filename.items() -%}
{%- set tmp = namespace(latest=ver_list[0]) -%}
{%- for v in ver_list -%}
{%- if tmp.latest is version(v, '<') -%}
{%- set tmp.latest = v -%}
{%- endif -%}
{%- endfor -%}
{%- set _ = results.update({fn: tmp.latest}) -%}
{%- endfor -%}
{{ results }}
给予
- set_fact:
my_files: "{{ result.files|json_query('[].path') }}"
- debug:
var: my_files
创建词典列表
my_files:
- /some/place/distfiles/foo-1.2.jar
- /some/place/distfiles/bar-1.1.jar
- /some/place/distfiles/bar-1.1.2.jar
- /some/place/distfiles/subdir/foo-1.3.jar
给予
- set_fact:
my_dict: "{{ my_dict
|default([]) + [
dict(['path', 'archive', 'version']
|zip([item,
(item|basename).split('-')[0],
(item|basename).split('-')[1]|splitext|list|first])) ] }}"
loop: "{{ my_files }}"
- debug:
var: my_dict
按归档名称对项目进行分组
my_dict:
- archive: foo
path: /some/place/distfiles/foo-1.2.jar
version: '1.2'
- archive: bar
path: /some/place/distfiles/bar-1.1.jar
version: '1.1'
- archive: bar
path: /some/place/distfiles/bar-1.1.2.jar
version: 1.1.2
- archive: foo
path: /some/place/distfiles/subdir/foo-1.3.jar
version: '1.3'
给予
- set_fact:
my_groups: "{{ my_dict|groupby('archive') }}"
- debug:
var: my_groups
准备好数据后,找到最新版本并打印结果
my_groups:
- - bar
- - archive: bar
path: /some/place/distfiles/bar-1.1.jar
version: '1.1'
- archive: bar
path: /some/place/distfiles/bar-1.1.2.jar
version: 1.1.2
- - foo
- - archive: foo
path: /some/place/distfiles/foo-1.2.jar
version: '1.2'
- archive: foo
path: /some/place/distfiles/subdir/foo-1.3.jar
version: '1.3'
给予
- debug:
msg: "Latest version of {{ item.0 }} is {{ item.1|json_query(query)|first }}"
vars:
query: "[?version == '{{ latest_version }}'].path"
latest_version: "{{ item.1|json_query('[].version')|max }}"
loop: "{{ my_groups }}"
笔记
- 过滤器
msg: Latest version of bar is /some/place/distfiles/bar-1.1.2.jar msg: Latest version of foo is /some/place/distfiles/subdir/foo-1.3.jar
的问题
Credit @mdaniel: >可以创建自定义过滤器插件,并使用它来选择最新版本。例如
$ cat filter_plugins/version_filters.py
from distutils.version import LooseVersion
def version_max(l):
return sorted(l, key=LooseVersion)[-1]
class FilterModule(object):
def filters(self):
return {
'version_max' : version_max
}
- 剧本期望文件名具有格式
latest_version: "{{ item.1|json_query('[].version')|version_max }}"
以上是关于如何使用Ansible过滤树中每个文件的最新版本?的主要内容,如果未能解决你的问题,请参考以下文章
在 Fedora 中获取最新的 Ansible 2.8 | Linux 中国