# This file is part of cloud-init. See LICENSE file for license information. from unittest import mock import pytest from cloudinit import safeyaml from cloudinit.net import network_state from cloudinit.tests.helpers import CiTestCase netstate_path = 'cloudinit.net.network_state' _V1_CONFIG_NAMESERVERS = """\ network: version: 1 config: - type: nameserver interface: {iface} address: - 192.168.1.1 - 8.8.8.8 search: - spam.local - type: nameserver address: - 192.168.1.0 - 4.4.4.4 search: - eggs.local - type: physical name: eth0 mac_address: '00:11:22:33:44:55' - type: physical name: eth1 mac_address: '66:77:88:99:00:11' """ V1_CONFIG_NAMESERVERS_VALID = _V1_CONFIG_NAMESERVERS.format(iface='eth1') V1_CONFIG_NAMESERVERS_INVALID = _V1_CONFIG_NAMESERVERS.format(iface='eth90') V2_CONFIG_NAMESERVERS = """\ network: version: 2 ethernets: eth0: match: macaddress: '00:11:22:33:44:55' nameservers: search: [spam.local, eggs.local] addresses: [8.8.8.8] eth1: match: macaddress: '66:77:88:99:00:11' nameservers: search: [foo.local, bar.local] addresses: [4.4.4.4] """ class TestNetworkStateParseConfig(CiTestCase): def setUp(self): super(TestNetworkStateParseConfig, self).setUp() nsi_path = netstate_path + '.NetworkStateInterpreter' self.add_patch(nsi_path, 'm_nsi') def test_missing_version_returns_none(self): ncfg = {} with self.assertRaises(RuntimeError): network_state.parse_net_config_data(ncfg) def test_unknown_versions_returns_none(self): ncfg = {'version': 13.2} with self.assertRaises(RuntimeError): network_state.parse_net_config_data(ncfg) def test_version_2_passes_self_as_config(self): ncfg = {'version': 2, 'otherconfig': {}, 'somemore': [1, 2, 3]} network_state.parse_net_config_data(ncfg) self.assertEqual([mock.call(version=2, config=ncfg)], self.m_nsi.call_args_list) def test_valid_config_gets_network_state(self): ncfg = {'version': 2, 'otherconfig': {}, 'somemore': [1, 2, 3]} result = network_state.parse_net_config_data(ncfg) self.assertNotEqual(None, result) def test_empty_v1_config_gets_network_state(self): ncfg = {'version': 1, 'config': []} result = network_state.parse_net_config_data(ncfg) self.assertNotEqual(None, result) def test_empty_v2_config_gets_network_state(self): ncfg = {'version': 2} result = network_state.parse_net_config_data(ncfg) self.assertNotEqual(None, result) class TestNetworkStateParseConfigV2(CiTestCase): def test_version_2_ignores_renderer_key(self): ncfg = {'version': 2, 'renderer': 'networkd', 'ethernets': {}} nsi = network_state.NetworkStateInterpreter(version=ncfg['version'], config=ncfg) nsi.parse_config(skip_broken=False) self.assertEqual(ncfg, nsi.as_dict()['config']) class TestNetworkStateParseNameservers: def _parse_network_state_from_config(self, config): yaml = safeyaml.load(config) return network_state.parse_net_config_data(yaml['network']) def test_v1_nameservers_valid(self): config = self._parse_network_state_from_config( V1_CONFIG_NAMESERVERS_VALID) # If an interface was specified, DNS shouldn't be in the global list assert ['192.168.1.0', '4.4.4.4'] == sorted( config.dns_nameservers) assert ['eggs.local'] == config.dns_searchdomains # If an interface was specified, DNS should be part of the interface for iface in config.iter_interfaces(): if iface['name'] == 'eth1': assert iface['dns']['addresses'] == ['192.168.1.1', '8.8.8.8'] assert iface['dns']['search'] == ['spam.local'] else: assert 'dns' not in iface def test_v1_nameservers_invalid(self): with pytest.raises(ValueError): self._parse_network_state_from_config( V1_CONFIG_NAMESERVERS_INVALID) def test_v2_nameservers(self): config = self._parse_network_state_from_config(V2_CONFIG_NAMESERVERS) # Ensure DNS defined on interface exists on interface for iface in config.iter_interfaces(): if iface['name'] == 'eth0': assert iface['dns'] == { 'nameservers': ['8.8.8.8'], 'search': ['spam.local', 'eggs.local'], } else: assert iface['dns'] == { 'nameservers': ['4.4.4.4'], 'search': ['foo.local', 'bar.local'] } # Ensure DNS defined on interface also exists globally (since there # is no global DNS definitions in v2) assert ['4.4.4.4', '8.8.8.8'] == sorted(config.dns_nameservers) assert [ 'bar.local', 'eggs.local', 'foo.local', 'spam.local', ] == sorted(config.dns_searchdomains) # vi: ts=4 expandtab