Ansible。覆盖单个字典键

时间:2014-08-05 00:52:29

标签: python yaml ansible

我正在使用ansible管理生产配置以及流浪盒。 我的文件包含默认值: 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 个答案:

答案 0 :(得分:16)

默认情况下,Ansible会覆盖第一级的变量。如果您希望能够合并字典,则必须更改ansible.cfg文件并设置:

hash_behaviour=merge

(默认值为replace)。

请注意Ansible团队does not recommend this(但不解释原因)。 我想这是用户之间真正的划分设置。一种为所有人做过的决定:当你开始使用这个功能时,你不能回去,而你可能无法与replace类型的人共享你的剧本。

然而,您仍然可以从那里的剧本中受益(我不会将剧本作为“特征”使用replace行为)。这就像拥有AB血型,是一个通用的接收器......但由于魔法通常以可变分辨率发生,而不是在任务或模板内部,我认为通常可以在不做任何改动的情况下分享你的角色。

如果您需要覆盖单个键,比如角色参数,则必须以某种复杂的方式传递参数。

例如,要覆盖特定角色的post_max_size字典中的upload_max_sizephp5个键,您必须这样做:

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

这就是说,我从一开始就使用merge行为,我对它很满意。保持变量组织非常方便。

答案 1 :(得分:14)

从Ansible 2.0开始,您可以使用Jinja2 combine过滤器合并YAML哈希/词典,而无需在hash_behavior=merge文件中的全局级别设置ansible.cfg

相关文档:http://docs.ansible.com/ansible/playbooks_filters.html#combining-hashes-dictionaries

答案 2 :(得分:5)

我找到的最好的方法是使用变量作为字典项的值,并覆盖它。我发现这允许简单而强大的变量优先级与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

roles / parent / tasks / 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]中的任何内容,您将获得这些优先级。 / p>

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

答案 3 :(得分:0)

刚尝试使用ansible 1.9.3,它运行正常。不确定,但似乎你只是在group_vars目录(不是groups_vars)的名称中输入错字。