Ansible—查找具有特定路径的文件,并将其从字典复制到特定的预设目标
我有一个问题,我已经试着解决了好几天了,我开始认为我不会得到它。所以,我来了 我必须编写一个Ansible playbook,它将在一堆repo中查找一堆文件,如果它碰巧在这些repo中找到该文件,则将其复制到特定的目标目录,该目录将预先设置并特定于该文件。一个问题是,该文件可能有多个实例,但我们只希望该文件位于路径中的特定子目录下(子目录的位置从repo更改为repo,并且repo的目录结构都非常不同) 为了不让大家都了解我们糟糕的命名约定,我把问题抽象到了这个愚蠢的例子中 假设这是我们的目录结构:Ansible—查找具有特定路径的文件,并将其从字典复制到特定的预设目标,ansible,Ansible,我有一个问题,我已经试着解决了好几天了,我开始认为我不会得到它。所以,我来了 我必须编写一个Ansible playbook,它将在一堆repo中查找一堆文件,如果它碰巧在这些repo中找到该文件,则将其复制到特定的目标目录,该目录将预先设置并特定于该文件。一个问题是,该文件可能有多个实例,但我们只希望该文件位于路径中的特定子目录下(子目录的位置从repo更改为repo,并且repo的目录结构都非常不同) 为了不让大家都了解我们糟糕的命名约定,我把问题抽象到了这个愚蠢的例子中 假设这是我们的目录
/tmp/example
└── foods
├── breakfast
│ ├── pancakes
│ └── waffles
├── dinner
│ ├── fish
│ └── pasta
└── lunch
├── burger
└── burrito
这是我们的字典,说明了用户,他们想要的食物,以及我们应该找到的食物的目的地路径:
orders:
'Bob':
food: 'burrito'
dst: '/tmp/example-homes/home/bob/plate'
'Jack':
food: 'fish'
dst: '/tmp/example-homes/home/jack/plate'
'Mary':
food: 'fish'
dst: '/tmp/example-homes/mary/plate'
现在,让我们假设我们要遍历orders字典中的人员列表,并在/tmp/example中找到他们的食物,但是只有当他们的食物选择在foods/午餐目录下时,它才应该匹配。如果我们碰巧在foods/午餐目录中找到了他们的食物,请将其复制到该用户指定的dst目录(请注意,并非所有dst目录都相同)。如果在食物/早餐或食物/晚餐,甚至是像餐厅/午餐之类的地方找到食物,则跳过食物;我们只关心食物/午餐。例如,玛丽想要鱼,鱼确实存在,但是它在食物/晚餐目录中,所以我们会认为它是丢失的,而不是复制。< / P >
我已经到了可以找到食物的地步,但我一直在尝试将找到的食物文件与dst字段联系起来,该字段告诉我们食物应该去哪里。这很令人沮丧,因为我觉得我需要的所有数据实际上都在find_food_results dictionary中。我只是不知道如何对find的结果采取行动,以便执行逻辑等价的“如果食物匹配,并且路径包含‘foods/午餐’,则将其复制到item.value.dst”
我也情不自禁地觉得有一种更简单的方法可以做到这一点,我只是在追根究底。无论如何,先谢谢你。如果我能澄清什么,请告诉我
代码如下:
---
- name: "directory finder"
hosts: 127.0.0.1
connection: local
vars:
orders:
'Bob':
food: 'burrito'
dst: '/tmp/example-homes/home/bob/plate'
'Jack':
food: 'fish'
dst: '/tmp/example-homes/home/jack/plate'
'Mary':
food: 'fish'
dst: '/tmp/example-homes/mary/plate'
tasks:
- name: "describe orders"
debug:
var: orders
- name: "describe orders | dict2items"
debug:
var: orders | dict2items
- name: "find the food"
find:
paths: "/tmp/example"
recurse: yes
file_type: file
patterns: "{{ item.value.food }}"
with_items:
- "{{ orders | dict2items }}"
register: find_food_results
- name: "describe find_food_results"
debug:
var: find_food_results
- name: "narrow down our findings to paths that contain 'foods/lunch'"
set_fact:
food_lunch_directory_paths: "{{ food_lunch_directory_paths | default([]) }} + [ '{{ item.path }}' ]"
with_items: "{{ find_food_results.results | map(attribute='files') | list }}"
when: "'foods/lunch' in item.path"
- name: "describe our food/lunch paths"
debug:
var: food_lunch_directory_paths
---
- name: "directory finder"
hosts: 127.0.0.1
connection: local
vars:
orders:
'Bob':
food: 'burrito'
dst: '/tmp/example-homes/home/bob/plate'
'Jack':
food: 'fish'
dst: '/tmp/example-homes/home/jack/plate'
'Mary':
food: 'fish'
dst: '/tmp/example-homes/mary/plate'
tasks:
- name: "describe orders"
debug:
var: orders
- name: "describe orders | dict2items"
debug:
var: orders | dict2items
- name: "find the food"
find:
paths: "/tmp/example"
recurse: yes
file_type: file
patterns: "{{ item.value.food }}"
with_items:
- "{{ orders | dict2items }}"
register: find_food_results
- name: "create a src key/value dictionary element"
set_fact:
orders: "{{ orders | combine( new_item, recursive=true ) }}"
vars:
new_item: "{ '{{ item.item.key }}': { 'src': '{{ item.files[0].path }}' } }"
with_items: "{{ find_food_results.results }}"
- name: "copy property files to destination"
copy:
src: "{{ item.value.src }}"
dest: "{{ item.value.dst }}"
owner: root
group: root
mode: 0644
with_dict: "{{ orders }}"
when: "'foods/lunch' in item.value.src"
以下是输出:
PLAY [directory finder] *******************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************
ok: [127.0.0.1]
TASK [describe orders] ********************************************************************************************************************************************
ok: [127.0.0.1] => {
"orders": {
"Bob": {
"dst": "/tmp/example-homes/home/bob/plate",
"food": "burrito"
},
"Jack": {
"dst": "/tmp/example-homes/home/jack/plate",
"food": "fish"
},
"Mary": {
"dst": "/tmp/example-homes/mary/plate",
"food": "fish"
}
}
}
TASK [describe orders | dict2items] *******************************************************************************************************************************
ok: [127.0.0.1] => {
"orders | dict2items": [
{
"key": "Bob",
"value": {
"dst": "/tmp/example-homes/home/bob/plate",
"food": "burrito"
}
},
{
"key": "Jack",
"value": {
"dst": "/tmp/example-homes/home/jack/plate",
"food": "fish"
}
},
{
"key": "Mary",
"value": {
"dst": "/tmp/example-homes/mary/plate",
"food": "fish"
}
}
]
}
TASK [find the food] **********************************************************************************************************************************************
ok: [127.0.0.1] => (item={u'key': u'Bob', u'value': {u'food': u'burrito', u'dst': u'/tmp/example-homes/home/bob/plate'}})
ok: [127.0.0.1] => (item={u'key': u'Jack', u'value': {u'food': u'fish', u'dst': u'/tmp/example-homes/home/jack/plate'}})
ok: [127.0.0.1] => (item={u'key': u'Mary', u'value': {u'food': u'fish', u'dst': u'/tmp/example-homes/mary/plate'}})
TASK [describe find_food_results] *********************************************************************************************************************************
ok: [127.0.0.1] => {
"find_food_results": {
"changed": false,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"changed": false,
"examined": 10,
"failed": false,
"files": [
{
"atime": 1604184466.0584693,
"ctime": 1604184466.0584693,
"dev": 66305,
"gid": 0,
"gr_name": "root",
"inode": 58724223,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1604184466.0584693,
"nlink": 1,
"path": "/tmp/example/foods/lunch/burrito",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 0,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
}
],
"invocation": {
"module_args": {
"age": null,
"age_stamp": "mtime",
"contains": null,
"depth": null,
"excludes": null,
"file_type": "file",
"follow": false,
"get_checksum": false,
"hidden": false,
"paths": [
"/tmp/example"
],
"patterns": [
"burrito"
],
"recurse": true,
"size": null,
"use_regex": false
}
},
"item": {
"key": "Bob",
"value": {
"dst": "/tmp/example-homes/home/bob/plate",
"food": "burrito"
}
},
"matched": 1,
"msg": ""
},
{
"ansible_loop_var": "item",
"changed": false,
"examined": 10,
"failed": false,
"files": [
{
"atime": 1604184480.3713806,
"ctime": 1604184480.3713806,
"dev": 66305,
"gid": 0,
"gr_name": "root",
"inode": 62917805,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1604184480.3713806,
"nlink": 1,
"path": "/tmp/example/foods/dinner/fish",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 0,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
}
],
"invocation": {
"module_args": {
"age": null,
"age_stamp": "mtime",
"contains": null,
"depth": null,
"excludes": null,
"file_type": "file",
"follow": false,
"get_checksum": false,
"hidden": false,
"paths": [
"/tmp/example"
],
"patterns": [
"fish"
],
"recurse": true,
"size": null,
"use_regex": false
}
},
"item": {
"key": "Jack",
"value": {
"dst": "/tmp/example-homes/home/jack/plate",
"food": "fish"
}
},
"matched": 1,
"msg": ""
},
{
"ansible_loop_var": "item",
"changed": false,
"examined": 10,
"failed": false,
"files": [
{
"atime": 1604184480.3713806,
"ctime": 1604184480.3713806,
"dev": 66305,
"gid": 0,
"gr_name": "root",
"inode": 62917805,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1604184480.3713806,
"nlink": 1,
"path": "/tmp/example/foods/dinner/fish",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 0,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
}
],
"invocation": {
"module_args": {
"age": null,
"age_stamp": "mtime",
"contains": null,
"depth": null,
"excludes": null,
"file_type": "file",
"follow": false,
"get_checksum": false,
"hidden": false,
"paths": [
"/tmp/example"
],
"patterns": [
"fish"
],
"recurse": true,
"size": null,
"use_regex": false
}
},
"item": {
"key": "Mary",
"value": {
"dst": "/tmp/example-homes/mary/plate",
"food": "fish"
}
},
"matched": 1,
"msg": ""
}
]
}
}
TASK [narrow down our findings to paths that contain 'foods/lunch'] ***********************************************************************************************
ok: [127.0.0.1] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1604184466.0584693, u'gr_name': u'root', u'path': u'/tmp/example/foods/lunch/burrito', u'xusr': False, u'atime': 1604184466.0584693, u'inode': 58724223, u'isgid': False, u'size': 0, u'isdir': False, u'wgrp': False, u'ctime': 1604184466.0584693, u'isblk': False, u'xgrp': False, u'isuid': False, u'dev': 66305, u'roth': True, u'isreg': True, u'isfifo': False, u'mode': u'0644', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True})
skipping: [127.0.0.1] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1604184480.3713806, u'gr_name': u'root', u'path': u'/tmp/example/foods/dinner/fish', u'xusr': False, u'atime': 1604184480.3713806, u'inode': 62917805, u'isgid': False, u'size': 0, u'isdir': False, u'wgrp': False, u'ctime': 1604184480.3713806, u'isblk': False, u'xgrp': False, u'isuid': False, u'dev': 66305, u'roth': True, u'isreg': True, u'isfifo': False, u'mode': u'0644', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True})
skipping: [127.0.0.1] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1604184480.3713806, u'gr_name': u'root', u'path': u'/tmp/example/foods/dinner/fish', u'xusr': False, u'atime': 1604184480.3713806, u'inode': 62917805, u'isgid': False, u'size': 0, u'isdir': False, u'wgrp': False, u'ctime': 1604184480.3713806, u'isblk': False, u'xgrp': False, u'isuid': False, u'dev': 66305, u'roth': True, u'isreg': True, u'isfifo': False, u'mode': u'0644', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True})
TASK [describe our food/lunch paths] ******************************************************************************************************************************
ok: [127.0.0.1] => {
"food_lunch_directory_paths": [
"/tmp/example/foods/lunch/burrito"
]
}
PLAY RECAP ********************************************************************************************************************************************************
127.0.0.1 : ok=7 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
当然,我一问这个问题,就会找到答案:-/ 好吧,如果有其他人在挣扎,下面是我如何修复它的。尽管如此,我还是希望看到更有效的解决方案,所以如果你有一个解决方案,请加入 我能够在字典中创建一个名为“src”的新值,该值包含使用find模块找到的文件的路径。然后,在复制模块中,我能够遍历字典,并且只在src包含“foods/午餐”时进行复制 代码如下:
---
- name: "directory finder"
hosts: 127.0.0.1
connection: local
vars:
orders:
'Bob':
food: 'burrito'
dst: '/tmp/example-homes/home/bob/plate'
'Jack':
food: 'fish'
dst: '/tmp/example-homes/home/jack/plate'
'Mary':
food: 'fish'
dst: '/tmp/example-homes/mary/plate'
tasks:
- name: "describe orders"
debug:
var: orders
- name: "describe orders | dict2items"
debug:
var: orders | dict2items
- name: "find the food"
find:
paths: "/tmp/example"
recurse: yes
file_type: file
patterns: "{{ item.value.food }}"
with_items:
- "{{ orders | dict2items }}"
register: find_food_results
- name: "describe find_food_results"
debug:
var: find_food_results
- name: "narrow down our findings to paths that contain 'foods/lunch'"
set_fact:
food_lunch_directory_paths: "{{ food_lunch_directory_paths | default([]) }} + [ '{{ item.path }}' ]"
with_items: "{{ find_food_results.results | map(attribute='files') | list }}"
when: "'foods/lunch' in item.path"
- name: "describe our food/lunch paths"
debug:
var: food_lunch_directory_paths
---
- name: "directory finder"
hosts: 127.0.0.1
connection: local
vars:
orders:
'Bob':
food: 'burrito'
dst: '/tmp/example-homes/home/bob/plate'
'Jack':
food: 'fish'
dst: '/tmp/example-homes/home/jack/plate'
'Mary':
food: 'fish'
dst: '/tmp/example-homes/mary/plate'
tasks:
- name: "describe orders"
debug:
var: orders
- name: "describe orders | dict2items"
debug:
var: orders | dict2items
- name: "find the food"
find:
paths: "/tmp/example"
recurse: yes
file_type: file
patterns: "{{ item.value.food }}"
with_items:
- "{{ orders | dict2items }}"
register: find_food_results
- name: "create a src key/value dictionary element"
set_fact:
orders: "{{ orders | combine( new_item, recursive=true ) }}"
vars:
new_item: "{ '{{ item.item.key }}': { 'src': '{{ item.files[0].path }}' } }"
with_items: "{{ find_food_results.results }}"
- name: "copy property files to destination"
copy:
src: "{{ item.value.src }}"
dest: "{{ item.value.dst }}"
owner: root
group: root
mode: 0644
with_dict: "{{ orders }}"
when: "'foods/lunch' in item.value.src"
让我们考虑一下丢失的文件。例如,给定命令
订单:
“鲍勃”:
食物:“玉米煎饼”
dst:“/tmp/example homes/home/bob/plate”
“杰克”:
食物:“鱼”
dst:“/tmp/示例homes/home/jack/plate”
“玛丽”:
食物:“鱼”
dst:“/tmp/example homes/mary/plate”
“乔”:
食物:“牛排”
dst:“/tmp/example homes/joe/plate”
创建食物列表
-名称:“创建食品清单”
设定事实:
食品:{{订单}目录2项|
映射(attribute='value.food')|唯一|排序|列表}”
-调试:
食品
给予
食品:
-玉米煎饼
-鱼
-牛排
查找文件并创建食品和相关文件的词典。然后使用字典将现有文件复制到目标
-名称:“找到食物”
查找:
路径:“/tmp/example”
递归:是的
文件类型:文件
模式:“{item}}”
循环:“{{foods}}”
注册:查找食物结果
-名称:“创建食品词典”
设定事实:
食物:{{dict(食物| zip(路径))}”
变量:
路径:“{{find_food_results.results”|
映射(属性='files')|列表}”
-名称:“将属性文件复制到目标”
调试:
msg:“将{{foods[item.value.food][0]['path']}}复制到{{item.value.dst}”
带_dict:“{{orders}”
回路控制:
标签:“{item.key}}”
时间:食物[项目.价值.食物]|长度>0
给予
问:“在早餐、午餐和晚餐目录中归档‘burrito’…我如何迭代……找到食物\u results.files?几乎就像一个嵌套循环。” 答:仅显示具有选定路径的词典。任务
-调试:
msg:“{{msg.split('\n')[:-1]}”
变量:
味精:|
{{item.key}
{{item.value | map(attribute='path')| list | to_nice_yaml}
循环:{{foods | dict2items}}”
回路控制:
标签:“{item.key}}”
给予
任务[调试]****
确定:[localhost]=>(项目=玉米饼)=>
味精:
-玉米煎饼
-“-/tmp/example/foods/早餐/玉米煎饼”
-“-/tmp/示例/食品/晚餐/玉米煎饼”
-“-/tmp/example/foods/午餐/玉米煎饼”
确定:[localhost]=>(item=fish)=>
味精:
-鱼
-“-/tmp/示例/食品/晚餐/鱼”
确定:[localhost]=>(项目=牛排)=>
味精:
-牛排
- '[]'
如果要迭代文件列表,请使用子元素。比如说
-name:“列出所有属性文件”
调试:
msg:{{item.0.key}{{{item.1.path}}”
带_子元素:
-“{{食物|词汇}”
-价值观
回路控制:
标签:“{item.0.key}}”
给予
任务[列出所有属性文件]****
确定:[localhost]=>(项目=玉米饼)=>
味精:玉米煎饼/tmp/example/foods/brea