Ansible:jinja2的双花括号转义(用引号括起来)

时间:2019-10-14 14:17:59

标签: python ansible escaping jinja2

我定义了这本剧本:

---
- hosts: "{{ target }}"
  tasks:
    - name: buildout test
      my_buildout:
        cfg: "{
          '/home/oerp/tmp':
            {
              'childs': {
                '{{ custom_name }}': {
                  'rules': [
                    (
                      (),
                      ('cmd', [('touch', {{ get_path('test.txt') }})])
                    )
                  ]
                }
              }
            }
        }"

通过以下方式运行我的剧本:ansible-playbook --extra-vars "target=local_stage" --connection=local /home/oerp/src/ansible-playbooks/buildout_test.yml -v

给出此错误:

fatal: [stage-my-odoo]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'get_path' is undefined\n\nThe error appears to be in '/home/oerp/src/ansible-playbooks/buildout_test.yml': line 4, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n  tasks:\n    - name: buildout test\n      ^ here\n"}

现在{{ custom_name }}是一个变量,其中{{ get_path('test.txt') }}是Jinja2表达式。

我尝试为jinja2表达式转义双花括号,例如:'{{' get_path('test.txt') '}}',但它给出了相同的输出。因此看起来它仍然将其视为ansible变量。我也无法删除dict(cfg参数类型为dict)的双引号,因为然后ansible变量将被忽略,并且它使用文字值(如{{ custom_name }},而不能替换为实际值)

P.S。 ansible 2.8.5.post0 python version = 3.6.7 (default, Mar 29 2019, 10:38:28) [GCC 5.4.0 20160609]

更新1

由ansible渲染cfg值并将其作为参数传递给模块后,它应该看起来像这样:

{
    '/home/oerp/tmp':
    {
      'childs': {
        'my_child_dirname': {
          'rules': [
            (
              (),
              ('cmd', [('touch', "{{ get_path('test.txt') }}")])
            )
          ]
        }
      }
    }
}

然后,当模块接收到该值时,它会进一步由jinja2呈现(特别是rules部分的项。在这种情况下,是touch命令参数`)。看起来像这样:

{
    '/home/oerp/tmp':
    {
      'childs': {
        'my_child_dirname': {
          'rules': [
            (
              (),
              ('cmd', [('touch', '/home/oerp/tmp/my_child_dirname/test.txt')])
            )
          ]
        }
      }
    }
}

Ansible仅应呈现{{ custom_name }},其中{{ get_path('test.txt') }}应该保留为文字字符串,稍后由我的模块处理。

更新2

看起来似乎是什么问题,我会尽力弄清楚问题出在哪里。

cfg参数中,有两个变量。 custom_nameget_path。第一个是正常的ansible变量。应该将其视为一体,并用ansible替换为值。 get_path不是变量。一旦my_buildout模块接收到呈现的cfg作为参数,它就是一个变为变量(调用方法)的表达式。

由于这个原因,{{ get_path('test.txt') }}应该被ansible视为简单字符串,并且不需要转换(例如{{ ansible_ignore_this }})。 而且要明确一点,不是整个cfg就是Jinja表达式。仅('touch', {{ get_path('test.txt') }})这部分由jinja渲染(当模块接收到整个cfg时,它将遍历该元组并尝试渲染字符串:"touch",然后渲染"{{ get_path('test.txt') }}"

如果my_buildout模块将直接接收cfg参数(而不使用ansible剧本或其他方法),并且看起来像 UPDATE 1 中的第一个示例中的,就像魅力一样。

1 个答案:

答案 0 :(得分:0)

已更新新问题内容

由于cfg必须是dict,因此对于该内容使用字符串文字是没有意义的-换句话说,您不想要jinja2小胡子表达式,您想要在变量 处使用变量

- name: buildout test
  my_buildout:
    cfg: >-
      {{
      {
        '/home/oerp/tmp': {
          'childs': {
             custom_name: {
               'rules': [
                (
                  (),
                  ('cmd', [('touch', get_path('test.txt') )])
                )
               ]
             }
          }
        }
      }
      }}