【问题标题】:Jinja2 - Concatenate string in a recursive loopJinja2 - 在递归循环中连接字符串
【发布时间】:2018-07-18 14:54:17
【问题描述】:

我有一个 yaml ansible 文件,例如:

_app_config:   
  APP:
    server: '"https://tst.example.com"'
    uploadRefreshRate: 10
    autonomous:
      active: "false"
      SiteId: 47
      tests:
        test1: 1

我想解析它并创建一个配置文件,例如:

APP.server = "https://tst.example.com"
APP.uploadRefreshRate = 10
    APP.autonomous.active = false
    APP.autonomous.SiteId = 47
      APP.autonomous.tests.test1 = 1

所以我的 jinja2 模板看起来像这样:

{%  if _app_config is defined %}
{%    if _app_config.APP is defined %}
{%      set key_chain = '' %}
{%      for key,value in _app_config.APP.iteritems() recursive %}
{%        if value is mapping %}
{%          set key_chain = key_chain + key %}
            {{ loop(value.iteritems()) }}
{%        else %}
{%          set param = 'APP.' + key_chain | string + '=' + value | string %}
{{ param | indent(loop.depth) }}
{%        endif %}
{%      endfor %}
{%    endif %}
{%  endif %}

所以结果不是预期的:)

APP.="common.core" 
AGL.=None
            AGL.=false AGL.=47
            AGL.=1


AGL.="https://tst.example.com" AGL.=10

值没有排序,key_chain 连接不起作用...

感谢您的帮助!

【问题讨论】:

    标签: recursion jinja2 string-concatenation


    【解决方案1】:

    下面的这个 python 'filter_plugin' 就是这样做的:

    from __future__ import (absolute_import, division, print_function)
    __metaclass__ = type
    
    
    ANSIBLE_METADATA = {
        'metadata_version': '1.1',
        'status': ['preview'],
        'supported_by': 'community'
    }
    
    
    from ansible.errors import AnsibleFilterError
    
    def dict_path(my_dict, path=None, sort=True):
        if isinstance(my_dict, dict):
            def recurse(values, path):
                for k, v in values.iteritems():
                    newpath = path + [k]
                    if isinstance(v, dict):
                        for u in recurse(v, newpath):
                            yield u
                    else:
                        yield newpath, v
            if path is None:
                path = []
            g=recurse(my_dict, path)
            if sort:
                return sorted(sorted(g, key=lambda item: len(item[0])), key=lambda item: '.'.join(item[0]))
            else:
                return g
        else:
            raise AnsibleFilterError(my_dict + 'must be a dictionary')
    
    # ---- Ansible filters ----
    class FilterModule(object):
        ''' Dict path filter '''
        def filters(self):
            return {
                'dict_path': dict_path
            }
    

    并在您的模板中添加此代码:

    {% for i in app_config | dict_path %}
    {{ i.0 | join('.') }} = {{ i.1 }}
    {% endfor %}
    

    皮埃尔

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-15
      • 2015-12-16
      • 2013-07-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多