summaryrefslogtreecommitdiff
path: root/cloudinit/sources/tests
diff options
context:
space:
mode:
authorChad Smith <chad.smith@canonical.com>2018-03-14 23:38:07 -0600
committerChad Smith <chad.smith@canonical.com>2018-03-14 23:38:07 -0600
commit133ad2cb327ad17b7b81319fac8f9f14577c04df (patch)
treeca14c7c958537e00f1c7ce93405eb77cee85b81e /cloudinit/sources/tests
parent76460b63f9c310c7de4e5f0c11d1525bedd277e1 (diff)
downloadvyos-cloud-init-133ad2cb327ad17b7b81319fac8f9f14577c04df.tar.gz
vyos-cloud-init-133ad2cb327ad17b7b81319fac8f9f14577c04df.zip
set_hostname: When present in metadata, set it before network bringup.
When instance meta-data provides hostname information, run cc_set_hostname in the init-local or init-net stage before network comes up. Prevent an initial DHCP request which leaks the stock cloud-image default hostname before the meta-data provided hostname was processed. A leaked cloud-image hostname adversely affects Dynamic DNS which would reallocate 'ubuntu' hostname in DNS to every instance brought up by cloud-init. These instances would only update DNS to the cloud-init configured hostname upon DHCP lease renewal. This branch extends the get_hostname methods in datasource, cloud and util to limit results to metadata_only to avoid extra cost of querying the distro for hostname information if metadata does not provide that information. LP: #1746455
Diffstat (limited to 'cloudinit/sources/tests')
-rw-r--r--cloudinit/sources/tests/test_init.py70
1 files changed, 69 insertions, 1 deletions
diff --git a/cloudinit/sources/tests/test_init.py b/cloudinit/sources/tests/test_init.py
index af151154..5065083c 100644
--- a/cloudinit/sources/tests/test_init.py
+++ b/cloudinit/sources/tests/test_init.py
@@ -7,7 +7,7 @@ import stat
from cloudinit.helpers import Paths
from cloudinit.sources import (
INSTANCE_JSON_FILE, DataSource)
-from cloudinit.tests.helpers import CiTestCase, skipIf
+from cloudinit.tests.helpers import CiTestCase, skipIf, mock
from cloudinit.user_data import UserDataProcessor
from cloudinit import util
@@ -108,6 +108,74 @@ class TestDataSource(CiTestCase):
self.assertEqual('userdata_raw', datasource.userdata_raw)
self.assertEqual('vendordata_raw', datasource.vendordata_raw)
+ def test_get_hostname_strips_local_hostname_without_domain(self):
+ """Datasource.get_hostname strips metadata local-hostname of domain."""
+ tmp = self.tmp_dir()
+ datasource = DataSourceTestSubclassNet(
+ self.sys_cfg, self.distro, Paths({'run_dir': tmp}))
+ self.assertTrue(datasource.get_data())
+ self.assertEqual(
+ 'test-subclass-hostname', datasource.metadata['local-hostname'])
+ self.assertEqual('test-subclass-hostname', datasource.get_hostname())
+ datasource.metadata['local-hostname'] = 'hostname.my.domain.com'
+ self.assertEqual('hostname', datasource.get_hostname())
+
+ def test_get_hostname_with_fqdn_returns_local_hostname_with_domain(self):
+ """Datasource.get_hostname with fqdn set gets qualified hostname."""
+ tmp = self.tmp_dir()
+ datasource = DataSourceTestSubclassNet(
+ self.sys_cfg, self.distro, Paths({'run_dir': tmp}))
+ self.assertTrue(datasource.get_data())
+ datasource.metadata['local-hostname'] = 'hostname.my.domain.com'
+ self.assertEqual(
+ 'hostname.my.domain.com', datasource.get_hostname(fqdn=True))
+
+ def test_get_hostname_without_metadata_uses_system_hostname(self):
+ """Datasource.gethostname runs util.get_hostname when no metadata."""
+ tmp = self.tmp_dir()
+ datasource = DataSourceTestSubclassNet(
+ self.sys_cfg, self.distro, Paths({'run_dir': tmp}))
+ self.assertEqual({}, datasource.metadata)
+ mock_fqdn = 'cloudinit.sources.util.get_fqdn_from_hosts'
+ with mock.patch('cloudinit.sources.util.get_hostname') as m_gethost:
+ with mock.patch(mock_fqdn) as m_fqdn:
+ m_gethost.return_value = 'systemhostname.domain.com'
+ m_fqdn.return_value = None # No maching fqdn in /etc/hosts
+ self.assertEqual('systemhostname', datasource.get_hostname())
+ self.assertEqual(
+ 'systemhostname.domain.com',
+ datasource.get_hostname(fqdn=True))
+
+ def test_get_hostname_without_metadata_returns_none(self):
+ """Datasource.gethostname returns None when metadata_only and no MD."""
+ tmp = self.tmp_dir()
+ datasource = DataSourceTestSubclassNet(
+ self.sys_cfg, self.distro, Paths({'run_dir': tmp}))
+ self.assertEqual({}, datasource.metadata)
+ mock_fqdn = 'cloudinit.sources.util.get_fqdn_from_hosts'
+ with mock.patch('cloudinit.sources.util.get_hostname') as m_gethost:
+ with mock.patch(mock_fqdn) as m_fqdn:
+ self.assertIsNone(datasource.get_hostname(metadata_only=True))
+ self.assertIsNone(
+ datasource.get_hostname(fqdn=True, metadata_only=True))
+ self.assertEqual([], m_gethost.call_args_list)
+ self.assertEqual([], m_fqdn.call_args_list)
+
+ def test_get_hostname_without_metadata_prefers_etc_hosts(self):
+ """Datasource.gethostname prefers /etc/hosts to util.get_hostname."""
+ tmp = self.tmp_dir()
+ datasource = DataSourceTestSubclassNet(
+ self.sys_cfg, self.distro, Paths({'run_dir': tmp}))
+ self.assertEqual({}, datasource.metadata)
+ mock_fqdn = 'cloudinit.sources.util.get_fqdn_from_hosts'
+ with mock.patch('cloudinit.sources.util.get_hostname') as m_gethost:
+ with mock.patch(mock_fqdn) as m_fqdn:
+ m_gethost.return_value = 'systemhostname.domain.com'
+ m_fqdn.return_value = 'fqdnhostname.domain.com'
+ self.assertEqual('fqdnhostname', datasource.get_hostname())
+ self.assertEqual('fqdnhostname.domain.com',
+ datasource.get_hostname(fqdn=True))
+
def test_get_data_write_json_instance_data(self):
"""get_data writes INSTANCE_JSON_FILE to run_dir as readonly root."""
tmp = self.tmp_dir()