我想在这里实现的目标如下
下面提到的是我使用过的 Ansible 角色:
- 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(我可以这样做)。目录结构如下:
shell> tree tmp
tmp
├── file1
├── file2
└── file3
shell> tree opt
opt
├── bar
│ └── file2
├── baz
│ └── file3
└── foo
└── file1
在这里,如果我使用下面的代码,其中我手动提到了文件名,那么它就可以工作。但是,我不想这样做
- 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 中的文件名完全相同
如果我理解正确,这里有一种可能的方法来处理您正在尝试做的事情。在下面的示例中,我取消了未归档的作业,因为它不在关键路径上。
我创建了两个示例目录。前两个任务只是为了进一步向您展示这个测试结构:
archive
包含随机目录4个文件的目录。其中之一不在目标中code
包含多个文件随机目录的目录。3 个文件与archive
.第一个find
任务与您的任务相同,并使用archive
目录中所有文件的详细信息注册结果。
对于目录中的第二个find
任务code
,关键点是patterns
将第一次搜索中的基本名称列表作为参数传递,您可以使用表达式获取该列表:
{{ search_archive.files | map(attribute='path') | map('basename') | list }}
我们可以将其详细描述为:files
从我们的存档find
结果中获取列表,仅提取path
属性,对每个列表元素应用basename
过滤器并返回一个列表。
对于最后一个任务,我使用了copy
模块. 我的示例在 localhost 上运行,但由于您的示例可能会在远程目标上运行,因此remote_src
必须设置它(或者将从控制器获取文件)。
循环是在上一个任务的结果上完成的,所以我们只得到代码目录中的匹配文件为dest
. 为了选择src
,我们使用以下表达式在存档文件夹中查找相应的文件:
{{ search_archive.files | map(attribute='path') | select('match', '^.*/' + item | basename + '$') | first }}
选择过滤器select
将match
测试应用于列表中的每个路径,仅选择以当前代码路径基名结尾的元素。该first
过滤器只得到第一个(只在您的案件)匹配的元素。loop_control.label
用于获得更好的任务结果输出。
前两个任务仅用于调试/演示目的。
---
- 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
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句