【问题标题】:Ansible: escape double curly braces for jinja2 (in quoted expression)Ansible:为 jinja2 转义双花括号(在引用的表达式中)
【发布时间】:2019-10-14 14:17:59
【问题描述】:

我已经定义了这个剧本:

---
- 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 }} 是ansible 变量,其中{{ get_path('test.txt') }} 是Jinja2 表达式。

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

附: ansible 2.8.5.post0python version = 3.6.7 (default, Mar 29 2019, 10:38:28) [GCC 5.4.0 20160609]

更新 1

cfg 的值被 ansible 渲染并作为参数传递给模块后,预计如下所示:

{
    '/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 替换为 value。 get_path 不是 ansible 变量。一旦my_buildout 模块接收到渲染的cfg 作为参数,它就是一个变为变量的表达式(调用方法)。

因此,{{ get_path('test.txt') }} 应该被 ansible 视为简单字符串,并且不需要转换(例如 {{ ansible_ignore_this }})。 并且说清楚,不是整个cfg 是神社表达。只有('touch', {{ get_path('test.txt') }}) 这部分由jinja 渲染(当模块接收到整个cfg 时,它会遍历该元组并尝试渲染字符串:"touch" 然后"{{ get_path('test.txt') }}"

如果 my_buildout 模块会直接接收 cfg 参数(不使用 ansible playbook 或其他),它看起来就像 UPDATE 1 中的第一个示例中的那样,那么它就像一个魅力.

【问题讨论】:

  • 根据您对我的回答的评论,我显然没有理解最终状态;你能显示你的cfg 值的前后吗?就像我所做的那样:处理可变的事物,然后将它们解决到最终状态?因为您所呈现的数据结构不能成为dict 没有一些分辨率
  • @mdaniel 我更新了我的答案,解释了 ansible 渲染后预期的 cfg 状态,然后在我的模块渲染它之后(使用 jinja2)。
  • 等一下,在你的模块渲染它之后?这不是我要问的——我说cfg 前后应该是什么样子,而不是你的模块 对内容做了什么;你想让 ansible 渲染一些内容,然后你调用 jinja2 来进一步渲染内容?
  • 另外,如果您再次调用 jinja2 是真的,那么,正如我正确指出的那样,您可以更改 您的模块 中的 variable_start_stringvariable_end_string 以进一步区分ansible的起始表达式和你的起始表达式
  • @mdaniel 我不是向您展示了 cfg 之前和之后的样子吗?为了更清楚,我展示了模块使用此类 cfg 后的样子。如果您不关心我的模块做什么,那么您可以忽略最后一个示例,但看起来您并不了解问题所在。您应该记下我所说的部分“(特别是规则部分的项目。在这种情况下,触摸命令参数)”。只有这部分在我的模块中呈现,其中元组的每个部分都被呈现。在这种情况下touch{{get_path..}}。如果不清楚,我会进一步更新我的问题。

标签: python ansible escaping jinja2


【解决方案1】:

更新了新的问题内容

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

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

【讨论】:

  • 尝试了这两种方法,但它给出了这个错误(在这两种情况下):fatal: [stage-my-odoo]: FAILED! => {"changed": false, "msg": "argument cfg is of type <class 'str'> and we were unable to convert to dict: unable to evaluate string as dictionary"}。它以某种方式使论点无效。
  • 我认为它更复杂,因为'test.txt'需要被引用。
  • 我更新了我的答案。希望它会弄清楚问题出在哪里。我也试过你更新的答案,但它会给出这个错误:The offending line appears to be: {{ { ^ here。虽然正如我多次提到的,cfg 只有一部分是由 jinja2 渲染的,所以我没想到它会起作用。
猜你喜欢
  • 2015-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-14
  • 2021-05-15
  • 2013-05-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多