Selecting attributes from a registered variable

I’m trying to use “gluster_heal_info” to retrieve the “no_of_entries” attribute. When I print out the values that gluster_heal_info returns, I see that this attribute exists:

storage1 | SUCCESS => {
“msg”: {
“brick”: " storage1-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
}
}

If I try to retrieve that attribute as follows:

  • name: Find out the healing status of /home
    gluster_heal_info:
    name: home
    status_filter: self-heal
    register: home_heal_status

until: home_heal_status.glusterfs.heal_info | selectattr(‘no_of_entries’,‘ne’,‘0’) | list | count == 0

I get the error: The task includes an option with an undefined variable. The error was: ‘dict object’ has no attribute ‘no_of_entries’.

This worked until a few weeks ago, so I’m wondering if either: a) something changed in the module in the Ansible version we’re using (2.9.16), or b) I was not using the syntax correctly and there was a false positive.

So how do I use selectattr to retrieve the ‘no_of_entries’ attribute?

Thanks,
Harry

What a module returns is not entirely the same as the variable value when using “register”.

Can you register the result and show what that values is (using debug task)?

I register the variable from the “gluster_heal_info” module and here’s the printout of it. I can shorten it if this is too long or too much to look at. Basically, I’m trying to gather the “no_of_entries” attribute from each gluster brick and sum them together and make sure that it equals zero. That means that no healing is going on, so I can then shut down the glusterd service and to a “yum update”.

Thanks,
Harry

storage1 | SUCCESS => {
“msg”: {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/bin/python”
},
“changed”: false,
“failed”: false,
“glusterfs”: {
“heal_info”: [
{
“brick”: " storage1-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage2-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage3-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage2-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage3-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage4-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage3-storage:/gluster_bricks/brick3/1"
},
{
“no_of_entries”: “6”,
“status”: “Connected”
},
{
“brick”: " storage4-storage:/gluster_bricks/brick4/1"
},
{
“no_of_entries”: “6”,
“status”: “Connected”
},
{
“brick”: " storage5-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage4-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage5-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage6-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage5-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage6-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage7-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage6-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage7-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage8-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage7-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage8-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage9-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage8-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage9-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage1-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage9-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage1-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage2-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
}
],
“rebalance”: “”,
“status_filter”: “self-heal”,
“volume”: “home”
}
}
}

I register the variable from the "gluster_heal_info" module and here's the printout of it. I can shorten it if this is
too long or too much to look at. Basically, I'm trying to gather the "no_of_entries" attribute from each gluster brick
and sum them together and make sure that it equals zero. That means that no healing is going on, so I can then shut down
the glusterd service and to a "yum update".

Thanks,
Harry

Hello Harry,

I think the problem is that not all dictionary entries carry a "no_of_entries" value.
This is likely to cause the undefined variable error.

Regards
         Racke

I understand that, but the variable that I register DOES return that as per my last email. But when I try to select it to use it, I get that error. Here’s my playbook for illustration:

Just to be sure, what is the output of the var (not the msg)?

I.e.:

- debug: var=home_heal_status

It appears that some healing on the gluster volume is going on, which could by why some of the attributes appear to be missing. But no_of_entries is there on most.

storage1 | SUCCESS => {
“home_heal_status”: {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/bin/python”
},
“changed”: false,
“failed”: false,
“glusterfs”: {
“heal_info”: [
{
“brick”: " storage1-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage2-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage3-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage2-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage3-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage4-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage3-storage:/gluster_bricks/brick3/1"
},
{
“no_of_entries”: “6”,
“status”: “Connected”
},
{
“brick”: " storage4-storage:/gluster_bricks/brick4/1"
},
{
“no_of_entries”: “6”,
“status”: “Connected”
},
{
“brick”: " storage5-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage4-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage5-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage6-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage5-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage6-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage7-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage6-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage7-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage8-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage7-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage8-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage9-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage8-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage9-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage1-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage9-storage:/gluster_bricks/brick3/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage1-storage:/gluster_bricks/brick4/1",
“no_of_entries”: “0”,
“status”: “Connected”
},
{
“brick”: " storage2-storage:/gluster_bricks/arbiter2/1",
“no_of_entries”: “0”,
“status”: “Connected”
}
],
“rebalance”: “”,
“status_filter”: “self-heal”,
“volume”: “home”
}
}
}

Harry

This would evaluate to 12 in your example:

"{{ home_heal_status|from_json|json_query('glusterfs.heal_info.no_of_entries')|map('int')|
sum }}"

is that what you want?

It is, but I can’t get that to evaluate:

“msg”: “Unexpected templating type error occurred on ({{ home_heal_status|from_json|json_query(‘glusterfs.heal_info.no_of_entries’)|map(‘int’)|sum }}): the JSON object must be str, bytes or bytearray, not ‘dict’”

Here’s what I tried:

  • name: Print /home status
    debug:
    msg: “{{ home_heal_status|from_json|json_query(‘glusterfs.heal_info.no_of_entries’)|map(‘int’)|sum }}”

Thanks,
Harry

Ah sorry , remove the from_json bit

OK, that worked in the debug message. Just trying to figure out how to use it in the “until” statement. The main goal is to have the sum be 0 and then continue on. If its not 0 after a certain number of tries, then we fail out of the playbook.

Thanks,
Harry

OK, that worked in the debug message. Just trying to figure out how to use it in the "until" statement. The main goal
is to have the sum be 0 and then continue on. If its not 0 after a certain number of tries, then we fail out of the
playbook.

Thanks,
Harry

My guess would be

   until: home_heal_status|json_query('glusterfs.heal_info.no_of_entries')|map('int')|sum == 0

Regards
         Racke