Неправильный результат при оценке многострочной логической переменной в файле Ansible yaml - PullRequest
0 голосов
/ 28 января 2019

Использование ansible 2.7.5 Я пытаюсь создать многострочный логический параметр.

Сначала я убедился, что он работает так, как ожидалось, как одна строка с:

FOOD: apple
IS_FRUIT: '{% if FOOD == "carrot" %}false{% elif FOOD == "apple" or FOOD == "banana" %}true{% endif %}'

изатем задача:

- name: "FOOD is: {{ FOOD }}" 
  debug: msg="FOOD is {{ FOOD }} where IS_FRUIT {{ IS_FRUIT | bool }}"

, которая печатает:

ok: [localhost] => {
    "msg": "FOOD is apple where IS_FRUIT [ True ]"
}

, как и ожидалось при запуске.

На основе:

В YAMLкак разбить строку на несколько строк?

Затем я попытался:

IS_FRUIT: >-
 {% if FOOD == "carrot" %}false
 {% elif FOOD == "apple" or FOOD == "banana" %}true
 {% endif %}

, но это выдает:

ok: [localhost] => {
    "msg": "FOOD is apple where IS_FRUIT [ False ]"
}

, что неправильно,Я нашел этот пост, описывающий похожую проблему: https://github.com/ansible/ansible/issues/18142

, но на самом деле он не дает решения.Любое предложение о том, как создать многострочные булевы переменные в Ansible?

На основе приведенного ниже ответа я также попытался:

FOOD: apple

IS_FRUIT: |
 {% if FOOD == "carrot" %}false
 {% elif FOOD == "apple" or FOOD == "banana" %}true
 {% endif %}

, но когда я запускаю это с той же задачей выше, я все ещеполучить:

ok: [localhost] => {
    "msg": "FOOD is apple where IS_FRUIT False"
}

что не так.

Ответы [ 3 ]

0 голосов
/ 28 января 2019

Скучное объяснение того, что происходит

IS_FRUIT: >-
 {% if FOOD == "carrot" %}false
 {% elif FOOD == "apple" or FOOD == "banana" %}true
 {% endif %}

Помните, что в YAML скаляр со сложенным блоком (начиная с >) заменяет отдельные символы новой строки пробелами(и несколько новых строк с одним меньшим количеством новых строк).Таким образом, приведенный выше код эквивалентен

IS_FRUIT: >-
 {% if FOOD == "carrot" %}false {% elif FOOD == "apple" or FOOD == "banana" %}true {% endif %}

Так что после обработки Jinja вы получите либо false, либо true с завершающим пробелом .YAML не будет сопоставлять эти скаляры с булевыми значениями из-за этого конечного пробела.

Теперь я думаю , что Ansible видит, что он получает не булево значение, и он отображает это не булево значение вв некотором роде логическое значение.И, таким образом, ваш скаляр оценивается в False, даже если он равен true с завершающим пробелом (уценка не позволяет мне правильно отобразить это).


Важная часть о том, как это исправить

Вместо этого вы можете использовать литеральный скалярный блок (на основе предложения clockworknet ):

IS_FRUIT: |-
 {% if FOOD == "carrot" %}false
 {% elif FOOD == "apple" or FOOD == "banana" %}true
 {% endif %}

Это работает, потому что сейчассимволы новой строки не будут преобразованы в пробелы, но вместо этого остаются символами новой строки.После обработки Jinja остается только одна строка, и последний символ новой строки будет удален - in |-.

Однако, это не поможет вам, если у вас есть более сложные выражения, где вы хотитена самом деле разделить содержимое на несколько строк.Существует лучшее решение: Управление пробелами Jinja :

IS_FRUIT: >-
 {% if FOOD == "carrot" %}false
 {%- elif FOOD == "apple" or FOOD == "banana" %}true
 {%- endif %}

- в тегах Jinja говорит Jinja удалить все пробелы перед этим тегом,так что это в основном эквивалентно

IS_FRUIT: >-
 {% if FOOD == "carrot" %}false{% elif FOOD == "apple" or FOOD == "banana" %}true{% endif %}

Вы также можете использовать это как -%}, чтобы удалить все пробелы после тега.Однако, будьте осторожны: обработка Jinja выполняется перед обработкой YAML, поэтому она может испортить ваши тщательно написанные отступы YAML!Например, не используйте {%- в первом теге Jinja в скаляре блока, поскольку Jinja будет помещать текст в ту же строку, что и |-, что является недопустимым YAML!То же самое касается последнего тега и -%}.

0 голосов
/ 29 января 2019

Хорошее объяснение того, что происходит с помощью @ flyx.

Я бы рекомендовал избегать использования выражений Джинджа в ваших книгах в пользу выражений Джинджа .
Операторы Still в шаблонах файлов в порядке.

Вы можете написать определение vars следующим образом:

IS_FRUIT: >-
  {{ false if FOOD == 'carrot'
     else
     (
       true if FOOD in ['apple', 'banana']
       else 'unknown'
     )
  }}

В этом случае мы заботимся только о последнем переводе строки, который удаляется с помощью >-.

0 голосов
/ 28 января 2019

Это работает для меня:

IS_FRUIT: |
 {% if FOOD == "carrot" %}false
 {% elif FOOD == "apple" or FOOD == "banana" %}true
 {% endif %}

(измените на символ |, чтобы использовать буквальное многострочное поведение)

...