Ansible:循环字典和文件树

标签 ansible jinja2

如何循环字典和文件树?我想将带有 .j2 后缀(键)的模板文件递归到目标位置(值),还应重命名基本名称(删除 .j2 后缀)。这是一个完美的用例。不幸的是,ansible 不擅长处理复杂的数据结构。

输入:

vars:
  applications:
    application1:
      svcpaths:
        localfolder/bardir1: remotefolder/bardir1
        localfolder/bardir2: remotefolder/bardir2
        localfolder/bardir3: remotefolder/bardir3
    application2:
      svcpaths:
        localfolder/bardir5: remotefolder/bardir5
        localfolder/bardir6: remotefolder/bardir6

我的尝试:

    - name: Files to template
      template:
        src: "{{ item.src }}"
        dest: "{{ item.destination }}/{{ item.name | regex_replace('.j2','') }}"
      loop: |
        [
        {% for c in applications %}
        {% if applications[c]['svcpaths'] is defined and applications[c]['svcpaths'] |list|length >0  %}
        {% for o,m in applications[c]['svcpaths'].items() %}
        {% for i in lookup('filetree', o ) %}
        {% if i.state == 'file' and i.path | regex_search('.\.j2') %}
        {
        "name": "{{ i.path }}",
        "src": "{{ i.src }}",
        "destination": "{{ m }}"
        }, 
        {% endif %}
        {% endfor %}
        {% endfor %}
        {% endif %}
        {% endfor %}
        ]

我知道在戏剧中使用 jinja 不好,如果可能的话,我想避免它。另外,输入数据结构不应更改。

谢谢

最佳答案

如果我明白你想要做什么,我认为有一个相当简单的解决方案。如果您编写一个名为 template_files.yml 的任务文件:

---
- name: render templates to dest_dir
  loop: "{{ query('filetree', src_dir) }}"

  # we need this to avoid conflicts with the "item" variable in
  # the calling playbook.
  loop_control:
    loop_var: template
  when: template.src.endswith('.j2')
  template:
    src: "{{ template.src }}"
    dest: "{{ dest_dir }}/{{ (template.src|basename)[:-3] }}"

然后你可以编写这样的剧本:

---
- hosts: localhost
  gather_facts: false
  vars:
    applications:
      application1:
        svcpaths:
          localfolder/bardir1: /tmp/remotefolder/bardir1
          localfolder/bardir2: /tmp/remotefolder/bardir2
          localfolder/bardir3: /tmp/remotefolder/bardir3
      application2:
        svcpaths:
          localfolder/bardir5: /tmp/remotefolder/bardir5
          localfolder/bardir6: /tmp/remotefolder/bardir6

  tasks:
    # generate a list of {key: src, value: destination} 
    # dictionaries from your data structure.
    - set_fact:
        templates: "{{ templates|default([]) + item|dict2items }}"
      loop: "{{ applications|json_query('*.svcpaths')}}"

    # show what the generated variable looks like
    - debug:
        var: templates

    # template all the things
    - include_tasks: template_files.yml
      loop: "{{ templates }}"
      vars:
        src_dir: "{{ item.key }}"
        dest_dir: "{{ item.value }}"

鉴于我有一组如下所示的本地文件:

localfolder/bardir1/example.txt.j2
localfolder/bardir2/example.txt.j2
localfolder/bardir3/example.txt.j2
localfolder/bardir5/example.txt.j2
localfolder/bardir6/example.txt.j2

运行剧本的结果是:

/tmp/remotefolder/bardir6/example.txt
/tmp/remotefolder/bardir5/example.txt
/tmp/remotefolder/bardir3/example.txt
/tmp/remotefolder/bardir2/example.txt
/tmp/remotefolder/bardir1/example.txt

我认为这可能比您正在使用的基于 Jinja 模板的解决方案更容易阅读和理解。

关于Ansible:循环字典和文件树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55983831/

相关文章:

ansible - 追加到 Ansible 列表中的字典

python - 不同的方法使用不同的 'Forms'

python - 如何从同样动态创建 salt 状态的循环中要求动态创建的 salt 状态?

ansible - jinja2-AnsibleUndefinedVariable : 'dict object' has no attribute '"{{ target_hosts } }"' "

docker - 运行(docker_image)模块ansible Playbook时出错

ansible - 具有 IP 范围的主机

oracle - Ansible playbook 执行 Oracle 脚本

java - 在 App Engine 上使用 Java 中的 Python 代码

python - 如何在 Flask-Jinja Python 中使用列表中的列表

git - 如何使用 Ansible 查看最近的 git 标签?