How do I register a variable and persist it between plays targeted on different nodes?

The problem you’re running into is that you’re trying to reference facts/variables of one host from those of another host.

You need to keep in mind that in Ansible, the variable foo assigned to the host localhost is distinct from the variable foo assigned to the host main or any other host.
If you want to access one hosts facts/variables from another host then you need to explicitly reference it via the hostvars variable. There’s a bit more of a discussion on this in this question.

Suppose you have a playbook like this:

- hosts: localhost
  gather_facts: no

  tasks:   
    - command: echo "hello world"
      register: foo


- hosts: localhost
  gather_facts: no

  tasks:
    - debug: 
        var: foo

This will work because you’re referencing the host localhost and localhosts‘s instance of the variable foo in both plays.

The output of this playbook is something like this:

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

TASK: [command] ***************************************************
changed: [localhost]

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

TASK: [debug] *****************************************************
ok: [localhost] => {
    "var": {
        "foo": {
            "changed": true,
            "cmd": [
                "echo",
                "hello world"
            ],
            "delta": "0:00:00.004585",
            "end": "2015-11-24 20:49:27.462609",
            "invocation": {
                "module_args": "echo \"hello world\",
                "module_complex_args": {},
                "module_name": "command"
            },
            "rc": 0,
            "start": "2015-11-24 20:49:27.458024",
            "stderr": "",
            "stdout": "hello world",
            "stdout_lines": [
                "hello world"
            ],
            "warnings": []
        }
    }
}

If you modify this playbook slightly to run the first play on one host and the second play on a different host, you’ll get the error that you encountered.

Solution

The solution is to use Ansible’s built-in hostvars variable to have the second host explicitly reference the first hosts variable.

So modify the first example like this:

- hosts: localhost
  gather_facts: no

  tasks:
    - command: echo "hello world"
      register: foo


- hosts: main
  gather_facts: no

  tasks:
    - debug: 
        var: foo
      when: foo is defined

    - debug: 
        var: hostvars['localhost']['foo']
        ## alternatively, you can use:
        # var: hostvars.localhost.foo
      when: hostvars['localhost']['foo'] is defined

The output of this playbook shows that the first task is skipped because foo is not defined by the host main.
But the second task succeeds because it’s explicitly referencing localhosts‘s instance of the variable foo:

TASK: [debug] *************************************************
skipping: [main]

TASK: [debug] *************************************************
ok: [main] => {
    "var": {
        "hostvars['localhost']['foo']": {
            "changed": true,
            "cmd": [
                "echo",
                "hello world"
            ],
            "delta": "0:00:00.005950",
            "end": "2015-11-24 20:54:04.319147",
            "invocation": {
                "module_args": "echo \"hello world\"",
                "module_complex_args": {},
                "module_name": "command"
            },
            "rc": 0,
            "start": "2015-11-24 20:54:04.313197",
            "stderr": "",
            "stdout": "hello world",
            "stdout_lines": [
                "hello world"
            ],
            "warnings": []
        }
    }
}

So, in a nutshell, you want to modify the variable references in your main playbook to reference the localhost variables in this manner:

{{ hostvars['localhost']['foo'] }}
{# alternatively, you can use: #}
{{ hostvars.localhost.foo }}

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)