From d85583339f91a74d6d9f36b57e2c1e5df2991278 Mon Sep 17 00:00:00 2001 From: Adam Dyess Date: Sun, 10 Mar 2024 12:21:59 -0500 Subject: [PATCH] search for node in calico-early config by stableAddress (#4) --- src/peer.py | 28 ++++++++++++++++++++++++++-- tests/unit/test_peer.py | 14 +++++++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/peer.py b/src/peer.py index 86fb77d..3e7857b 100644 --- a/src/peer.py +++ b/src/peer.py @@ -4,6 +4,7 @@ import socket from ipaddress import ip_address from pathlib import Path +from subprocess import CalledProcessError, check_output from typing import List, Mapping, Optional, Set import yaml @@ -24,6 +25,20 @@ def _read_file_content(path: Path) -> Optional[str]: return path.read_text() if path.exists() else None +def _localhost_ips() -> List[ip_address]: + try: + lo_ifc = yaml.safe_load(check_output(["ip", "--json", "addr", "show", "lo"])) + except (CalledProcessError, yaml.YAMLError): + log.exception("Couldn't fetch the ip addresses of lo") + return [] + return [ + ip_address(addr["local"]) + for ifc in lo_ifc + if ifc["ifname"] == "lo" + for addr in ifc["addr_info"] + ] + + class BGPPeer(BaseModel): """Represents a host interface's bpg peer info.""" @@ -101,10 +116,19 @@ def _early_service_cfg() -> Optional[BGPParameters]: log.warning(f"Couldn't find calico early config in {yaml_location}") return None + stable_address = None + for ip in _localhost_ips(): + if not ip.is_loopback: + stable_address = ip + early_cfg = yaml.safe_load(content) try: - node = early_cfg["spec"]["nodes"][0] - except (TypeError, KeyError, IndexError): + for node in early_cfg["spec"]["nodes"]: + if node["stableAddress"]["address"] == str(stable_address): + break + else: + raise KeyError(f"No node matches {stable_address}") + except (TypeError, KeyError): log.warning(f"Config File didn't contain spec.nodes in config={yaml_location}") return None hostname = socket.gethostname() diff --git a/tests/unit/test_peer.py b/tests/unit/test_peer.py index 6fa7eba..21f4adf 100644 --- a/tests/unit/test_peer.py +++ b/tests/unit/test_peer.py @@ -4,6 +4,7 @@ # Learn more about testing at: https://juju.is/docs/sdk/testing import unittest.mock as mock +from ipaddress import ip_address from textwrap import indent import ops.testing @@ -46,6 +47,17 @@ def early_service(): yield patched +@pytest.fixture +def localhost_ips(): + with mock.patch("peer._localhost_ips") as patched: + patched.return_value = [ + ip_address("127.0.0.1"), + ip_address("10.10.10.1"), + ip_address("::1"), + ] + yield patched + + LOCAL_BGP_PARAMS = """ asNumber: 20001 interfaceAddresses: @@ -79,7 +91,7 @@ def early_service(): }""" -def test_peer_relation_data(harness, charm, early_service): +def test_peer_relation_data(harness, charm, early_service, localhost_ips): rel_id = 0 # peer-relation is always 0 harness.add_relation_unit(rel_id, "calico-enterprise/0") harness.set_leader(True)