Возможное изменение значения по умолчанию в соответствии с условием

16

Можно ли изменить значение переменной роли по умолчанию в соответствии с некоторым условием (т. Е. Значением другой переменной)?

Детали

У меня есть две связанные переменные для команды, envи composer_opts.

Если оба остаются по умолчанию ( env = "prod"и composer_opts = "--no-dev"), все в порядке.

Если я поменяю envна dev, по умолчанию для другого будет нарушена моя команда, поэтому мне всегда нужно устанавливать оба. Можно ли избежать этого, установив условное значение по умолчанию с помощью специального сценария / if?

Важно: я не хочу всегда устанавливать composer_optsзначение в соответствии со envзначением. Я хочу установить его, только если он еще не установлен (т.е. динамическое значение по умолчанию).

ПСЕВДОКОД

Я хотел бы сделать что-то вроде этого (следующий код не является допустимым, просто псевдокод, чтобы выразить мою потребность)

---
# defaults/main.yml

env: prod
composer_opts: 
    when: "{{env}}" = 'prod'
        '--no-dev --optimize-autoloader --no-interaction'
    when: "{{env}}" = 'dev'
        '' 
Франческо Абени
источник

Ответы:

12

Я предлагаю это решение:

---
 - set_fact:
     composer_opts: ""
   when: "{{env}}" == 'dev'

Он будет устанавливать composer_optsпеременную в строку, ""когда переменная envравна ' dev'.

Вот пример книги на основе обновленного вопроса:

$ cat test.yml

---
- hosts: 127.0.0.1
  connection: local
  tasks:
  - set_fact:
      composer_opts: "{% if env == 'prod' %} '--no-dev --optimize-autoloader --no-interaction' {% else %} '' {% endif %}"

  - debug: var=composer_opts

Пример вывода:

sudo ansible-playbook test.yml -e env=dev

PLAY [127.0.0.1] ************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [127.0.0.1]

TASK: [set_fact ] ************************************************************* 
ok: [127.0.0.1]

TASK: [debug var="{{composer_opts}}"] ***************************************** 
ok: [127.0.0.1] => {
    "var": {
        " '' ": " '' "
    }
}

PLAY RECAP ******************************************************************** 
127.0.0.1                  : ok=3    changed=0    unreachable=0    failed=0   


sudo ansible-playbook test.yml -e env=prod

PLAY [127.0.0.1] ************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [127.0.0.1]

TASK: [set_fact ] ************************************************************* 
ok: [127.0.0.1]

TASK: [debug var="{{composer_opts}}"] ***************************************** 
ok: [127.0.0.1] => {
    "var": {
        " '--no-dev --optimize-autoloader --no-interaction' ": " '--no-dev --optimize-autoloader --no-interaction' "
    }
}

PLAY RECAP ******************************************************************** 
127.0.0.1                  : ok=3    changed=0    unreachable=0    failed=0   
Navern
источник
1
Это часть решения. Он всегда будет содержать composer_optsпустую строку, когда envравен «dev», перезаписывая любое установленное значение. Я думаю , что условное должен быть продлен так: when: "{{env}}" == 'dev' and "{{composer_opts}}" is undefined. Это выглядит хорошо? Можете ли вы соответственно обновить свой вопрос?
Франческо Абени
composer_opts будет определен, потому что он имеет значение по умолчанию. Вам нужно другое выражение, чтобы решить вашу задачу. Например, переменная custom_composer_opts.
Заверн
Пожалуйста, укажите с псевдокодом, что вы хотите сделать. Я обновлю свой ответ соответственно.
Заверн
Я обновил свой вопрос дополнительным объяснением и образцом псевдокода. Спасибо.
Франческо Абени
Я обновил свой ответ. Проверь это. Я считаю, что я понял, что вам нужно.
Заверн
4

В то время как @ ответ Navern в делает работу, я обнаружил , внедренный jinja2 обозначение ( "{% if env == 'prod' %} ...) чрезвычайно восприимчивы к обозначениям и , таким образом , довольно хрупкие. Например, при переносе рассматриваемой строки для лучшей читабельности, такой как в этом непроверенном коде :

composer_opts: >
               "{% if env == 'prod' %}
                   '--no-dev --optimize-autoloader --no-interaction'
                {% else %}
                   ''
                {% endif %}"

Я закончил с неожиданными результатами, такими как дополнительные пробелы или \nв composer_opts.

Подход, который я использую, гораздо тупее, но также и более устойчив:

- name: set composer_opts for dev env
  set_fact:
     composer_opts: ''
     when: "{{env}}" == 'dev'

- name: set composer_opts for prod env
  set_fact:
     composer_opts: '--no-dev --optimize-autoloader --no-interaction'
     when: "{{env}}" == 'prod'

Я также нашел этот пост в блоге полезным, который по сути следует тому же подходу.

ССК
источник
@sec, если вы используете |вместо >вас, возможно, не будет проблемы с пробелами. (или вы получите больше LOL)
Майкл
@sec Используйте '> -' и проверьте заданную спецификацию. Он имеет много опций для правильного манипулирования многострочными строками. yaml-multiline.info Обратите внимание, в частности, на индикатор чипирования блока.
DylanYoung
Обратите внимание, что у этого решения также были проблемы с приоритетом. Факт не по умолчанию.
DylanYoung
2

Ansible set_fact, основанный на условии в одном лайнере:

- name: "set composer_opts based on environment"
  set_fact:
     composer_opts:  "{{ '--no-dev --optimize-autoloader --no-interaction' if (env == 'prod') else '' }}"
СК Венкат
источник
Те же проблемы приоритетов, что и в других решениях (факт не является значением по умолчанию), однако, если вы поместите это условное право в файл defaults.yml, это решение будет работать. Это становится очень уродливо очень быстро, если у вас есть ряд значений по умолчанию, зависящих от условия
DylanYoung