Ansible - использовать по умолчанию, если переменная не определена

102

Я настраиваю usersсоздание Linux внутри своей роли. Мне нужно , чтобы пользователи моей роли подгоняет home_directory, group_name, name, password.

Мне было интересно, есть ли более гибкий способ справиться со значениями по умолчанию.

Я знаю, что приведенный ниже код возможен:

- name: Create default
  user:
    name: "default_name"
  when: my_variable is not defined

 - name: Create custom
  user:
    name: "{{my_variable}}"
  when: my_variable is defined

Но, как я уже упоминал, существует множество необязательных переменных, и это создает множество возможностей.

Есть ли что-то вроде приведенного выше кода?

user:
  name: "default_name", "{{my_variable}}"

Код должен быть установлен, name="default_name"если my_variableне определен.

Я мог бы установить все переменные defaults/main.ymlи создать такого пользователя:

- name: Create user
  user:
    name: "{{my_variable}}"

Но эти переменные находятся внутри действительно большого хеша, и внутри него есть хеши, которые не могут быть значениями по умолчанию.

Бернардо Вейл
источник
связанные: stackoverflow.com/questions/19614027/…
Чиро Сантилли 郝海东 冠状 病 六四 事件

Ответы:

193

Вы можете использовать Jinja default:

- name: Create user
  user:
    name: "{{ my_variable | default('default_value') }}"
сеноворошилка42
источник
10
И если переменная по умолчанию зависит от другой переменной. Например default('/home/' {{ anothervar }}), есть ли способ объединить эти значения?
Бернардо Вале
8
Просто удалите 'вокруг, default_valueи он будет использовать переменную с именем default_value
dagonza
7
Не работает, если переменная вложена как {{ dict.key | default(5) }}. Если dictне определено, произойдет сбой .
Джордан Стюарт
1
К вашему сведению, теперь это приведет к ошибке:[WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or {% %}.
Брайан Кеннеди,
1
@JordanStewart У меня был такой же случай - с вложенными переменными. Я опубликовал ответ с возможными решениями ниже.
Роман Круглов
11

Не полностью связано, но вы также можете проверить переменную undefinedAND empty(например my_variable:). (ПРИМЕЧАНИЕ: работает только с доступной версией> 1.9, см .: ссылка )

- name: Create user
  user:
    name: "{{ ((my_variable == None) | ternary('default_value', my_variable)) \
    if my_variable is defined else 'default_value' }}"
Томми Нгуен
источник
2
Это здорово, очень полезно.
eagle33322
5

Если кто-то ищет вариант, который обрабатывает вложенные переменные, в этом выпуске github есть несколько таких вариантов .

Короче говоря, вам нужно использовать фильтр «по умолчанию» для каждого уровня вложенных переменных. Для переменной «a.nested.var» это будет выглядеть так:

- hosts: 'localhost'
  tasks:
    - debug:
        msg: "{{ ((a | default({})).nested | default({}) ).var | default('bar') }}"

или вы можете установить значения по умолчанию для пустых dicts для каждого уровня vars, возможно, используя фильтр «комбинировать». Или используйте фильтр «json_query». Но вариант, который я выбрал, мне кажется более простым, если у вас только один уровень вложенности.

Роман Круглов
источник
4

Если у вас есть одна игра, которую вы хотите перебрать в цикле по элементам, определите этот список в group_vars / all или где-нибудь еще, что имеет смысл:

all_items:
  - first
  - second
  - third
  - fourth

Тогда ваша задача может выглядеть так:

  - name: List items or default list
    debug:
      var: item
    with_items: "{{ varlist | default(all_items) }}"

Передайте список переменных в виде массива JSON:

ansible-playbook <playbook_name> --extra-vars='{"varlist": [first,third]}'

До этого вам также может понадобиться задача, которая проверяет, что каждый элемент в списке переменных также находится в all_items :

  - name: Ensure passed variables are in all_items
    fail:
      msg: "{{ item }} not  in all_items list"
    when: item not in all_items
    with_items: "{{ varlist | default(all_items) }}"
разъем
источник
3

Если вы используете поиск для установки чтения из среды по умолчанию, вы также установили для второго параметра по умолчанию значение true:

- set_facts:
    ansible_ssh_user: "{{ lookup('env', 'SSH_USER') | default('foo', true) }}"

Вы также можете объединить несколько определений по умолчанию:

- set_facts:
    ansible_ssh_user: "{{ some_var.split('-')[1] | default(lookup('env','USER'), true) | default('foo') }}"
пантик
источник
1

Вопрос довольно старый, а как насчет:

- hosts: 'localhost'
  tasks:
    - debug:
        msg: "{{ ( a | default({})).get('nested', {}).get('var','bar') }}"

Мне это кажется менее громоздким ...

pshunter
источник
1

Если вы назначаете значение по умолчанию для логического факта, убедитесь, что внутри default () не используются кавычки.

- name: create bool default
  set_fact:
    name: "{{ my_bool | default(true) }}"

Для других переменных использовался тот же метод, что и в подтвержденном ответе.

- name: Create user
  user:
    name: "{{ my_variable | default('default_value') }}"
Самсельвапрабу
источник