Nested facts get clobbered with an update to child fact

102 views
Skip to first unread message

E.C. Raymond

unread,
Sep 28, 2016, 10:53:54 PM9/28/16
to Ansible Project
I am testing on both 1.9.4 and 2.1 and seeing the exact same behavior.

We have a fact.d generator that creates a tree of facts under ansible_local.  We use this to set defaults, but if during playbook execution it needs to update a default, it clobbers the entire ansible_local parent fact. I created a test playbook to replicate the same issue.

---
  - hosts: localhost
    connection: local
    vars:
      my_roles:
        info:
          hardware: "CPU info"
        cmdb:
          local: [{'name':'blah'}]
          remote: False

    tasks:
      - name: set new facts
        set_fact:
        args:
          test_dict: {'name': meh'}

      - name: test
        set_fact:
        args:
          my_roles:
            cmdb:
              local: "{{ my_roles.cmdb.local + ([test_dict]|list) }}"
              remote: True

      - debug: var=my_roles

PLAY [localhost] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [set facts] ***************************************************************
ok: [localhost]

TASK [test] ********************************************************************
ok: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "my_roles": {
        "cmdb": {
            "local": [
                {
                    "name": "blah"
                },
                {
                    "name": "meh"
                }
            ],
            "remote": true
        }
    }
}

PLAY RECAP *********************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0
 
As you can see, the playbook clobbers the parent my_roles and updates with whatever is in the set_fact task.  I have read through various documentation links, and searched around but have not seen anyone come across this specifically.  I understand that ansible uses everything as a string, so taking a fact and then updating obliterates the original fact, but how does one update a nested fact in Ansible? 


Nick

unread,
Sep 30, 2016, 5:41:59 AM9/30/16
to ansible...@googlegroups.com
On 29/09/16 03:53, E.C. Raymond wrote:
> I am testing on both 1.9.4 and 2.1 and seeing the exact same behavior.
>
> We have a fact.d generator that creates a tree of facts under
> ansible_local. We use this to set defaults, but if during playbook
> execution it needs to update a default, it clobbers the entire
> ansible_local parent fact. I created a test playbook to replicate the
> same issue.

I'm no authority, for instance I've not switched to using 2.x versions
of Ansible since I got an essentially functional setup, but I'll chip in
and say I *think* this is normal behaviour when variable scopes are
composed.

I used to try and nest role variables into hierarchies but a long time
ago decided this was simply too fraught when composing them (and this
not even using set_fact). I started treating them as globals (albeit
"with structure"), and naming them with prefixes accordingly: replace
underscores for dots. This resolved my problems at the time.

If it wasn't or is no longer the case, I'd be interested to hear about
it, I'm not aware of anything in the docs which describe scope
composition rules in this level of detail.

N
Reply all
Reply to author
Forward
0 new messages