ipaddr is too eager to evaluate variables types
cosandr opened this issue · 0 comments
SUMMARY
Please excuse bad title, I really don't know what to call this. The issue is fairly straight forward to test for. This could affect other modules, but I've only experienced it with the ipaddr
filter. The problem is with the input validation being too eager, most clearly visible when trying to use hostvars
(see replication steps below).
This patch fixes the issue but it changes the behavior at runtime as well, although I'd argue it's more consistent with other modules.
diff --git a/plugins/filter/ipaddr.py b/plugins/filter/ipaddr.py
index 0ed9865..3e87309 100644
--- a/plugins/filter/ipaddr.py
+++ b/plugins/filter/ipaddr.py
@@ -11,6 +11,7 @@ from __future__ import absolute_import, division, print_function
from functools import partial
from ansible.errors import AnsibleFilterError
+from ansible.template import AnsibleUndefined
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
AnsibleArgSpecValidator,
@@ -263,6 +264,8 @@ def _ipaddr(*args, **kwargs):
pass
elif isinstance(data["value"], int):
pass
+ elif isinstance(data["value"], AnsibleUndefined):
+ pass
else:
raise AnsibleFilterError(
"Unrecognized type <{0}> for ipaddr filter <{1}>".format(
With this patch you will get "test": "VARIABLE IS NOT DEFINED!"
at runtime instead of an exception.
The output of hostvars
with the patch is consistent with other modules, they're displayed as is (in raw form) until actually used at runtime where they're evaluated. Someone more familiar with the code base may decide if this is the right way to fix it, if it is I'd gladly open a PR if desired.
ISSUE TYPE
- Bug Report
COMPONENT NAME
ansible.utils.ipaddr
ANSIBLE VERSION
ansible [core 2.15.2]
config file = /home/andrei/src/ansible-test/ansible.cfg
configured module search path = ['/home/andrei/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.11/site-packages/ansible
ansible collection location = /home/andrei/src/ansible
executable location = /usr/bin/ansible
python version = 3.11.3 (main, Jun 5 2023, 09:32:32) [GCC 13.1.1 20230429] (/usr/bin/python)
jinja version = 3.1.2
libyaml = True
COLLECTION VERSION
# /home/andrei/src/ansible/ansible_collections
Collection Version
------------- -------
ansible.utils 2.10.4
# /usr/lib/python3.11/site-packages/ansible_collections
Collection Version
------------- -------
ansible.utils 2.10.3
CONFIGURATION
COLLECTIONS_PATHS(/home/andrei/src/ansible-test/ansible.cfg) = ['/home/andrei/src/ansible']
CONFIG_FILE() = /home/andrei/src/ansible-test/ansible.cfg
DEFAULT_HOST_LIST(/home/andrei/src/ansible-test/ansible.cfg) = ['/home/andrei/src/ansible-test/hosts.yml']
EDITOR(env: EDITOR) = vim
PAGER(env: PAGER) = less
OS / ENVIRONMENT
Arch, this issue is OS agnostic.
STEPS TO REPRODUCE
Inventory
all:
hosts:
a:
test:
- "10.0.0.1"
- "10.0.0.2"
b:
test: "{{ hostvars['a'].test | ansible.utils.ipaddr('host') }}"
Config
[defaults]
inventory = hosts.yml
# This is here so I could test my changes, it only contains a clone of this repo's main branch
collections_path = ~/src/ansible
EXPECTED RESULTS
$ ansible b -m debug -a var=test
b | SUCCESS => {
"test": [
"10.0.0.1/32",
"10.0.0.2/32"
]
}
$ ansible localhost -m debug -a msg="{{ hostvars['b'] }}"
localhost | SUCCESS => {
"msg": {
"ansible_check_mode": false,
"ansible_config_file": "/home/andrei/src/ansible-test/ansible.cfg",
"ansible_diff_mode": false,
"ansible_facts": {},
"ansible_forks": 5,
"ansible_inventory_sources": [
"/home/andrei/src/ansible-test/hosts.yml"
],
"ansible_playbook_python": "/usr/bin/python",
"ansible_verbosity": 0,
"ansible_version": {
"full": "2.15.2",
"major": 2,
"minor": 15,
"revision": 2,
"string": "2.15.2"
},
"group_names": [
"ungrouped"
],
"groups": {
"all": [
"a",
"b"
],
"ungrouped": [
"a",
"b"
]
},
"inventory_dir": "/home/andrei/src/ansible-test",
"inventory_file": "/home/andrei/src/ansible-test/hosts.yml",
"inventory_hostname": "b",
"inventory_hostname_short": "b",
"playbook_dir": "/home/andrei/src/ansible-test",
"test": "{{ hostvars['a'].test | ansible.utils.ipaddr('host') }}"
}
}
ACTUAL RESULTS
$ ansible b -m debug -a var=test
b | SUCCESS => {
"test": [
"10.0.0.1/32",
"10.0.0.2/32"
]
}
$ ansible localhost -m debug -a msg="{{ hostvars['b'] }}"
localhost | FAILED! => {
"msg": "Unrecognized type <<class 'ansible.template.AnsibleUndefined'>> for ipaddr filter <value>"
}