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

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

问题描述

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

What I am trying to achieve here is as below

  1. 取消归档tar.gz中的代码-工作
  2. 在未归档目录中查找文件名-工作中
  3. 根据步骤2中获取的文件名在代码目录中查找文件名-失败
  4. 从源:(第2步)目标:(第3步)复制文件-如果在第3步的模式部分中使用硬编码的文件名,则可以正常工作
  1. Unarchive the code from tar.gz - working
  2. Find file names in unarchived directory - working
  3. Find file names in code directory based on file names fetched in step 2 - failed
  4. Copy files from source:(Step 2) destination:(Step3) - working if I use the hardcoded file names in the pattern section of step 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来根据我在/tmp中未存档的pattern(filename)精确定位到/opt目录中的文件

最后,根据文件名和路径将/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属性,应用

    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 正在应用<对列表中选择的每个路径进行href ="https://docs.ansible.com/ansible/latest/user_guide/playbooks_tests.html#testing-strings" rel ="nofollow noreferrer"> 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天全站免登陆