Ansible嵌套循环和jinja2过滤器

时间:2019-05-17 17:21:34

标签: ansible jinja2

我需要在我的项目中列出一些目录,我有这种树:

.
└── path
    └── to
        ├── aa
        │   └── x9999
        ├── bb
        │   ├── x9997
        │   └── x9998
        ├── cc
        └── dd

我已经在剧本中完成了以下任务以查找目录:

---
- name: 'test of find'
  hosts: localhost
  vars:
    loopVar:
      - 'aa'
      - 'bb'
      - 'cc'
      - 'dd'
  tasks:
    - name: 'find'
      find:
        path: '/path/to/{{item}}'
        file_type: directory
        patterns: '[^_]*[a-z]+[0-9]{4}[a-z]*$'
        use_regex: yes
      register: list
      loop: '{{loopVar}}'

结果是:

{
    "list": {
        "results": [
            {
                "files": [
                    {
                        "path": "/path/to/aa/x9999"
                    }
                ],
                "item": "aa",
                "matched": 1
            },
            {
                "files":  [
                    {
                        "path": "/path/to/bb/x9997"
                    },
                    {
                        "path": "/path/to/bb/x9998"
                    }
                ],

                "item": "bb",
                "matched": 2
            },
            {
                "files": [],
                "item": "cc",
                "matched": 0
            },
            {
                "files": [],
                "item": "dd",
                "matched": 0
            }
        ]
    }
}

我想用此数组调用一个include_role,但是由于我需要将varpath设置在同一级别,所以不能这样做。 我想在我的结果中努力获得这种价值:

{ "final": [
    { "path": "/path/to/aa/x9999", "var": "aa" },
    { "path": "/path/to/bb/x9998", "var": "bb" },
    { "path": "/path/to/bb/x9997", "var": "bb" }
  ]
}

我使用 set_fact 尝试了很多事情,但是我找不到如何进行这种工作的方法。 非常感谢您的帮助:-)

2 个答案:

答案 0 :(得分:0)

下面的戏

- find:
    paths: "/path/to/{{ item }}"
    file_type: directory
    recurse: yes
  register: list
  loop: [ aa, bb, cc, dd]
- set_fact:
    pre_final: "{{ list.results|json_query('[].{path: files[].path,
                                                var: item}') }}"
- set_fact:
    final: "{{ final|default([]) + [{'var': item.0.var,
                                     'path': item.1}] }}"
  loop: "{{ lookup('subelements', pre_final, 'path') }}"
- debug:
    var: final

给予(节略):

"final": [
    {
        "path": "/path/to/aa/x9999", 
        "var": "aa"
    }, 
    {
        "path": "/path/to/bb/x9997", 
        "var": "bb"
    }, 
    {
        "path": "/path/to/bb/x9998", 
        "var": "bb"
    }
]

答案 1 :(得分:0)

我找到了一种方法。这不是可爱的,但是有效。
我必须使用include_tasks模块和给定的json_query:

playbook.yml

---
- name: 'test of find'
  hosts: localhost
  vars:
    loopVar:
      - 'aa'
      - 'bb'
      - 'cc'
      - 'dd'
  tasks:
    - name: 'find'
      find:
        path: '/path/to/{{item}}'
        file_type: directory
        patterns: '[^_]*[a-z]+[0-9]{4}[a-z]*$'
        use_regex: yes
      register: list
      loop: '{{loopVar}}'

    - set_fact:
        all: '{{ list.results|json_query("[].{path: files[].path, var: item, matched: matched}") }}'

    - include_tasks: 'inner.yml'
      vars:
        paths: '{{item.path}}'
        var: '{{item.var}}'
      loop: '{{all}}'
      when: 'item.matched != 0'

    - debug:
        var: final

inner.yaml

---
- set_fact:
    final: '{{ final|default([]) + [{ "path": path|basename, "var": var }] }}'
  loop: '{{paths}}'
  loop_control:
    loop_var: path

结果:

[root@xxxx path]# ansible-playbook playbook.yml

PLAY [test of find] *********************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [find] *****************************************************************************************************************************************************************************************************************************
ok: [localhost] => (item=aa)
ok: [localhost] => (item=bb)
ok: [localhost] => (item=cc)
ok: [localhost] => (item=dd)

TASK [set_fact] *************************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [include_tasks] ********************************************************************************************************************************************************************************************************************
skipping: [localhost] => (item={'var': u'cc', 'path': [], 'matched': 0})
skipping: [localhost] => (item={'var': u'dd', 'path': [], 'matched': 0})
included: /mnt/hgfs/Documents/inner.yml for localhost => (item={'var': u'aa', 'path': [u'/path/to/aa/x9999'], 'matched': 1})
included: /mnt/hgfs/Documents/inner.yml for localhost => (item={'var': u'bb', 'path': [u'/path/to/bb/x9997', u'/path/to/bb/x9998'], 'matched': 2})

TASK [set_fact] *************************************************************************************************************************************************************************************************************************
ok: [localhost] => (item=/path/to/aa/x9999)

TASK [set_fact] *************************************************************************************************************************************************************************************************************************
ok: [localhost] => (item=/path/to/bb/x9997)
ok: [localhost] => (item=/path/to/bb/x9998)

TASK [debug] ****************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "final": [
        {
            "path": "x9999",
            "var": "aa"
        },
        {
            "path": "x9997",
            "var": "bb"
        },
        {
            "path": "x9998",
            "var": "bb"
        }
    ]
}

PLAY RECAP ******************************************************************************************************************************************************************************************************************************
localhost                  : ok=8    changed=0    unreachable=0    failed=0

我找不到不使用外部剧本的方法。 如果有人找到方法,我很乐于学习:-)

非常感谢。