From 74ca2a676923e330388cce104da6881841fcdaaf Mon Sep 17 00:00:00 2001 From: Roger Luethi Date: Thu, 6 Aug 2026 07:13:30 +0200 Subject: [PATCH] rabbitmq: keep dots in interface fact keys get_rabbitmq_node_addresses() derived the ansible fact name for an interface by replacing both "-" and "." with "_": normalized_interface = internal_interface.replace(".", "_").replace("-", "_") Ansible only replaces "-". PrefixFactNamespace._underscore() is def _underscore(self, name): return name.replace('-', '_') and the setup module prefixes the result with "ansible_", so an interface named br-ex is ansible_br_ex -- but one named bond0.100 is ansible_bond0.100, with the dot intact. Dotted names are the conventional way to name a VLAN interface, so for any deployment using bond0. the lookup asked for ansible_bond0_100, found nothing, and reported Interface bond0.100 (ansible_bond0_100) not found in ansible facts This is independent of the Jinja2 handling further up the function: it happens even when internal_interface is a plain literal with no template in it at all. Drop the dot substitution and keep the dash one. The unit test asserted the old mapping ("eth0.100" -> "ansible_eth0_100"), so it pinned the bug in place; it now asserts the mapping Ansible actually uses. Verified against live fact gathering on ansible-core 2.18.9 and 2.19.11: a real interface named br-e4aefb861457 is cached as ansible_br_e4aefb861457, and PrefixFactNamespace leaves eth0.100 as ansible_eth0.100. Assisted-by: Claude:claude-opus-5 Signed-off-by: Roger Luethi --- osism/utils/rabbitmq.py | 10 +++++----- tests/unit/utils/test_rabbitmq.py | 15 ++++++++------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/osism/utils/rabbitmq.py b/osism/utils/rabbitmq.py index ad5b1dcf3..e11f1f21b 100644 --- a/osism/utils/rabbitmq.py +++ b/osism/utils/rabbitmq.py @@ -92,11 +92,11 @@ def get_rabbitmq_node_addresses(): logger.debug(f"Internal interface for {host}: {internal_interface}") - # Look for the interface in ansible facts - # Interface names with special chars are normalized (e.g., eth0.100 -> ansible_eth0_100) - normalized_interface = internal_interface.replace(".", "_").replace( - "-", "_" - ) + # Look for the interface in ansible facts. Ansible replaces "-" + # with "_" in fact names and leaves dots alone + # (PrefixFactNamespace._underscore), so "br-ex" is + # ansible_br_ex while "bond0.100" is ansible_bond0.100. + normalized_interface = internal_interface.replace("-", "_") interface_key = f"ansible_{normalized_interface}" interface_facts = facts.get(interface_key) diff --git a/tests/unit/utils/test_rabbitmq.py b/tests/unit/utils/test_rabbitmq.py index 874351fce..d061b2974 100644 --- a/tests/unit/utils/test_rabbitmq.py +++ b/tests/unit/utils/test_rabbitmq.py @@ -346,17 +346,18 @@ def test_template_traversal_hits_non_dict_skips_host( _assert_error_logged(loguru_logs, "Could not resolve template") @pytest.mark.parametrize( - "interface,normalized_key", - [("eth0.100", "ansible_eth0_100"), ("eth-0", "ansible_eth_0")], + "interface,fact_key", + [("eth0.100", "ansible_eth0.100"), ("eth-0", "ansible_eth_0")], ) - def test_interface_name_normalized_for_fact_lookup( - self, setup_addresses, loguru_logs, interface, normalized_key + def test_interface_name_mapped_to_fact_key( + self, setup_addresses, loguru_logs, interface, fact_key ): - # Facts are only stored under the normalized key, so a correct lookup - # is the only way the address can be found. + # Facts are only stored under the key Ansible actually uses, so a + # correct mapping is the only way the address can be found. Ansible + # replaces "-" with "_" and keeps dots. setup_addresses( hosts=["host1"], - redis_side_effect=[_facts(normalized_key, "10.0.0.7")], + redis_side_effect=[_facts(fact_key, "10.0.0.7")], check_output=[_GROUP_LISTING, _hostvars(interface)], )