summaryrefslogtreecommitdiff
path: root/tests/unittests/test_net_activators.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unittests/test_net_activators.py')
-rw-r--r--tests/unittests/test_net_activators.py262
1 files changed, 262 insertions, 0 deletions
diff --git a/tests/unittests/test_net_activators.py b/tests/unittests/test_net_activators.py
new file mode 100644
index 00000000..3c29e2f7
--- /dev/null
+++ b/tests/unittests/test_net_activators.py
@@ -0,0 +1,262 @@
+from collections import namedtuple
+from unittest.mock import patch
+
+import pytest
+
+from cloudinit.net.activators import (
+ DEFAULT_PRIORITY,
+ IfUpDownActivator,
+ NetplanActivator,
+ NetworkdActivator,
+ NetworkManagerActivator,
+ NoActivatorException,
+ search_activator,
+ select_activator,
+)
+from cloudinit.net.network_state import parse_net_config_data
+from cloudinit.safeyaml import load
+
+V1_CONFIG = """\
+version: 1
+config:
+- type: physical
+ name: eth0
+- type: physical
+ name: eth1
+"""
+
+V2_CONFIG = """\
+version: 2
+ethernets:
+ eth0:
+ dhcp4: true
+ eth1:
+ dhcp4: true
+"""
+
+NETPLAN_CALL_LIST = [
+ ((["netplan", "apply"],), {}),
+]
+
+
+@pytest.fixture
+def available_mocks():
+ mocks = namedtuple("Mocks", "m_which, m_file")
+ with patch("cloudinit.subp.which", return_value=True) as m_which:
+ with patch("os.path.isfile", return_value=True) as m_file:
+ yield mocks(m_which, m_file)
+
+
+@pytest.fixture
+def unavailable_mocks():
+ mocks = namedtuple("Mocks", "m_which, m_file")
+ with patch("cloudinit.subp.which", return_value=False) as m_which:
+ with patch("os.path.isfile", return_value=False) as m_file:
+ yield mocks(m_which, m_file)
+
+
+class TestSearchAndSelect:
+ def test_defaults(self, available_mocks):
+ resp = search_activator()
+ assert resp == DEFAULT_PRIORITY
+
+ activator = select_activator()
+ assert activator == DEFAULT_PRIORITY[0]
+
+ def test_priority(self, available_mocks):
+ new_order = [NetplanActivator, NetworkManagerActivator]
+ resp = search_activator(priority=new_order)
+ assert resp == new_order
+
+ activator = select_activator(priority=new_order)
+ assert activator == new_order[0]
+
+ def test_target(self, available_mocks):
+ search_activator(target="/tmp")
+ assert "/tmp" == available_mocks.m_which.call_args[1]["target"]
+
+ select_activator(target="/tmp")
+ assert "/tmp" == available_mocks.m_which.call_args[1]["target"]
+
+ @patch(
+ "cloudinit.net.activators.IfUpDownActivator.available",
+ return_value=False,
+ )
+ def test_first_not_available(self, m_available, available_mocks):
+ resp = search_activator()
+ assert resp == DEFAULT_PRIORITY[1:]
+
+ resp = select_activator()
+ assert resp == DEFAULT_PRIORITY[1]
+
+ def test_priority_not_exist(self, available_mocks):
+ with pytest.raises(ValueError):
+ search_activator(priority=["spam", "eggs"])
+ with pytest.raises(ValueError):
+ select_activator(priority=["spam", "eggs"])
+
+ def test_none_available(self, unavailable_mocks):
+ resp = search_activator()
+ assert resp == []
+
+ with pytest.raises(NoActivatorException):
+ select_activator()
+
+
+IF_UP_DOWN_AVAILABLE_CALLS = [
+ (("ifquery",), {"search": ["/sbin", "/usr/sbin"], "target": None}),
+ (("ifup",), {"search": ["/sbin", "/usr/sbin"], "target": None}),
+ (("ifdown",), {"search": ["/sbin", "/usr/sbin"], "target": None}),
+]
+
+NETPLAN_AVAILABLE_CALLS = [
+ (("netplan",), {"search": ["/usr/sbin", "/sbin"], "target": None}),
+]
+
+NETWORK_MANAGER_AVAILABLE_CALLS = [
+ (("nmcli",), {"target": None}),
+]
+
+NETWORKD_AVAILABLE_CALLS = [
+ (("ip",), {"search": ["/usr/sbin", "/bin"], "target": None}),
+ (("systemctl",), {"search": ["/usr/sbin", "/bin"], "target": None}),
+]
+
+
+@pytest.mark.parametrize(
+ "activator, available_calls",
+ [
+ (IfUpDownActivator, IF_UP_DOWN_AVAILABLE_CALLS),
+ (NetplanActivator, NETPLAN_AVAILABLE_CALLS),
+ (NetworkManagerActivator, NETWORK_MANAGER_AVAILABLE_CALLS),
+ (NetworkdActivator, NETWORKD_AVAILABLE_CALLS),
+ ],
+)
+class TestActivatorsAvailable:
+ def test_available(self, activator, available_calls, available_mocks):
+ activator.available()
+ assert available_mocks.m_which.call_args_list == available_calls
+
+
+IF_UP_DOWN_BRING_UP_CALL_LIST = [
+ ((["ifup", "eth0"],), {}),
+ ((["ifup", "eth1"],), {}),
+]
+
+NETWORK_MANAGER_BRING_UP_CALL_LIST = [
+ ((["nmcli", "connection", "up", "ifname", "eth0"],), {}),
+ ((["nmcli", "connection", "up", "ifname", "eth1"],), {}),
+]
+
+NETWORKD_BRING_UP_CALL_LIST = [
+ ((["ip", "link", "set", "up", "eth0"],), {}),
+ ((["ip", "link", "set", "up", "eth1"],), {}),
+ ((["systemctl", "restart", "systemd-networkd", "systemd-resolved"],), {}),
+]
+
+
+@pytest.mark.parametrize(
+ "activator, expected_call_list",
+ [
+ (IfUpDownActivator, IF_UP_DOWN_BRING_UP_CALL_LIST),
+ (NetplanActivator, NETPLAN_CALL_LIST),
+ (NetworkManagerActivator, NETWORK_MANAGER_BRING_UP_CALL_LIST),
+ (NetworkdActivator, NETWORKD_BRING_UP_CALL_LIST),
+ ],
+)
+class TestActivatorsBringUp:
+ @patch("cloudinit.subp.subp", return_value=("", ""))
+ def test_bring_up_interface(
+ self, m_subp, activator, expected_call_list, available_mocks
+ ):
+ activator.bring_up_interface("eth0")
+ assert len(m_subp.call_args_list) == 1
+ assert m_subp.call_args_list[0] == expected_call_list[0]
+
+ @patch("cloudinit.subp.subp", return_value=("", ""))
+ def test_bring_up_interfaces(
+ self, m_subp, activator, expected_call_list, available_mocks
+ ):
+ index = 0
+ activator.bring_up_interfaces(["eth0", "eth1"])
+ for call in m_subp.call_args_list:
+ assert call == expected_call_list[index]
+ index += 1
+
+ @patch("cloudinit.subp.subp", return_value=("", ""))
+ def test_bring_up_all_interfaces_v1(
+ self, m_subp, activator, expected_call_list, available_mocks
+ ):
+ network_state = parse_net_config_data(load(V1_CONFIG))
+ activator.bring_up_all_interfaces(network_state)
+ for call in m_subp.call_args_list:
+ assert call in expected_call_list
+
+ @patch("cloudinit.subp.subp", return_value=("", ""))
+ def test_bring_up_all_interfaces_v2(
+ self, m_subp, activator, expected_call_list, available_mocks
+ ):
+ network_state = parse_net_config_data(load(V2_CONFIG))
+ activator.bring_up_all_interfaces(network_state)
+ for call in m_subp.call_args_list:
+ assert call in expected_call_list
+
+
+IF_UP_DOWN_BRING_DOWN_CALL_LIST = [
+ ((["ifdown", "eth0"],), {}),
+ ((["ifdown", "eth1"],), {}),
+]
+
+NETWORK_MANAGER_BRING_DOWN_CALL_LIST = [
+ ((["nmcli", "connection", "down", "eth0"],), {}),
+ ((["nmcli", "connection", "down", "eth1"],), {}),
+]
+
+NETWORKD_BRING_DOWN_CALL_LIST = [
+ ((["ip", "link", "set", "down", "eth0"],), {}),
+ ((["ip", "link", "set", "down", "eth1"],), {}),
+]
+
+
+@pytest.mark.parametrize(
+ "activator, expected_call_list",
+ [
+ (IfUpDownActivator, IF_UP_DOWN_BRING_DOWN_CALL_LIST),
+ (NetplanActivator, NETPLAN_CALL_LIST),
+ (NetworkManagerActivator, NETWORK_MANAGER_BRING_DOWN_CALL_LIST),
+ (NetworkdActivator, NETWORKD_BRING_DOWN_CALL_LIST),
+ ],
+)
+class TestActivatorsBringDown:
+ @patch("cloudinit.subp.subp", return_value=("", ""))
+ def test_bring_down_interface(
+ self, m_subp, activator, expected_call_list, available_mocks
+ ):
+ activator.bring_down_interface("eth0")
+ assert len(m_subp.call_args_list) == 1
+ assert m_subp.call_args_list[0] == expected_call_list[0]
+
+ @patch("cloudinit.subp.subp", return_value=("", ""))
+ def test_bring_down_interfaces(
+ self, m_subp, activator, expected_call_list, available_mocks
+ ):
+ activator.bring_down_interfaces(["eth0", "eth1"])
+ assert expected_call_list == m_subp.call_args_list
+
+ @patch("cloudinit.subp.subp", return_value=("", ""))
+ def test_bring_down_all_interfaces_v1(
+ self, m_subp, activator, expected_call_list, available_mocks
+ ):
+ network_state = parse_net_config_data(load(V1_CONFIG))
+ activator.bring_down_all_interfaces(network_state)
+ for call in m_subp.call_args_list:
+ assert call in expected_call_list
+
+ @patch("cloudinit.subp.subp", return_value=("", ""))
+ def test_bring_down_all_interfaces_v2(
+ self, m_subp, activator, expected_call_list, available_mocks
+ ):
+ network_state = parse_net_config_data(load(V2_CONFIG))
+ activator.bring_down_all_interfaces(network_state)
+ for call in m_subp.call_args_list:
+ assert call in expected_call_list