Ansible.覆盖单个字典键

Jev*_*nov 26 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"
Run Code Online (Sandbox Code Playgroud)

host_vars/vagrantbox中我希望有类似的东西:

db:
    root_pwd: super_easy_password
Run Code Online (Sandbox Code Playgroud)

但是这个完全超越db dictrionary,而我想覆盖单键.怎么实现呢?

更新1 刚用ansible.cfg检查:

[defaults]
host_key_checking=false
hash_behaviour=merge
Run Code Online (Sandbox Code Playgroud)

groups_vars /所有

db:
    root_pwd: some_strong_pwd
    pdo_driver: pdo_mysql
    host: localhost
    name: dbname
    user: dbuser
    pwd: some password
    charset: utf8
Run Code Online (Sandbox Code Playgroud)

host_vars/vagrantbox

db:
    root_pwd: root
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

One or more undefined variables: 'dict object' has no attribute 'name'
Run Code Online (Sandbox Code Playgroud)

我做错了什么?

leu*_*cos 18

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

hash_behaviour=merge
Run Code Online (Sandbox Code Playgroud)

(默认值为replace).

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

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

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

例如,要覆盖post_max_sizeupload_max_size键入php5特定角色的字典,您必须这样做:

- { role: php5-fpm, php5: { post_max_size: 40M,
                            upload_max_filesize: 20M }}
Run Code Online (Sandbox Code Playgroud)

话虽这么说,我merge从一开始就使用行为,我很高兴.保持变量组织非常方便.

  • 当然,添加运算符以便只在需要的地方进行显式合并是有意义的吗?把它当作某种全球魔术只是奇怪的. (4认同)
  • 我想每个人都将复杂的行为视为 BadThing™。但是说“使用哈希比普通变量更复杂”真的很主观。我个人认为使用散列并不复杂或产生复杂的行为。同样,您可以对您的配置进行分组,当您有复杂的设置时,它最终会让事情变得更具可读性,并且有一个有趣的“范围”副作用。但是它有一个*大*缺点:您不能将某些散列键值重用为同一散列中键的另一个值(这真的很烦人!) (2认同)
  • @grasshopper:例如,你不能定义:foo.bar:5并且在同一个dict中foo.baz:{{foo.bar}}(对不起,不可能把代码放在评论中;你必须想象这个"YAML式". (2认同)

Jef*_*man 15

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

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


Mea*_*ode 6

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

角色/父母/默认/ main.yml

---
root_pw_value: ParentPassword

parent_dict:
  - root_pw: "{{ root_pw_value }}"
Run Code Online (Sandbox Code Playgroud)

角色/小孩/默认/ main.yml

注意:role/child/meta/main.yml包含dependencies: - { role: parent }

---
root_pw_value: ChildPassword
Run Code Online (Sandbox Code Playgroud)

播放me.yml

---
  - hosts: all
    roles:
      - child
Run Code Online (Sandbox Code Playgroud)

roles/parent/tasks/main.yml&roles/child/tasks/main.yml

- debug: var=parent_dict
Run Code Online (Sandbox Code Playgroud)

运行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
Run Code Online (Sandbox Code Playgroud)

这些是默认值.如果您指定root_pw_value更具体的优先级,例如库存组/主机变量,角色变量,命令行上的extra_vars,或者优先顺序[0]中的任何内容,您将获得这些优先级.

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