Подтвердить что ты не робот

Анзибль. переопределить один ключ словаря

Я использую возможность управлять конфигурацией как для производства, так и для бродячего бокса. У меня есть файл со значениями по умолчанию: group_vars/all.

---
env: prod
wwwuser: www-data

db:
    root_pwd: root_pwd
    pdo_driver: pdo_mysql
    host: localhost
    name: test
    user: test
    pwd: test
    charset: utf8

domain: somedomain
projectdir: /var/www/application
webrootdir: "{{ projectdir }}/web"

В host_vars/vagrantbox Я хочу сделать что-то вроде:

db:
    root_pwd: super_easy_password

Но это одно переопределение полностью db dictrionary, в то время как я хочу переопределить один ключ. Как достичь этого?

ОБНОВЛЕНИЕ 1 Просто проверено с помощью ansible.cfg:

[defaults]
host_key_checking=false
hash_behaviour=merge

groups_vars/все

db:
    root_pwd: some_strong_pwd
    pdo_driver: pdo_mysql
    host: localhost
    name: dbname
    user: dbuser
    pwd: some password
    charset: utf8

host_vars/vagrantbox

db:
    root_pwd: root

Я получаю следующую ошибку:

One or more undefined variables: 'dict object' has no attribute 'name'

Что я делаю неправильно?

4b9b3361

Ответ 1

По умолчанию Ansible переопределяет переменные на первом уровне. Если вы хотите объединить словари, вы должны изменить свой файл ansible.cfg и установить:

hash_behaviour=merge

(значение по умолчанию replace).

Обратите внимание, что команда Ansible не рекомендует это (но не объясняйте почему). Я предполагаю, что это реальное разделение между пользователями. Одно решение для всех: когда вы начинаете использовать эту функцию, вы не можете вернуться, и вы, вероятно, не сможете поделиться своим плейером с людьми replace.

Тем не менее, вы по-прежнему можете пользоваться учебниками для воспроизведения (я не считаю, что в книжных играх используется поведение replace как "функция" ). Это похоже на наличие типа крови AB, являющегося универсальным приемником... но поскольку магия обычно происходит при переменном разрешении, а не внутри задач или шаблонов, я думаю, что часто можно делиться своими ролями без каких-либо изменений.

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

Например, чтобы переопределить ключи post_max_size и upload_max_size в php5 dictionnary для определенной роли, вам придется сделать это следующим образом:

- { role: php5-fpm, php5: { post_max_size: 40M,
                            upload_max_filesize: 20M }}

При этом я использую поведение merge с самого начала, и я очень доволен им. Это очень удобно для сохранения переменных.

Ответ 2

Начиная с Ansible 2.0, вы можете использовать фильтр Jinja2 combine для объединения хэшей/словарей YAML без необходимости устанавливать hash_behavior=merge на глобальном уровне в вашем файле ansible.cfg.

Соответствующие документы: http://docs.ansible.com/ansible/playbooks_filters.html#combining-hashes-dictionaries

Ответ 3

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

Роль/родителя/дефолты/main.yml

---
root_pw_value: ParentPassword

parent_dict:
  - root_pw: "{{ root_pw_value }}"

Роль/ребенок/дефолты/main.yml

Примечание: role/child/meta/main.yml содержит dependencies: - { role: parent }

---
root_pw_value: ChildPassword

плей-me.yml

---
  - hosts: all
    roles:
      - child

role/parent/tasks/main.yml и role/child/tasks/main.yml

- debug: var=parent_dict

Запустите ansible -i localhost, --connection="local" play-me.yml и вы получите следующий вывод:

PLAY [all] ******************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [localhost]

TASK: [parent | debug var=parent_dict] **************************************** 
ok: [localhost] => {
    "var": {
        "parent_dict": [
            {
                "root_pw": "ParentPassword"
            }
        ]
    }
}

TASK: [child | debug var=parent_dict] ***************************************** 
ok: [localhost] => {
    "var": {
        "parent_dict": [
            {
                "root_pw": "ChildPassword"
            }
        ]
    }
}

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

И это значения по умолчанию. Если вы укажете root_pw_value на более определенных уровнях приоритета, таких как переменные группы инвентаря/хоста, переменные роли, extra_vars в командной строке или что-нибудь из порядка приоритета [0], вы получите их.

[0] http://docs.ansible.com/ansible/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable

Ответ 4

Просто попробовал с помощью 1.9s 1.9, и он отлично работает. Не уверен, но кажется, что у вас есть только опечатка в имени каталога group_vars (не groups_vars).