Ansible: экранировать двойные фигурные скобки для jinja2 (в кавычках) - PullRequest
0 голосов
/ 14 октября 2019

У меня определен этот playbook:

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

Запуск моей playbook с: 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 }} isпеременная ansible, где {{ get_path('test.txt') }}, является выражением Jinja2.

Я попытался избежать двойных фигурных скобок для выражения jinja2, например: '{{' get_path('test.txt') '}}', но он выдает тот же результат. Так что, похоже, он все еще видит это как переменную типа ANSIBLE. Я также не могу удалить перенос двойных кавычек для dict (тип аргумента cfg равен dict), потому что тогда игнорируемые переменные игнорируются, и он использует буквальное значение (например, {{ custom_name }}, без замены на фактическое значение)

PS ansible 2.8.5.post0 python 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_name и get_path. Первый - нормальная переменная. Его следует рассматривать как единое целое и заменять значением значение ansible. get_path не является переменной типа. Это выражение становится переменным (вызов метода), когда модуль 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 , тогда он будет работать как шарм.

1 Ответ

0 голосов
/ 15 октября 2019

обновлено для нового содержания вопроса

Поскольку cfg должно быть dict, использовать строковый литерал для этого содержимого не имеет смысла - вДругими словами, вам не нужны выражения усов jinja2, вы хотите использовать переменные в местах, которые переменные :

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