summaryrefslogtreecommitdiff
path: root/tests/unittests
diff options
context:
space:
mode:
authorJames Falcon <therealfalcon@gmail.com>2021-07-01 14:43:07 -0500
committerGitHub <noreply@github.com>2021-07-01 14:43:07 -0500
commit81299de5fe3b6e491a965a6ebef66c6b8bf2c037 (patch)
treec4d2277a7f6240e306f6222769d349357510414a /tests/unittests
parent78e89b03ecb29e7df3181b1219a0b5f44b9d7532 (diff)
downloadvyos-cloud-init-81299de5fe3b6e491a965a6ebef66c6b8bf2c037.tar.gz
vyos-cloud-init-81299de5fe3b6e491a965a6ebef66c6b8bf2c037.zip
Add new network activators to bring up interfaces (#919)
Currently _bring_up_interfaces() is a no-op for any distro using renderers. We need to be able to support bringing up a single interfaces, a list of interfaces, and all interfaces. This should be independent of the renderers, as the network config is often generated independent of the mechanism used to apply it. Additionally, I included a refactor to remove "_supported_write_network_config". We had a confusing call chain of apply_network_config->_write_network_config->_supported_write_network_config. The last two have been combined.
Diffstat (limited to 'tests/unittests')
-rw-r--r--tests/unittests/test_net.py2
-rw-r--r--tests/unittests/test_net_activators.py177
2 files changed, 178 insertions, 1 deletions
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index 1aab51ee..43e209c1 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -5277,7 +5277,7 @@ class TestNetRenderers(CiTestCase):
# available should only be called until one is found.
m_eni_avail.return_value = True
m_sysc_avail.side_effect = Exception("Should not call me")
- found = renderers.search(priority=['eni', 'sysconfig'], first=True)
+ found = renderers.search(priority=['eni', 'sysconfig'], first=True)[0]
self.assertEqual(['eni'], [found[0]])
@mock.patch("cloudinit.net.renderers.sysconfig.available")
diff --git a/tests/unittests/test_net_activators.py b/tests/unittests/test_net_activators.py
new file mode 100644
index 00000000..f11486ff
--- /dev/null
+++ b/tests/unittests/test_net_activators.py
@@ -0,0 +1,177 @@
+from collections import namedtuple
+from unittest.mock import patch
+
+import pytest
+
+from cloudinit.net.activators import (
+ DEFAULT_PRIORITY,
+ search_activator,
+ select_activator,
+)
+from cloudinit.net.activators import (
+ IfUpDownActivator,
+ NetplanActivator,
+ NetworkManagerActivator
+)
+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
+"""
+
+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}),
+]
+
+IF_UP_DOWN_CALL_LIST = [
+ ((['ifup', 'eth0'], ), {}),
+ ((['ifup', 'eth1'], ), {}),
+]
+
+NETPLAN_AVAILABLE_CALLS = [
+ (('netplan',), {'search': ['/usr/sbin', '/sbin'], 'target': None}),
+]
+
+NETPLAN_CALL_LIST = [
+ ((['netplan', 'apply'], ), {'capture': True}),
+]
+
+NETWORK_MANAGER_AVAILABLE_CALLS = [
+ (('nmcli',), {'target': None}),
+]
+
+NETWORK_MANAGER_CALL_LIST = [
+ ((['nmcli', 'connection', 'up', 'eth0'], ), {}),
+ ((['nmcli', 'connection', 'up', 'eth1'], ), {}),
+]
+
+
+@pytest.yield_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.yield_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(RuntimeError):
+ select_activator()
+
+
+@pytest.mark.parametrize('activator, available_calls, expected_call_list', [
+ (IfUpDownActivator, IF_UP_DOWN_AVAILABLE_CALLS, IF_UP_DOWN_CALL_LIST),
+ (NetplanActivator, NETPLAN_AVAILABLE_CALLS, NETPLAN_CALL_LIST),
+ (NetworkManagerActivator, NETWORK_MANAGER_AVAILABLE_CALLS,
+ NETWORK_MANAGER_CALL_LIST),
+])
+class TestIfUpDownActivator:
+ def test_available(
+ self, activator, available_calls, expected_call_list, available_mocks
+ ):
+ activator.available()
+ assert available_mocks.m_which.call_args_list == available_calls
+
+ @patch('cloudinit.subp.subp', return_value=('', ''))
+ def test_bring_up_interface(
+ self, m_subp, activator, available_calls, 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, available_calls, expected_call_list,
+ available_mocks
+ ):
+ activator.bring_up_interfaces(['eth0', 'eth1'])
+ assert expected_call_list == m_subp.call_args_list
+
+ @patch('cloudinit.subp.subp', return_value=('', ''))
+ def test_bring_up_all_interfaces_v1(
+ self, m_subp, activator, available_calls, 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, available_calls, 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