如何在不覆盖上一个变量的情况下包含具有相同名称include_vars变量



我有这个,我们称之为include.yaml

#- name: "Playing with Ansible and Include files"
- hosts: localhost
connection: local 
tasks:
- find: paths="./" recurse=yes patterns="test.yaml"
register: file_to_exclude
- debug: var=file_to_exclude.stdout_lines        
- name: shell
shell: "find "$(pwd)" -name 'test.yaml'"
register: files_from_dirs     
- debug: var=files_from_dirs.stdout_lines
- name: Include variable files
include_vars: "{{ item }}"
with_items:
- "{{ files_from_dirs.stdout_lines }}"
- debug: var=files 

和 2 个或更多测试文件

./dir1/test.yaml

包含

files: 
- file1 
- file2
./dir2/test.yaml

包含

files: 
- file3 
- file4

结果是

TASK [Include variable files] ******************************************************************************************
ok: [localhost] => (item=/mnt/c/Users/GFlorinescu/ansible_scripts/ansible/1st/test.yaml)
ok: [localhost] => (item=/mnt/c/Users/GFlorinescu/ansible_scripts/ansible/2nd/test.yaml)
TASK [debug] ***********************************************************************************************************
ok: [localhost] => {
"files": [
"file3",
"file4"
]
}

如何获取文件中的所有值,目前最后一个文件中最后一个包含files变量覆盖了以前文件中的files?当然,无需更改文件中的变量名称test.yaml

换句话说,我希望文件是:

ok: [localhost] => {
"files": [
"file1",
"file2",
"file3",
"file4"
]
}

更具体地说,我要求任何类型的解决方案或模块,甚至不是官方或某些 github 模块,我不想要特定的include_vars模块解决方案。

将包含的变量放入具有唯一名称的字典中。例如,从循环的索引创建名称。然后,迭代名称并连接列表

- command: "find {{ playbook_dir }} -name test.yaml"
register: files_from_dirs
- include_vars:
file: "{{ item }}"
name: "{{ name }}"
loop: "{{ files_from_dirs.stdout_lines }}"
loop_control:
extended: true
vars:
name: "files_{{ ansible_loop.index }}"
- set_fact:
files: "{{ files|d([]) + lookup('vars', item).files }}"
with_varnames: "files_[0-9]+"
- debug:
var: files

files:
- file1
- file2
- file3
- file4

笔记:

  • 您必须提供相对于主目录的路径或绝对路径。请参阅下面的示例
- command: "echo $PWD"
register: out
- debug:
var: out.stdout

out.stdout: /home/admin

例如,当您想要查找相对于剧本目录的文件时

- command: "find {{ playbook_dir }} -name test.yaml"
register: files_from_dirs     
- debug:
var: files_from_dirs.stdout_lines

files_from_dirs.stdout_lines:
- /export/scratch/tmp8/test-987/dir1/test.yaml
- /export/scratch/tmp8/test-987/dir2/test.yaml
  • 这同样适用于模块查找。例如
- find:
paths: "{{ playbook_dir }}"
recurse: true
patterns: test.yaml
register: files_from_dirs
- debug:
var: files_from_dirs.files|map(attribute='path')|list

给出相同的结果

files_from_dirs.files|map(attribute='path')|list:
- /export/scratch/tmp8/test-987/dir1/test.yaml
- /export/scratch/tmp8/test-987/dir2/test.yaml
  • 简化代码并将文件的声明放入变量中。例如,下面的声明给出相同的结果
files: "{{ query('varnames', 'files_[0-9]+')|
map('extract', hostvars.localhost, 'files')|
flatten }}"

用于测试的完整行动手册示例

- hosts: localhost
vars:
files: "{{ query('varnames', 'files_[0-9]+')|
map('extract', hostvars.localhost, 'files')|
flatten }}"
tasks:
- find:
paths: "{{ playbook_dir }}"
recurse: true
patterns: test.yaml
register: files_from_dirs
- include_vars:
file: "{{ item }}"
name: "{{ name }}"
loop: "{{ files_from_dirs.files|map(attribute='path')|list }}"
loop_control:
extended: true
vars:
name: "files_{{ ansible_loop.index }}"
- debug:
var: files

(也许跑题了,见评论)

问:">有没有办法写出发现它的路径?

答:是的。请参阅下面的自我解释示例。鉴于库存

shell> cat hosts
host_1 file_1=alice
host_2 file_2=bob
host_3

剧本

- hosts: host_1,host_2,host_3
vars:
file_1_list: "{{ hostvars|json_query('*.file_1') }}"
file_2_list: "{{ hostvars|json_query('*.file_2') }}"
file_1_dict: "{{ dict(hostvars|dict2items|
selectattr('value.file_1', 'defined')|
json_query('[].[key, value.file_1]')) }}"
file_1_lis2: "{{ hostvars|dict2items|
selectattr('value.file_1', 'defined')|
json_query('[].{key: key, file_1: value.file_1}') }}"
tasks:
- debug:
msg: |-
file_1_list: {{ file_1_list }}
file_2_list: {{ file_2_list }}
file_1_dict:
{{ file_1_dict|to_nice_yaml|indent(2) }}
file_1_lis2:
{{ file_1_lis2|to_nice_yaml|indent(2) }}
run_once: true

msg: |-
file_1_list: ['alice']
file_2_list: ['bob']
file_1_dict:
host_1: alice

file_1_lis2:
-   file_1: alice
key: host_1

最新更新