Merge lp:~gfidente/cloud-init/try_fqdn_from_hosts into lp:~cloud-init-dev/cloud-init/trunk

Proposed by Giulio Fidente on 2016-05-13
Status: Rejected
Rejected by: Scott Moser on 2017-06-06
Proposed branch: lp:~gfidente/cloud-init/try_fqdn_from_hosts
Merge into: lp:~cloud-init-dev/cloud-init/trunk
Diff against target: 139 lines (+96/-5)
2 files modified
cloudinit/util.py (+9/-5)
tests/unittests/test_util.py (+87/-0)
To merge this branch: bzr merge lp:~gfidente/cloud-init/try_fqdn_from_hosts
Reviewer Review Type Date Requested Status
cloud-init commiters 2016-05-13 Pending
Review via email: mp+294680@code.launchpad.net

Description of the Change

In util.py , get_hostname_fqdn tries cloud.get_hostname(fqdn=True) to get the fqdn, but that might return just the hostname if fqdn isn't found.

This change is meant to make it try get_fqdn_from_hosts if fqdn does not contain any dot.

To post a comment you must log in.
Joshua Harlow (harlowja) wrote :

Anyway to add some unittests for this?

Giulio Fidente (gfidente) wrote :

Yes absolutely, thanks for checking this out. There wasn't any for the hostname functions from util.py so I will be adding a bunch.

1220. By Giulio Fidente on 2016-05-13

Adds unit tests for util.py

This adds seven new unit tests are meant to cover get_hostname_fqdn() and
get_fqdn_from_hosts() from util.py

1221. By Giulio Fidente on 2016-05-13

Fix test_from_cloud()

The FakeCloudWithDomain provider was incorrectly returning the fqdn
when called with fqdn=False

Giulio Fidente (gfidente) wrote :

Do you think it would be useful to add the unit tests first, without any additional code change to diminish the code changes related to the new logic into a different proposal?

Joshua Harlow (harlowja) :
Giulio Fidente (gfidente) wrote :

hi, thanks again for reviewing this, will do!

1222. By Giulio Fidente on 2016-05-18

Ensure temporary 'hosts' file used for testing is deleted via addCleanup

While tearDown is not executed in case of errors raised during the setUp
phase while addCleanup is; this change updates test_util.py so that the
temporary 'hosts' file created to run some unit tests is deleted in
addCleanup instead of tearDown.

would sure use this fix O_O. The fix LGTM

Scott Moser (smoser) wrote :

Hello,
Thank you for taking the time to contribute to cloud-init. Cloud-init has moved its revision control system to git. As a result, we are marking all bzr merge proposals as 'rejected'. If you would like to re-submit this proposal for review, please do so by following the current HACKING documentation at http://cloudinit.readthedocs.io/en/latest/topics/hacking.html .

Please do re-submit.
Sorry for lost time and unresponsiveness.

Scott

Unmerged revisions

1222. By Giulio Fidente on 2016-05-18

Ensure temporary 'hosts' file used for testing is deleted via addCleanup

While tearDown is not executed in case of errors raised during the setUp
phase while addCleanup is; this change updates test_util.py so that the
temporary 'hosts' file created to run some unit tests is deleted in
addCleanup instead of tearDown.

1221. By Giulio Fidente on 2016-05-13

Fix test_from_cloud()

The FakeCloudWithDomain provider was incorrectly returning the fqdn
when called with fqdn=False

1220. By Giulio Fidente on 2016-05-13

Adds unit tests for util.py

This adds seven new unit tests are meant to cover get_hostname_fqdn() and
get_fqdn_from_hosts() from util.py

1219. By Giulio Fidente on 2016-05-13

Ensure fqdn is not left to None if get_fqdn_from_hosts returns None

1218. By Giulio Fidente on 2016-05-13

Try get_fqdn_from_hosts if get_hostname(fqdn=True) is unable to find one

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cloudinit/util.py'
2--- cloudinit/util.py 2016-05-12 17:56:26 +0000
3+++ cloudinit/util.py 2016-05-18 22:38:52 +0000
4@@ -933,7 +933,7 @@
5 return contents.replace('\r\n', '\n')
6
7
8-def get_hostname_fqdn(cfg, cloud):
9+def get_hostname_fqdn(cfg, cloud, hosts_filename='/etc/hosts'):
10 # return the hostname and fqdn from 'cfg'. If not found in cfg,
11 # then fall back to data from cloud
12 if "fqdn" in cfg:
13@@ -947,13 +947,17 @@
14 fqdn = cfg['hostname']
15 hostname = cfg['hostname'][:fqdn.find('.')]
16 else:
17+ if "hostname" in cfg:
18+ hostname = cfg['hostname']
19+ else:
20+ hostname = cloud.get_hostname()
21 # no fqdn set, get fqdn from cloud.
22 # get hostname from cfg if available otherwise cloud
23 fqdn = cloud.get_hostname(fqdn=True)
24- if "hostname" in cfg:
25- hostname = cfg['hostname']
26- else:
27- hostname = cloud.get_hostname()
28+ if fqdn.find('.') < 1:
29+ fqdn_from_hosts = get_fqdn_from_hosts(hostname, hosts_filename)
30+ if fqdn_from_hosts:
31+ fqdn = fqdn_from_hosts
32 return (hostname, fqdn)
33
34
35
36=== modified file 'tests/unittests/test_util.py'
37--- tests/unittests/test_util.py 2016-03-14 13:45:11 +0000
38+++ tests/unittests/test_util.py 2016-05-18 22:38:52 +0000
39@@ -37,6 +37,20 @@
40 self.restored.append(path)
41
42
43+class FakeCloudWithoutDomain(object):
44+
45+ def get_hostname(self, fqdn=False):
46+ return "cloudname"
47+
48+
49+class FakeCloudWithDomain(object):
50+
51+ def get_hostname(self, fqdn=False):
52+ if fqdn:
53+ return "cloudname.clouddomain"
54+ return "cloudname"
55+
56+
57 class TestGetCfgOptionListOrStr(helpers.TestCase):
58 def test_not_found_no_default(self):
59 """None is returned if key is not found and no default given."""
60@@ -69,6 +83,79 @@
61 self.assertEqual([], result)
62
63
64+class TestGetHostnameFqdn(helpers.TestCase):
65+ def setUp(self):
66+ super(TestGetHostnameFqdn, self).setUp()
67+ tmp_h, self.tmp_path = tempfile.mkstemp()
68+ self.addCleanup(os.remove, self.tmp_path)
69+ self.f = os.fdopen(tmp_h, "w")
70+ self.f.write("9.10.11.12 cloudname.clouddomain cloudname\n")
71+ self.f.close()
72+ self.cloud = FakeCloudWithDomain()
73+ self.cloud_no_domain = FakeCloudWithoutDomain()
74+
75+ def test_with_fqdn(self):
76+ """Results based only on fqdn config key"""
77+ cfg = {'fqdn': 'thisname.thisdomain'}
78+ hostname, fqdn = util.get_hostname_fqdn(cfg, self.cloud, self.tmp_path)
79+ self.assertEqual("thisname", hostname)
80+ self.assertEqual("thisname.thisdomain", fqdn)
81+
82+ def test_with_dotted_hostname(self):
83+ """Results based only on hostname config key"""
84+ cfg = {'hostname': 'thisname.thisdomain'}
85+ hostname, fqdn = util.get_hostname_fqdn(cfg, self.cloud, self.tmp_path)
86+ self.assertEqual("thisname", hostname)
87+ self.assertEqual("thisname.thisdomain", fqdn)
88+
89+ def test_with_short_hostname(self):
90+ """The hostname is from config key, the fqdn from cloud"""
91+ cfg = {'hostname': 'thisname'}
92+ hostname, fqdn = util.get_hostname_fqdn(cfg, self.cloud, self.tmp_path)
93+ self.assertEqual("thisname", hostname)
94+ self.assertEqual("cloudname.clouddomain", fqdn)
95+
96+ def test_from_cloud(self):
97+ """Results based only on cloud"""
98+ cfg = {}
99+ hostname, fqdn = util.get_hostname_fqdn(cfg, self.cloud, self.tmp_path)
100+ self.assertEqual("cloudname", hostname)
101+ self.assertEqual("cloudname.clouddomain", fqdn)
102+
103+ def test_from_cloud_without_domain(self):
104+ """The hostname is from cloud, the fqdn mapped from hosts file"""
105+ cfg = {}
106+ hostname, fqdn = util.get_hostname_fqdn(cfg,
107+ self.cloud_no_domain,
108+ self.tmp_path)
109+ self.assertEqual("cloudname", hostname)
110+ self.assertEqual("cloudname.clouddomain", fqdn)
111+
112+
113+class TestGetFqdnFromHosts(helpers.TestCase):
114+ def setUp(self):
115+ super(TestGetFqdnFromHosts, self).setUp()
116+ tmp_h, self.tmp_path = tempfile.mkstemp()
117+ self.addCleanup(os.remove, self.tmp_path)
118+ self.f = os.fdopen(tmp_h, "w")
119+ self.f.write("# comment\n")
120+ self.f.write("1.2.3.4 name.domain name\n")
121+ self.f.write("5.6.7.8 myname.mydomain myname # comment\n")
122+ self.f.close()
123+
124+ def test_fqdn_found(self):
125+ """Test fqdn is returned when hostname is found"""
126+ hostname = "myname"
127+ fqdn = util.get_fqdn_from_hosts(hostname, self.tmp_path)
128+ self.assertEqual("myname.mydomain", fqdn)
129+
130+ def test_fqdn_not_found(self):
131+ """Test None is returned when hostname is not found"""
132+ hostname = "unnamed"
133+ fqdn = util.get_fqdn_from_hosts(hostname, self.tmp_path)
134+ self.assertEqual(None, fqdn)
135+
136+
137 class TestWriteFile(helpers.TestCase):
138 def setUp(self):
139 super(TestWriteFile, self).setUp()