如何使用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获取完整列表,但对于每个foobar,我只需要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: >可以创建自定义过滤器插件,并使用它来选择最新版本。例如

max

$ 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过滤树中每个文件的最新版本?的主要内容,如果未能解决你的问题,请参考以下文章

sh 使用git和pip将ansible升级到最新版本

ansible-2.9.6 最新版本离线安装

sh 使用apt-get将ansible更新到最新版本

在 Fedora 中获取最新的 Ansible 2.8 | Linux 中国

ansible的playbook进行yum批量安装nginx最新版本

ansible中过滤器的介绍以及如何自定义过滤器