Ansible—查找具有特定路径的文件,并将其从字典复制到特定的预设目标

Ansible—查找具有特定路径的文件,并将其从字典复制到特定的预设目标,ansible,Ansible,我有一个问题,我已经试着解决了好几天了,我开始认为我不会得到它。所以,我来了 我必须编写一个Ansible playbook,它将在一堆repo中查找一堆文件,如果它碰巧在这些repo中找到该文件,则将其复制到特定的目标目录,该目录将预先设置并特定于该文件。一个问题是,该文件可能有多个实例,但我们只希望该文件位于路径中的特定子目录下(子目录的位置从repo更改为repo,并且repo的目录结构都非常不同) 为了不让大家都了解我们糟糕的命名约定,我把问题抽象到了这个愚蠢的例子中 假设这是我们的目录

我有一个问题,我已经试着解决了好几天了,我开始认为我不会得到它。所以,我来了

我必须编写一个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