Ansible - 使用注册的变量值查找 [英] Ansible - Find using registered variable value

查看:22
本文介绍了Ansible - 使用注册的变量值查找的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在这里实现的目标如下

What I am trying to achieve here is as below

  1. 从 tar.gz 解压缩代码 - 工作
  2. 在未归档的目录中查找文件名 - 工作
  3. 根据第 2 步中获取的文件名在代码目录中查找文件名 - 失败
  4. 从源复制文件:(第 2 步)目标:(第 3 步)- 如果我在第 3 步的模式部分使用硬编码的文件名,则工作

下面提到的是我用过的 Ansible 角色:

Below mentioned is the Ansible role I have used:

- name: Unarchive config files to server
  unarchive:
    src: "{{ config_dir }}/config.tar.gz"
    dest: /tmp
    list_files: yes
  register: tar_path

- name: Find file names in unarchived config files
  find:
    paths: "{{ tar_path.dest }}"
    file_type: file
    recurse: yes
  register: tmp_file_path

- name: Find file names in code base
  find:
    paths: /opt
    file_type: file
    recurse: yes
    patterns:
      #Search for file names with the values in tmp_file_path
  register: code_file_path

- set_fact:
    code_files: "{{ code_files|default([]) +
                    [{'path': item, 'name': item|basename}] }}"
  loop: "{{ code_file_path.files|map(attribute='path')|list }}"

- name: copy files
  command: cp "{{ item.0 }}" "{{ item.1.path }}"
  with_together:
    - "{{ tmp_file_path.files|map(attribute='path')|list|sort }}"
    - "{{ code_files|sort(attribute='name') }}"

在这里,我需要使用 find 根据模式(文件名)在/opt 目录中定位文件,正是我在/tmp 中未归档的文件

最后,根据文件名和路径将文件从/tmp 替换为/opt(我可以这样做).目录结构如下:

And finally, replace files from /tmp to /opt based on the file names and paths(This I am able to do). The directory structure is as follows:

shell> tree tmp
tmp
├── file1
├── file2
└── file3

shell> tree opt
opt
├── bar
│   └── file2
├── baz
│   └── file3
└── foo
    └── file1

在这里,如果我使用下面的代码,其中我手动提到了文件名,那么它就可以工作.但是,我不想这样做

Here if I use the below code wherein I manually mention the file names, then it works. However, I don't want to do that

- name: Find file names in code base
  find:
    paths: /opt
    file_type: file
    recurse: yes
    patterns:
      - file1
      - file2
      - file3
  register: code_file_path

我需要一个解决方案来替换模式的硬编码:file1、file2 和 file3,并使用一些变量来做到这一点.我需要替换的/tmp 和/opt 中的文件名完全相同

I need a solution to replace the hardcoding for patterns: file1, file2 and file3 and use some variable to do that. The file names in /tmp and /opt where I need to replace is exactly the same

推荐答案

如果我理解正确,这里有一种可能的方法来处理您正在尝试做的事情.在下面的示例中,我删除了未归档作业,因为它不在关键路径上.

If I understood correctly, here is a possible way to handle what you're trying to do. In the below example, I took away the unarchive job as it's not on the critical path.

  • 我创建了两个示例目录.前两个任务只是为了进一步向您展示这个测试结构:

  • I created two sample directories. The first two tasks are only there to further show you this test structure:

  1. 一个 archive 目录,包含随机目录中的 4 个文件.其中之一不存在于目标中
  2. 一个 code 目录,包含几个文件随机目录.3 个文件与 archive 中的其他文件具有相同的基本名称.
  1. an archive directory containing 4 files in random directories. One of them is not present in the target
  2. a code directory containing several files random directories. 3 files have the same basenames as other files found in archive.

  • 第一个 find 任务与您的相同,并注册一个结果,其中包含 archive 目录中所有文件的详细信息.

  • The first find task is identical to yours and registers a result with details of all files in the archive dir.

    对于 code 目录中的第二个 find 任务,关键是将基本名称列表作为 patterns 参数传递从您可以使用表达式获得的第一次搜索:

    For the second find task in the code directory, the key point is to pass as patterns parameter the list of basenames from the first search which you can get with the expression:

    {{ search_archive.files | map(attribute='path') | map('basename') | list }}
    

    我们可以将其详细描述为:从我们的存档 find 结果中获取 files 列表,仅提取 path 属性,应用 basename 过滤器 对每个列表元素和返回一个列表.

    We can detail this one as: get files list from our archive find result, extract only the path attribute, apply the basename filter on each list element and return a list.

    对于最后一个任务,我使用了copy 模块.我的示例在 localhost 上运行,但由于您的示例可能会在远程目标上运行,因此必须设置 remote_src(否则将从控制器获取文件).

    For the last task, I used the copy module. My example runs on localhost but since yours will probably run on a remote target, the remote_src has to be set (or files will be fetched from the controller).

    循环是在上一个任务的结果上完成的,所以我们只得到代码目录中的匹配文件为dest.为了选择src,我们在存档文件夹中查找对应的文件,表达式如下:

    The loop is done on the result of the previous task so we only get the matching files in code directory as dest. To select the src, we look for corresponding files in the archive folder with the following expression:

    {{ search_archive.files | map(attribute='path') | select('match', '^.*/' + item | basename + '$') | first }}
    

    选择过滤器select 正在应用 match 测试 到列表中的每个路径,仅选择以当前代码路径基名结尾的元素.first 过滤器只获得第一个(并且仅在您的情况下)匹配元素.loop_control.label用于获得更好的任务结果输出.

    The select filter select is applying the match test to each path in the list selecting only the elements ending with the current code path basename. The first filter get only the first (and only in your case) matching element. loop_control.label is used to get a better output of task result.

    前两个任务仅用于调试/演示目的.

    The first two task are only for debugging/demo purpose.

    ---
    - name: Update files from package in code wherever they are
      hosts: localhost
      gather_facts: false
    
      tasks:
    
        - name: Capture sample data structure
          command: tree archive code
          register: structure
          changed_when: false
    
        - name: Show sample data structure
          debug:
            msg: "{{ structure.stdout_lines}}"
    
        - name: Find files in archive
          find:
            paths: archive
            file_type: file
            recurse: yes
          register: search_archive
    
        - name: Find files in code matching names in archive
          find:
            paths: code
            file_type: file
            recurse: yes
            patterns:  >-
              {{
                search_archive.files |
                map(attribute='path') |
                map('basename') |
                list
              }}
          register: search_code
    
        - name: Copy files from archive to code
          vars:
            archive_source: >-
              {{
                search_archive.files |
                map(attribute='path') |
                select('match', '^.*/' + item | basename + '$') |
                first
              }}
          copy:
            remote_src: yes
            src: "{{ archive_source }}"
            dest: "{{ item }}"
          loop: "{{ search_code.files | map(attribute='path') | list }}"
          loop_control:
            label:
              Source: "{{ archive_source }}"
              Destination: "{{ item }}"
    

    结果

    PLAY [Update files from package in code wherever they are] *****************************************************************************************************************************************************************************
    
    TASK [Capture sample data structure] ***************************************************************************************************************************************************************************************************
    ok: [localhost]
    
    TASK [Show sample data structure] ******************************************************************************************************************************************************************************************************
    ok: [localhost] => {
        "msg": [
            "archive",
            "├── a_dir",
            "│   └── file2",
            "├── file1.txt",
            "├── file3",
            "└── other_dir",
            "    └── bla",
            "        └── fileX",
            "code",
            "├── dir1",
            "│   └── file1.txt",
            "├── dir2",
            "│   ├── file2",
            "│   ├── pipo",
            "│   └── toto",
            "└── dir3",
            "    └── subdir",
            "        └── file3",
            "",
            "7 directories, 9 files"
        ]
    }
    
    TASK [Find files in archive] ***********************************************************************************************************************************************************************************************************
    ok: [localhost]
    
    TASK [Find files in code matching names in archive] ************************************************************************************************************************************************************************************
    ok: [localhost]
    
    TASK [Copy files from archive to code] *************************************************************************************************************************************************************************************************
    changed: [localhost] => (item={'Source': 'archive/file1.txt', 'Destination': 'code/dir1/file1.txt'})
    changed: [localhost] => (item={'Source': 'archive/a_dir/file2', 'Destination': 'code/dir2/file2'})
    changed: [localhost] => (item={'Source': 'archive/file3', 'Destination': 'code/dir3/subdir/file3'})
    
    PLAY RECAP *****************************************************************************************************************************************************************************************************************************
    localhost                  : ok=5    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    

    这篇关于Ansible - 使用注册的变量值查找的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆