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
=== modified file 'cloudinit/util.py'
--- cloudinit/util.py 2016-05-12 17:56:26 +0000
+++ cloudinit/util.py 2016-05-18 22:38:52 +0000
@@ -933,7 +933,7 @@
933 return contents.replace('\r\n', '\n')933 return contents.replace('\r\n', '\n')
934934
935935
936def get_hostname_fqdn(cfg, cloud):936def get_hostname_fqdn(cfg, cloud, hosts_filename='/etc/hosts'):
937 # return the hostname and fqdn from 'cfg'. If not found in cfg,937 # return the hostname and fqdn from 'cfg'. If not found in cfg,
938 # then fall back to data from cloud938 # then fall back to data from cloud
939 if "fqdn" in cfg:939 if "fqdn" in cfg:
@@ -947,13 +947,17 @@
947 fqdn = cfg['hostname']947 fqdn = cfg['hostname']
948 hostname = cfg['hostname'][:fqdn.find('.')]948 hostname = cfg['hostname'][:fqdn.find('.')]
949 else:949 else:
950 if "hostname" in cfg:
951 hostname = cfg['hostname']
952 else:
953 hostname = cloud.get_hostname()
950 # no fqdn set, get fqdn from cloud.954 # no fqdn set, get fqdn from cloud.
951 # get hostname from cfg if available otherwise cloud955 # get hostname from cfg if available otherwise cloud
952 fqdn = cloud.get_hostname(fqdn=True)956 fqdn = cloud.get_hostname(fqdn=True)
953 if "hostname" in cfg:957 if fqdn.find('.') < 1:
954 hostname = cfg['hostname']958 fqdn_from_hosts = get_fqdn_from_hosts(hostname, hosts_filename)
955 else:959 if fqdn_from_hosts:
956 hostname = cloud.get_hostname()960 fqdn = fqdn_from_hosts
957 return (hostname, fqdn)961 return (hostname, fqdn)
958962
959963
960964
=== modified file 'tests/unittests/test_util.py'
--- tests/unittests/test_util.py 2016-03-14 13:45:11 +0000
+++ tests/unittests/test_util.py 2016-05-18 22:38:52 +0000
@@ -37,6 +37,20 @@
37 self.restored.append(path)37 self.restored.append(path)
3838
3939
40class FakeCloudWithoutDomain(object):
41
42 def get_hostname(self, fqdn=False):
43 return "cloudname"
44
45
46class FakeCloudWithDomain(object):
47
48 def get_hostname(self, fqdn=False):
49 if fqdn:
50 return "cloudname.clouddomain"
51 return "cloudname"
52
53
40class TestGetCfgOptionListOrStr(helpers.TestCase):54class TestGetCfgOptionListOrStr(helpers.TestCase):
41 def test_not_found_no_default(self):55 def test_not_found_no_default(self):
42 """None is returned if key is not found and no default given."""56 """None is returned if key is not found and no default given."""
@@ -69,6 +83,79 @@
69 self.assertEqual([], result)83 self.assertEqual([], result)
7084
7185
86class TestGetHostnameFqdn(helpers.TestCase):
87 def setUp(self):
88 super(TestGetHostnameFqdn, self).setUp()
89 tmp_h, self.tmp_path = tempfile.mkstemp()
90 self.addCleanup(os.remove, self.tmp_path)
91 self.f = os.fdopen(tmp_h, "w")
92 self.f.write("9.10.11.12 cloudname.clouddomain cloudname\n")
93 self.f.close()
94 self.cloud = FakeCloudWithDomain()
95 self.cloud_no_domain = FakeCloudWithoutDomain()
96
97 def test_with_fqdn(self):
98 """Results based only on fqdn config key"""
99 cfg = {'fqdn': 'thisname.thisdomain'}
100 hostname, fqdn = util.get_hostname_fqdn(cfg, self.cloud, self.tmp_path)
101 self.assertEqual("thisname", hostname)
102 self.assertEqual("thisname.thisdomain", fqdn)
103
104 def test_with_dotted_hostname(self):
105 """Results based only on hostname config key"""
106 cfg = {'hostname': 'thisname.thisdomain'}
107 hostname, fqdn = util.get_hostname_fqdn(cfg, self.cloud, self.tmp_path)
108 self.assertEqual("thisname", hostname)
109 self.assertEqual("thisname.thisdomain", fqdn)
110
111 def test_with_short_hostname(self):
112 """The hostname is from config key, the fqdn from cloud"""
113 cfg = {'hostname': 'thisname'}
114 hostname, fqdn = util.get_hostname_fqdn(cfg, self.cloud, self.tmp_path)
115 self.assertEqual("thisname", hostname)
116 self.assertEqual("cloudname.clouddomain", fqdn)
117
118 def test_from_cloud(self):
119 """Results based only on cloud"""
120 cfg = {}
121 hostname, fqdn = util.get_hostname_fqdn(cfg, self.cloud, self.tmp_path)
122 self.assertEqual("cloudname", hostname)
123 self.assertEqual("cloudname.clouddomain", fqdn)
124
125 def test_from_cloud_without_domain(self):
126 """The hostname is from cloud, the fqdn mapped from hosts file"""
127 cfg = {}
128 hostname, fqdn = util.get_hostname_fqdn(cfg,
129 self.cloud_no_domain,
130 self.tmp_path)
131 self.assertEqual("cloudname", hostname)
132 self.assertEqual("cloudname.clouddomain", fqdn)
133
134
135class TestGetFqdnFromHosts(helpers.TestCase):
136 def setUp(self):
137 super(TestGetFqdnFromHosts, self).setUp()
138 tmp_h, self.tmp_path = tempfile.mkstemp()
139 self.addCleanup(os.remove, self.tmp_path)
140 self.f = os.fdopen(tmp_h, "w")
141 self.f.write("# comment\n")
142 self.f.write("1.2.3.4 name.domain name\n")
143 self.f.write("5.6.7.8 myname.mydomain myname # comment\n")
144 self.f.close()
145
146 def test_fqdn_found(self):
147 """Test fqdn is returned when hostname is found"""
148 hostname = "myname"
149 fqdn = util.get_fqdn_from_hosts(hostname, self.tmp_path)
150 self.assertEqual("myname.mydomain", fqdn)
151
152 def test_fqdn_not_found(self):
153 """Test None is returned when hostname is not found"""
154 hostname = "unnamed"
155 fqdn = util.get_fqdn_from_hosts(hostname, self.tmp_path)
156 self.assertEqual(None, fqdn)
157
158
72class TestWriteFile(helpers.TestCase):159class TestWriteFile(helpers.TestCase):
73 def setUp(self):160 def setUp(self):
74 super(TestWriteFile, self).setUp()161 super(TestWriteFile, self).setUp()