Dictionary lookups being clobbered when assigning values to children elsewhere

47 views
Skip to first unread message

cmacrae

unread,
Nov 15, 2015, 8:37:27 AM11/15/15
to Ansible Project
Hey People,

Having some trouble using YAML dictionaries.
I'm refactoring my variable structure in a role a wrote a while ago.

The variables used to all look like: sensu_api_host, but I wanted to move to using dictionaries, so when referencing them it wouldn't be:
{{ sensu_api_host }}
it'd be:
{{ sensu['api']['host'] }}

In doing so, I've restructured my roles' defaults/main.yml like so:
sensu:
  api
:
    host
: "{{ groups['sensu_masters'][0] }}"
    port
: 4567
    ssl
: "false"
    user_name
: admin
    password
: secret
    uchiwa_path
: ''
    timeout
: 5000
  client_config
: client.json.j2
  config_path
: /opt/local/etc/sensu
  gem_state
: present
  plugin_gem_state
: present
  user_name
: sensu
  group_name
: sensu
  include_plugins
: true
  include_dashboard
: false
  master
: false

Though, I have a problem. Lookups for the above variables work fine... until I try to assign them values elsewhere, where it should take precedence. Some of the key values above are clobbered when they are defined elsewhere, such as host_vars/hostname.yml or group_vars/groupname.yml. It seems that if I want to define one of the nested keys' value elsewhere, it ruins the dictionary lookup for all other child keys who share that parent. For example, above you can see that sensu['include_dashboard'] is set to false. If I want to set this to `true` for a particular host, in host_vars/hostname.yml like so:
---
sensu
:
  include_dashboard
: true
This then clobbers the lookup for any other child keys belonging to the sensu dictionary. So, for example, lookups for sensu['group_name'] will fail with the following: fatal: [my.host.tld] => One or more undefined variables: 'dict object' has no attribute 'group_name' When trying to evaluate the following play:
  - name: Ensure the Sensu group is present
   
group: name={{ sensu['group_name'] }}
           state
=present

I'm not sure what it is I'm doing wrong here - I'd really appreciate any help!
For the record: I'm running Ansible 1.9.4

Thanks in advance,
Calum

Rob Wilkerson

unread,
Nov 15, 2015, 10:43:35 AM11/15/15
to Ansible Project
I'm still new to Ansible, but my understanding is that it overwrites variables by default, including dictionary variables. This is because the default value for hash_behavior setting is "replace". If you change that config value to "merge", you'll see the behavior you're expecting, I believe.

I don't fully understand why replace is preferred, but I've found it easier to just avoid dictionary variables just to keep things simple. Seems like some changes have been made in v2.0.

Matt Martz

unread,
Nov 15, 2015, 10:47:47 AM11/15/15
to ansible...@googlegroups.com
The default behavior of Ansible is to "replace" the entire data structure instead of merging it.  This is defined/configured by the hash_behavior parameter in an ansible.cfg file.

Because switching to merge is a process that requires a user to modify their Ansible configuration, I feel that is most appropriate to *not* use nested data structures where you expect users to provide configurations for your role, but instead use what you were doing previously with sensu_api_host.
--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/01207bb1-325a-4d80-93ad-ab501a60d422%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
Matt Martz
@sivel
sivel.net

cmacrae

unread,
Nov 15, 2015, 1:11:07 PM11/15/15
to Ansible Project
You're absolutely right - thanks for taking the time to point this out!

cmacrae

unread,
Nov 15, 2015, 1:11:40 PM11/15/15
to Ansible Project
Thanks, Matt.
In that case, I'll keep it the way I've written it :)

On Sunday, 15 November 2015 15:47:47 UTC, Matt Martz wrote:
The default behavior of Ansible is to "replace" the entire data structure instead of merging it.  This is dAhefined/configured by the hash_behavior parameter in an ansible.cfg file.

To unsubscribe from this group and stop receiving emails from it, send an email to ansible-project+unsubscribe@googlegroups.com.
To post to this group, send email to ansible-project@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages