Problem returning IP address from custom fact

I see this problem when running a custom fact that is trying to return an IP address string.
Ansible reports an empty string, but I see the correct output when I run the fact manually on the target.

Running Ansible 2.2.1.0 on Ubuntu 16.04.
The Vagrant target is running Centos 6.
(I’ve edited out the real IP address below.)

The fact is written like this:

#!/bin/bash
KA_ROLE=$(cat /var/log/keepalived-state)
IP_OWNED=$(ip addr | grep ‘/32’ | grep -Po ‘(\d+.){3}\d+’)
cat <<EOF
{
“role” : “$KA_ROLE”,
“vip” : “$IP_OWNED”
}
EOF

if I run the fact manually on the target it gives the expected output:

./keepalive.fact

{
“role” : “MASTER”,
“vip” : “my.expected.ip.address”
}

But when I run with Ansible, I don’t get the VIP:

$ ansible -m setup -a “filter=ansible_local” -i vagrant radius1
radius1 | SUCCESS => {
“ansible_facts”: {
“ansible_local”: {
“keepalive”: {
“role”: “MASTER”,
“vip”: “”
}
}
},
“changed”: false
}

If I run the script on the target and redirect the output to a file,
then rerun the setup module, I see the correct information is read by
Ansible from the file.

./keepalive.fact > test.fact

radius1 | SUCCESS => {
“ansible_facts”: {
“ansible_local”: {
“keepalive”: {
“role”: “MASTER”,
“vip”: “”
},
“test”: {
“role”: “MASTER”,
“vip”: “my.expected.ip.address”
}
}
},
“changed”: false
}

I first guess is that not all commands is in PATH when it's runs through Ansible.

Mot likely ip which in /sbin, use absolute path to the commands and see if that helps.