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

Я использую ansible для управления конфигурацией как для производства, так и для vagrant box. У меня есть файл со значениями по умолчанию: 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'

Что я делаю не так?

4 ответа

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

hash_behaviour=merge

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

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

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

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

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

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

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

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

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

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

Роль / родитель / по умолчанию / 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

Роли / родитель / задачи / main.yml & Роли / ребенок / задачи / 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

Только что попробовал с ansible 1.9.3 и работает нормально. Не уверен, но кажется, что вы просто опечатка в имени group_vars каталог (не groups_vars).

Другие вопросы по тегам