Problem with function to merge nested dictionaries

458 views
Skip to first unread message

Max Lock

unread,
Nov 18, 2015, 11:59:30 AM11/18/15
to Ansible Project
Hi All,

 I'm using ansible 1.9.3, and want to merge two nested dicts to template to a config file. I've written a combine function similar to whats in 2.n.n. The problem is that the merged dictionary appears to be unicode preventing me from iterating over it in the template. This is the combine function:

def combine(original, update):
   
for key, value in original.items():
       
if not key in update:
            update
[key] = value
       
elif isinstance(value, dict):
            combine
(value, update[key])

   
return update

class FilterModule(object):

   
def filters(self):
       
return {
           
'combine': combine,
       
}

My testcase is this.

---
- hosts: all
  gather_facts
: False
  vars
:
    a
:
      first
:
        second
: 'foo'
    b
:
      first
:
        third
: 'bar'

  tasks
:
   
- set_fact: c="{{ a | combine(b) }}"
   
- debug: var=c
   
- debug: msg="{% print a.__class__ %}"
   
- debug: msg="{% print b.__class__ %}"
   
- debug: msg="{% print c.__class__ %}"...

Which when run produces:

PLAY [all] ********************************************************************

TASK
: [set_fact c="{{ a | combine(b) }}"] *************************************
ok
: [localhost]

TASK
: [debug var=c] ***********************************************************
ok
: [localhost] => {
   
"var": {
       
"c": {
           
"first": {
               
"second": "foo",
               
"third": "bar"
           
}
       
}
   
}
}

TASK
: [debug msg="<class 'jinja2.runtime.StrictUndefined'>"] ******************
ok
: [localhost] => {
   
"msg": "<type 'dict'>"
}

TASK
: [debug msg="<class 'jinja2.runtime.StrictUndefined'>"] ******************
ok
: [localhost] => {
   
"msg": "<type 'dict'>"
}

TASK
: [debug msg="<class 'jinja2.runtime.StrictUndefined'>"] ******************
ok
: [localhost] => {
   
"msg": "<type 'unicode'>"
}

PLAY RECAP
********************************************************************
localhost                  
: ok=5    changed=0    unreachable=0    failed=0


Notice that both parent dicts are of type dict, but the merged child is of type unicode? Any help much appreciated. :)

 -Cheers Max.

Max Lock

unread,
Nov 23, 2015, 6:44:45 AM11/23/15
to Ansible Project

 So this is the solution.

    - set_fact:
        c
: "{{ a | combine(b) }}"

https://github.com/ansible/ansible/issues/5463

 set fact typecasts everything as a string when using key=value syntax. Use yaml syntax and you're good to go.

 Many many thanks to an off list unsung hero....

 -Max.
Reply all
Reply to author
Forward
0 new messages