ansible: accessing register variables from other plays within same playbook

18,584
  1. Register variables, like facts, are per host. The values can differ depending on the machine. So you can only use host/ip defined in the inventory as key, not the group name. I think you have already knowed this, as you marked this in code snippet 1.

  2. In the code snippet 2, the set_fact line (- set_fact: the_count=result.stdout) actually set the key the_count to the text value result.stdout, since result.stdout is treated as plain text, not a variable. If you want to treat it as a variable, you'd better use {{ result.stdout }}. You can verify this via running the playbook with -v option.

    Tasks:

    • set_fact: the_content1=content.stdout
    • set_fact: the_content2={{ content.stdout }}

    Output:

    TASK [set_fact] ****************************************************************
    ok: [192.168.1.58] => {"ansible_facts": {"the_content1": "content.stdout"}, "changed": false}
    
    TASK [set_fact] ****************************************************************
    ok: [192.168.1.58] => {"ansible_facts": {"the_content2": "hello world"}, "changed": false}
    
  3. The debug module has two possible parameter: var and msg. The var parameter expect a variable name.

    • debug: var={{hostvars}}

    In this line, first of all, Ansible extracts the value of hostvars, since it is enclosed with two brackets. Secondly, it tries to find a variable whose name is the value of hostvars, since var parameter expects a variable name directly. That is why you see the following strange output. This means Ansible couldn't find a variable whose name is <ansible.vars.hostvars.HostVars object at 0x7f3b6602b290>.

    "<ansible.vars.hostvars.HostVars object at 0x7f3b6602b290>": "VARIABLE IS NOT DEFINED!"
    

    You can use the following:

    • debug: var=hostvars
    • debug: msg={{hostvars}}

References:

Share:
18,584
dot
Author by

dot

Updated on June 13, 2022

Comments

  • dot
    dot almost 2 years

    I'm trying to access the variable called "count" from the first "play" in my playbook in the second playbook. I found some other posts here about the same issue and I thought I was following the right steps, but the code below is still failing.

    The Code

    - hosts: group1
      tasks:
      - name: count registrations on primary node
        shell: psql -U widgets widgets -c 'SELECT COUNT(*) FROM location' -t
        register: count
      - debug: var=count.stdout
    
    - hosts: group2
      tasks:
    #the line below works...
    #  - debug: msg={{ hostvars['myserver1.mydomain.com']['count']['stdout'] }}
    # but this one fails
      - debug: msg={{ hostvars['group1']['count']['stdout'] }}
    

    This produces the following output:

    PLAY ***************************************************************************
    
    TASK [setup] *******************************************************************
    ok: [myserver1.mydomain.com]
    
    TASK [count registrations on node] **************************************
    changed: [myserver1.mydomain.com]
    
    TASK [debug] *******************************************************************
    ok: [myserver1.mydomain.com] => {
        "count.stdout": "     2"
    }
    
    PLAY ***************************************************************************
    
    TASK [setup] *******************************************************************
    ok: [myserver2.mydomain.com]
    
    TASK [debug] *******************************************************************
    fatal: [myserver1.mydomain.com]: FAILED! => {"failed": true, "msg": "'ansible.vars.hostvars.HostVars object' has no attribute 'can_sip1'"}
    
    NO MORE HOSTS LEFT *************************************************************
     [ERROR]: Could not create retry file 'playbooks/test.retry'. The error was: [Errno 13] Permission denied: 'playbooks/test.retry'
    
    
    PLAY RECAP *********************************************************************
    

    myserver1.mydomain.com : ok=3 changed=1 unreachable=0 failed=0
    myserver2.mydomain.com : ok=1 changed=0 unreachable=0 failed=1

    The other post that I referring to is found here: How do I set register a variable to persist between plays in ansible?

    It's probably something simple, but I can't see where the bug lies. Thanks.

    EDIT 1

    I've also tried to use set_fact like this:

    - hosts: group1
      tasks:                                  
      - name: count registrations on primary node        
        shell: psql -U widget widget -c 'SELECT COUNT(*) FROM location' -t
        register: result                      
      - debug: var=result.stdout              
      - set_fact: the_count=result.stdout
      - debug: var={{the_count}}              
    
    - hosts: group2                        
      tasks:                                  
      - name: retrieve variable from previous play
        shell: echo hello                     
      - debug: var={{hostvars}}
    

    The results I get are:

    PLAY ***************************************************************************
    
    TASK [setup] *******************************************************************
    ok: [myserver1.mydomain.com]
    
    TASK [count reg on primary] ****************************************************
    changed: [myserver1.mydomain.com]
    
    TASK [debug] *******************************************************************
    ok: [myserver1.mydomain.com] => {
        "result.stdout": "     2"
    }
    
    TASK [set_fact] ****************************************************************
    ok: [myserver1.mydomain.com]
    
    TASK [debug] *******************************************************************
    ok: [myserver1.mydomain.com] => {
        "result.stdout": "     2"
    }
    
    PLAY ***************************************************************************
    
    TASK [setup] *******************************************************************
    ok: [myserver2.mydomain.com]
    
    TASK [retrieve variable from previous play] ************************************
    changed: [myserver2.mydomain.com]
    
    TASK [debug] *******************************************************************
    ok: [myserver2.mydomain.com] => {
        "<ansible.vars.hostvars.HostVars object at 0x7f3b6602b290>": "VARIABLE IS NOT DEFINED!"
    }
    
    PLAY RECAP *********************************************************************
    myserver1.mydomain.com        : ok=5    changed=1    unreachable=0    failed=0   
    myserver2.mydomain.com       : ok=3    changed=1    unreachable=0    failed=0   
    

    So It looks like there are no objects in the hostvars...

    EDIT 3

    This is what the playbook looks like this morning.

    - hosts: group1
      tasks:
      - name: count reg on primary
        shell: psql -U widgets widgets -c 'SELECT COUNT(*) FROM location' -t
        register: result
      - debug: var=result.stdout
      - set_fact: the_count={{result.stdout}} 
      - debug: var={{the_count}}
    
    - hosts: group2
      tasks:
      - name: retrieve variable from previous play
        shell: echo hello
      - debug: var={{hostvars}}    
    

    The "debug: var={{the_count}}" line from the first play prints out the correct value for the count but it also says the VARIABLE IS NOT DEFINED... like so:

    TASK [set_fact] **************************************************************** task path: /etc/ansible/playbooks/test.yml:8 ok: [myserver1.mydomain.com] => {"ansible_facts": {"the_count": " 2"}, "changed": false, "invocation": {"module_args": {"the_count": " 2"}, "module_name": "set_fact"}}

    TASK [debug] ******************************************************************* task path: /etc/ansible/playbooks/test.yml:10 ok: [myserver1.mydomain.com] => { " 2": "VARIABLE IS NOT DEFINED!" }

    And then once I hit the second play, I still get the message

    TASK [debug] *******************************************************************
    task path: /etc/ansible/playbooks/test.yml:16
    ok: [myserver2.mydomain.com] => {
        "<ansible.vars.hostvars.HostVars object at 0x7fb077fdc310>": "VARIABLE IS NOT DEFINED!"
    }
    

    In your example, you are suggestion that I use "debug: var={{hostlers}}". If you can clarify that for me please. It looks like it's a typo.

    EDIT 4:

    If you take a look at Edit 3 carefully, you will see that I have implemented "debug:var={{hostvars}}" as you suggest in your answer. But it gives me the same error that the variable is not defined. I'm not just trying to pass variables from one play to another.. but from one set of hosts to another. Notice how play 1 uses group1 and play two applies only to group2.

  • longhua
    longhua about 8 years
    @dot The error message in your edit 3 means Ansible tries to lookup a variable whose name is 2, however it doesn't exist. Would you please check my answer #3? The var parameter for debug expects a variable name in plain text. And {{the_count}} provides the value 2 of the_count variable. So Ansible tries to lookup a variable with the name 2.
  • longhua
    longhua about 8 years
    @dot I am sorry I meant to use msg parameter of debug module.
  • dot
    dot about 8 years
    it's okay. would you be able to chat for a few minutes instead of going back and forth here?