Python Ansible。覆盖单个字典键

Python Ansible。覆盖单个字典键,python,yaml,ansible,Python,Yaml,Ansible,我正在使用ansible来管理生产配置以及vagrant box配置。 我有默认值的文件:组变量/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 projectdi

我正在使用ansible来管理生产配置以及vagrant box配置。 我有默认值的文件:组变量/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"
主机变量/vagrant框中我想要一些类似于:

db:
    root_pwd: super_easy_password
但这一个完全覆盖了db dictronial,而我想覆盖单个键。 如何做到这一点

更新1 刚刚使用ansible.cfg进行了检查:

[defaults]
host_key_checking=false
hash_behaviour=merge
组\u vars/all

db:
    root_pwd: some_strong_pwd
    pdo_driver: pdo_mysql
    host: localhost
    name: dbname
    user: dbuser
    pwd: some password
    charset: utf8
寄宿家庭/流浪者箱

db:
    root_pwd: root
我遇到以下错误:

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

我做错了什么?

默认情况下,Ansible在第一级重写变量。如果希望能够合并词典,则必须更改
ansible.cfg
文件并设置:

hash_behaviour=merge
(默认值为
replace

注意Ansible团队(但不解释原因)。 我想这是一个真正的用户划分设置。这是一种一劳永逸的决定:当您开始使用此功能时,您无法返回,并且您可能无法与
replace
-类型的人共享您的剧本

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

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

例如,要覆盖特定角色的
php5
词典中的
post_max_size
upload_max_size
键,您必须这样做:

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

话虽如此,我从一开始就使用
merge
行为,我对此非常满意。将变量组织起来非常方便。

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


相关文档:

刚刚试用了ansible 1.9.3,效果良好。不确定,但似乎您只是在
group\u vars
目录(不是
groups\u vars
)的名称中有一个输入错误。

我发现的最好方法是使用变量作为字典项的值,并覆盖它。我发现这允许简单而强大的变量优先于ansible的变量顺序

角色/parent/defaults/main.yml role/child/defaults/main.yml 注意:
role/child/meta/main.yml
包含
依赖项:-{role:parent}

---
root_pw_value: ChildPassword
玩我吧 roles/parent/tasks/main.yml和roles/child/tasks/main.yml 运行
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\u pw\u值
,例如库存组/主机变量、角色变量、命令行上的额外变量或优先级顺序[0]中的任何内容,您将获得这些变量


[0]

更多地了解为什么它被视为“坏习惯”:TLDR:它鼓励复杂的行为,而ansible创造者认为复杂的行为是坏事。我想每个人都认为复杂的行为是坏事™. 但是说“使用哈希比使用普通变量更复杂”确实是主观的。我个人认为使用散列并不复杂,也不会产生复杂的行为。同样,您可以对配置进行分组,当您有复杂的设置,并且有一个有趣的“范围”副作用时,它最终会使事情更具可读性。它有一个很大的缺点:你不能在同一个散列中重复使用一些散列键值作为一个键值的另一个值(这真的很烦人!)我不理解它的缺点,想详细说明一下吗?您永远不能在同一个哈希中使用同一个键两次。@grasshopper:例如,您不能在同一个dict foo.baz:{{foo.bar}中定义:foo.bar:5和(很抱歉,不可能在注释中添加代码;您必须想象这种“yaml样式”。添加一个操作符以使显式合并仅在需要的地方才可能是有意义的吗?将其作为某种全局魔法是很奇怪的。对于Ansible,您是否碰巧知道如何将
合并
应用于所描述的角色参数?解决这个问题。
---
  - hosts: all
    roles:
      - child
- debug: var=parent_dict
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