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

Proposed by Giulio Fidente
Status: Rejected
Rejected by: Scott Moser
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 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.
Revision history for this message
Joshua Harlow (harlowja) wrote :

Anyway to add some unittests for this?

Revision history for this message
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

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

Fix test_from_cloud()

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

Revision history for this message
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?

Revision history for this message
Joshua Harlow (harlowja) :
Revision history for this message
Giulio Fidente (gfidente) wrote :

hi, thanks again for reviewing this, will do!

1222. By Giulio Fidente

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.

Revision history for this message
Juan Antonio Osorio Robles (juan-osorio-robles) wrote :

would sure use this fix O_O. The fix LGTM

Revision history for this message
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

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

Fix test_from_cloud()

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

1220. By Giulio Fidente

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

Ensure fqdn is not left to None if get_fqdn_from_hosts returns None

1218. By Giulio Fidente

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()