Looking at Ansible’s documentation on variable precedence makes my head spin a bit: there are many sources for variable data. ;-)

I’m repeating the rules here to avoid us having to flip back and forth:

  1. Variables loaded from YAML files mentioned in vars_files in a playbook.
  2. vars as defined in the playbook.
  3. facts, whether built in or custom, or variables assigned from the register keyword.
  4. variables passed to parameterized task include statements.
  5. Host variables from inventory.
  6. Group variables from inventory, in order of least specific group to most specific.

I’m finding it difficult to get this into a decent diagram, so take this with a pinch or two of salt, please. I’ve also omitted a few sources of variables for “clarity”:

ansible variable precedence

The further down we get in the diagram, the higher the precedence, i.e. variables declared further down overwrite values defined above.

The documentation states:

if you want to set a default value for something you wish to override somewhere else, the best place to set such a default is in a group variable.

and I agree: I can then override a variable on a per-host basis by creating a host_vars/hostname file for example. (See also Michael DeHaan’s comment below.)

Register variables

In version 0.7 Ansible can store the output of a given command in a variable which I use later on in templates, say. The register keyword names the variable.

- hosts:
  connection: local
  - person: Jane Jolie
  - filename: v1.j2
  - vars.yml
  - name: Quien soy?
    action: command /usr/bin/whoami
    register: myname
  - name: Run jpprog.sh
    action: command ./jpprog.sh
    register: v

  - name: Populate template
    action: template src={{filename}} dest=/tmp/out

This playbook runs two commands: the first stores its output in a variable called myname, and the second in a variable v. The result of whoami is a single string which is made available to the template as variablename.stdout. The result of jpprog.sh is a JSON object represented as a string:

    "number": 18,
    "name": "john"

The template follows:

-> I am {{ myname.stdout }}

{% set t = v.stdout|from_json %}

JSON struct T: {{ t }}

name = {{ t.name }} 
number = {{ t['number'] }} 

and the output is:

-> I am jpm

JSON struct T: {u'number': 18, u'name': u'john'}

name = john 
number = 18 

I thought extracting JSON from a command could be pretty useful and contributed a small patch earlier. Basically this is just a different way of obtaining facts: instead of writing a module we use register variables.