ansible

Pass variable within dictionary using other dictionary value


How does one assign a value containing a variable to a dictionary key, when it is using another dictionary value as a parameter.

Example

---
- name: Test vars
  hosts: ['localhost']
  vars:
    foo:
      a: "foo a value"
      b: "{{ a }}"
  tasks:
  - name: Fix owneship and permission issue with sudoers file
    debug:
      msg: Print {{ foo.b }}

I have tried the following:

vars:
  foo:
    a: " foo a value"
    b: "{{ foo.a }}"
vars:
  foo:
    a: " foo a value"
    b: "{{ foo['a'] }}"
vars:
  foo:
    a: " foo a value"
    b: "{{ a }}"

None of the above work.


Solution

  • You can fulfil this requirement using YAML only, via a couple node anchor / alias node.

    In YAML syntax, you can add an anchor before a value, then you can reference it via an alias node.

    An anchor is denoted by the & indicator:

    some_key: &anchor_name value
    

    While an alias is denoted by the * indicator:

    some_other_key: *anchor_name
    

    So, given the task:

    - debug:
        var: foo.b
      vars:
        foo:
          a: &foo_a "foo a value"
          b: *foo_a
    

    This yields the expected:

    ok: [localhost] => 
      foo.b: foo a value
    

    But, indeed, it is just an anchor and alias, you won't be able to compose a value from a literal plus a variable or compose based on multiple variables, e.g. if you want

    ####
    # Please note that this is a counterexample and won't work
    ####
    
    mydict:
      foo: "example {{ mydict.bar }}"
      bar: 123
    

    or

    ####
    # Please note that this is a counterexample and won't work
    ####
    
    mydict:
      foo: "{{ mydict.bar }}{{ mydict.baz }}"
      bar: 123
      baz: 456
    

    You are left with no option, as this is something Ansible does not plan to allow:

    This is expected and not something that we plan on changing. You cannot create a self referential variable.

    Quoted from sivel, maintainer of Ansible, on their issue tracker