ansible: accessing register variables from other p

2019-02-25 13:53发布

问题:

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.

回答1:

  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:

  • Register variables don't survive across plays with different hosts
  • set_fact - Set host facts from a task
  • debug - Print statements during execution