diff --git a/cloud-init-0.7.9-digitalocean-loopback.patch b/cloud-init-0.7.9-digitalocean-loopback.patch new file mode 100644 index 0000000..e17bb2b --- /dev/null +++ b/cloud-init-0.7.9-digitalocean-loopback.patch @@ -0,0 +1,158 @@ +Index: cloud-init-0.7.9/cloudinit/sources/helpers/digitalocean.py +=================================================================== +--- cloud-init-0.7.9.orig/cloudinit/sources/helpers/digitalocean.py ++++ cloud-init-0.7.9/cloudinit/sources/helpers/digitalocean.py +@@ -107,15 +107,12 @@ def convert_network_configuration(config + } + """ + +- def _get_subnet_part(pcfg, nameservers=None): ++ def _get_subnet_part(pcfg): + subpart = {'type': 'static', + 'control': 'auto', + 'address': pcfg.get('ip_address'), + 'gateway': pcfg.get('gateway')} + +- if nameservers: +- subpart['dns_nameservers'] = nameservers +- + if ":" in pcfg.get('ip_address'): + subpart['address'] = "{0}/{1}".format(pcfg.get('ip_address'), + pcfg.get('cidr')) +@@ -157,13 +154,8 @@ def convert_network_configuration(config + continue + + sub_part = _get_subnet_part(raw_subnet) +- if nic_type == 'public' and 'anchor' not in netdef: +- # add DNS resolvers to the public interfaces only +- sub_part = _get_subnet_part(raw_subnet, dns_servers) +- else: +- # remove the gateway any non-public interfaces +- if 'gateway' in sub_part: +- del sub_part['gateway'] ++ if netdef in ('private', 'anchor_ipv4', 'anchor_ipv6'): ++ del sub_part['gateway'] + + subnets.append(sub_part) + +@@ -171,6 +163,10 @@ def convert_network_configuration(config + nic_configs.append(ncfg) + LOG.debug("nic '%s' configuration: %s", if_name, ncfg) + ++ if dns_servers: ++ LOG.debug("added dns servers: %s", dns_servers) ++ nic_configs.append({'type': 'nameserver', 'address': dns_servers}) ++ + return {'version': 1, 'config': nic_configs} + + +Index: cloud-init-0.7.9/tests/unittests/test_datasource/test_digitalocean.py +=================================================================== +--- cloud-init-0.7.9.orig/tests/unittests/test_datasource/test_digitalocean.py ++++ cloud-init-0.7.9/tests/unittests/test_datasource/test_digitalocean.py +@@ -194,7 +194,13 @@ class TestDataSourceDigitalOcean(TestCas + + class TestNetworkConvert(TestCase): + +- def _get_networking(self): ++ @mock.patch('cloudinit.net.get_interfaces_by_mac') ++ def _get_networking(self, m_get_by_mac): ++ m_get_by_mac.return_value = { ++ '04:01:57:d1:9e:01': 'ens1', ++ '04:01:57:d1:9e:02': 'ens2', ++ 'b8:ae:ed:75:5f:9a': 'enp0s25', ++ 'ae:cc:08:7c:88:00': 'meta2p1'} + netcfg = digitalocean.convert_network_configuration( + DO_META['interfaces'], DO_META['dns']['nameservers']) + self.assertIn('config', netcfg) +@@ -203,18 +209,33 @@ class TestNetworkConvert(TestCase): + def test_networking_defined(self): + netcfg = self._get_networking() + self.assertIsNotNone(netcfg) ++ dns_defined = False + +- for nic_def in netcfg.get('config'): +- print(json.dumps(nic_def, indent=3)) +- n_type = nic_def.get('type') +- n_subnets = nic_def.get('type') +- n_name = nic_def.get('name') +- n_mac = nic_def.get('mac_address') +- +- self.assertIsNotNone(n_type) +- self.assertIsNotNone(n_subnets) +- self.assertIsNotNone(n_name) +- self.assertIsNotNone(n_mac) ++ for part in netcfg.get('config'): ++ n_type = part.get('type') ++ print("testing part ", n_type, "\n", json.dumps(part, indent=3)) ++ ++ if n_type == 'nameserver': ++ n_address = part.get('address') ++ self.assertIsNotNone(n_address) ++ self.assertEqual(len(n_address), 3) ++ ++ dns_resolvers = DO_META["dns"]["nameservers"] ++ for x in n_address: ++ self.assertIn(x, dns_resolvers) ++ dns_defined = True ++ ++ else: ++ n_subnets = part.get('type') ++ n_name = part.get('name') ++ n_mac = part.get('mac_address') ++ ++ self.assertIsNotNone(n_type) ++ self.assertIsNotNone(n_subnets) ++ self.assertIsNotNone(n_name) ++ self.assertIsNotNone(n_mac) ++ ++ self.assertTrue(dns_defined) + + def _get_nic_definition(self, int_type, expected_name): + """helper function to return if_type (i.e. public) and the expected +@@ -255,12 +276,6 @@ class TestNetworkConvert(TestCase): + self.assertEqual(meta_def.get('mac'), nic_def.get('mac_address')) + self.assertEqual('physical', nic_def.get('type')) + +- def _check_dns_nameservers(self, subn_def): +- self.assertIn('dns_nameservers', subn_def) +- expected_nameservers = DO_META['dns']['nameservers'] +- nic_nameservers = subn_def.get('dns_nameservers') +- self.assertEqual(expected_nameservers, nic_nameservers) +- + def test_public_interface_ipv6(self): + """test public ipv6 addressing""" + (nic_def, meta_def) = self._get_nic_definition('public', 'eth0') +@@ -275,7 +290,6 @@ class TestNetworkConvert(TestCase): + + self.assertEqual(cidr_notated_address, subn_def.get('address')) + self.assertEqual(ipv6_def.get('gateway'), subn_def.get('gateway')) +- self._check_dns_nameservers(subn_def) + + def test_public_interface_ipv4(self): + """test public ipv4 addressing""" +@@ -288,7 +302,6 @@ class TestNetworkConvert(TestCase): + + self.assertEqual(ipv4_def.get('netmask'), subn_def.get('netmask')) + self.assertEqual(ipv4_def.get('gateway'), subn_def.get('gateway')) +- self._check_dns_nameservers(subn_def) + + def test_public_interface_anchor_ipv4(self): + """test public ipv4 addressing""" +@@ -302,10 +315,15 @@ class TestNetworkConvert(TestCase): + self.assertEqual(ipv4_def.get('netmask'), subn_def.get('netmask')) + self.assertNotIn('gateway', subn_def) + +- def test_convert_without_private(self): ++ @mock.patch('cloudinit.net.get_interfaces_by_mac') ++ def test_convert_without_private(self, m_get_by_mac): ++ m_get_by_mac.return_value = { ++ 'b8:ae:ed:75:5f:9a': 'enp0s25', ++ 'ae:cc:08:7c:88:00': 'meta2p1'} + netcfg = digitalocean.convert_network_configuration( + DO_META_2['interfaces'], DO_META_2['dns']['nameservers']) + ++ # print(netcfg) + byname = {} + for i in netcfg['config']: + if 'name' in i: diff --git a/cloud-init.spec b/cloud-init.spec index ab0c56d..670e2d9 100644 --- a/cloud-init.spec +++ b/cloud-init.spec @@ -1,6 +1,6 @@ Name: cloud-init Version: 0.7.9 -Release: 4%{?dist} +Release: 5%{?dist} Summary: Cloud instance init scripts License: GPLv3 URL: http://launchpad.net/cloud-init @@ -78,6 +78,13 @@ Patch18: cloud-init-0.7.9-before-network-target.patch # https://git.launchpad.net/cloud-init/commit/?id=b71592ce0e0a9f9f9f225315015ca57b312ad30d Patch19: cloud-init-0.7.9-credcache.patch +# Make DigitalOcean data sources handle DNS servers similar to OpenStack +# https://bugzilla.redhat.com/show_bug.cgi?id=1442463 +# https://bugs.launchpad.net/cloud-init/+bug/1675571 +# https://git.launchpad.net/cloud-init/commit/?id=5442b517ebe5508159a46d11d500fbc6ad854ba0 +# https://git.launchpad.net/cloud-init/commit/?id=493f6c3e923902d5d4f3d87e1cc4c726ea90ada4 +Patch20: cloud-init-0.7.9-digitalocean-loopback.patch + BuildArch: noarch BuildRequires: pkgconfig(systemd) @@ -210,6 +217,9 @@ nosetests-%{python3_version} tests/unittests/ %changelog +* Fri Apr 14 2017 Garrett Holmstrom - 0.7.9-5 +- Made DigitalOcean DNS server handling consistent with OpenStack [RH:1442463, LP:1675571] + * Tue Mar 14 2017 Garrett Holmstrom - 0.7.9-4 - Fixed systemd dependency cycle with cloud-final and os-collect-config [RH:1420946, RH:1428492] - Fixed systemd dependency cycle with cloud-init and multi-user.target [RH:1428492, RH:1430511]