Merge ~smoser/cloud-init:bug/1635350-tests-read-cfg.d into cloud-init:master

Proposed by Scott Moser
Status: Merged
Merged at revision: 1e55f4127f356b930e2c1ad36dcb6bed24f3beb2
Proposed branch: ~smoser/cloud-init:bug/1635350-tests-read-cfg.d
Merge into: cloud-init:master
Diff against target: 181 lines (+23/-30)
2 files modified
tests/unittests/helpers.py (+8/-0)
tests/unittests/test_data.py (+15/-30)
Reviewer Review Type Date Requested Status
Joshua Powers (community) Approve
cloud-init Commiters Pending
Review via email: mp+309124@code.launchpad.net

Commit message

unittests: do not read system /etc/cloud/cloud.cfg.d

Many of the unit tests in test_data would inadvertantly read the
system's /etc/cloud/cloud.cfg and /etc/cloud/cloud.cfg.d.
This was first noticed on a system deployed by MAAS, where
files in /etc/cloud/cloud.cfg.d/ are root read-only.

This changes those tests to actually make use of
FilesystemMockingTestCase functionality and adds 'reRoot()' to that
class which is easier to use for at least this use case.

LP: #1635350

To post a comment you must log in.
Revision history for this message
Joshua Powers (powersj) wrote :

Can confirm this merge request fixes the issue that I was seeing. I can now build as a non-root user as expected.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/tests/unittests/helpers.py b/tests/unittests/helpers.py
index 1cdc05a..a2355a7 100644
--- a/tests/unittests/helpers.py
+++ b/tests/unittests/helpers.py
@@ -205,6 +205,14 @@ class FilesystemMockingTestCase(ResourceUsingTestCase):
205 self.patched_funcs.enter_context(205 self.patched_funcs.enter_context(
206 mock.patch.object(sys, 'stderr', stderr))206 mock.patch.object(sys, 'stderr', stderr))
207207
208 def reRoot(self, root=None):
209 if root is None:
210 root = tempfile.mkdtemp()
211 self.addCleanup(shutil.rmtree, root)
212 self.patchUtils(root)
213 self.patchOS(root)
214 return root
215
208216
209def import_httpretty():217def import_httpretty():
210 """Import HTTPretty and monkey patch Python 3.4 issue.218 """Import HTTPretty and monkey patch Python 3.4 issue.
diff --git a/tests/unittests/test_data.py b/tests/unittests/test_data.py
index 13db8a4..55d9b93 100644
--- a/tests/unittests/test_data.py
+++ b/tests/unittests/test_data.py
@@ -3,8 +3,6 @@
3import gzip3import gzip
4import logging4import logging
5import os5import os
6import shutil
7import tempfile
86
9try:7try:
10 from unittest import mock8 from unittest import mock
@@ -98,10 +96,7 @@ class TestConsumeUserData(helpers.FilesystemMockingTestCase):
9896
99 ci = stages.Init()97 ci = stages.Init()
100 ci.datasource = FakeDataSource(blob)98 ci.datasource = FakeDataSource(blob)
101 new_root = tempfile.mkdtemp()99 self.reRoot()
102 self.addCleanup(shutil.rmtree, new_root)
103 self.patchUtils(new_root)
104 self.patchOS(new_root)
105 ci.fetch()100 ci.fetch()
106 ci.consume_data()101 ci.consume_data()
107 cc_contents = util.load_file(ci.paths.get_ipath("cloud_config"))102 cc_contents = util.load_file(ci.paths.get_ipath("cloud_config"))
@@ -127,9 +122,7 @@ class TestConsumeUserData(helpers.FilesystemMockingTestCase):
127 { "op": "add", "path": "/foo", "value": "quxC" }122 { "op": "add", "path": "/foo", "value": "quxC" }
128]123]
129'''124'''
130 new_root = tempfile.mkdtemp()125 self.reRoot()
131 self.addCleanup(shutil.rmtree, new_root)
132 self._patchIn(new_root)
133 initer = stages.Init()126 initer = stages.Init()
134 initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)127 initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)
135 initer.read_cfg()128 initer.read_cfg()
@@ -167,9 +160,7 @@ class TestConsumeUserData(helpers.FilesystemMockingTestCase):
167 { "op": "add", "path": "/foo", "value": "quxC" }160 { "op": "add", "path": "/foo", "value": "quxC" }
168]161]
169'''162'''
170 new_root = tempfile.mkdtemp()163 self.reRoot()
171 self.addCleanup(shutil.rmtree, new_root)
172 self._patchIn(new_root)
173 initer = stages.Init()164 initer = stages.Init()
174 initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)165 initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)
175 initer.read_cfg()166 initer.read_cfg()
@@ -212,12 +203,9 @@ c: d
212 message.attach(message_cc)203 message.attach(message_cc)
213 message.attach(message_jp)204 message.attach(message_jp)
214205
206 self.reRoot()
215 ci = stages.Init()207 ci = stages.Init()
216 ci.datasource = FakeDataSource(str(message))208 ci.datasource = FakeDataSource(str(message))
217 new_root = tempfile.mkdtemp()
218 self.addCleanup(shutil.rmtree, new_root)
219 self.patchUtils(new_root)
220 self.patchOS(new_root)
221 ci.fetch()209 ci.fetch()
222 ci.consume_data()210 ci.consume_data()
223 cc_contents = util.load_file(ci.paths.get_ipath("cloud_config"))211 cc_contents = util.load_file(ci.paths.get_ipath("cloud_config"))
@@ -245,9 +233,7 @@ name: user
245run:233run:
246 - z234 - z
247'''235'''
248 new_root = tempfile.mkdtemp()236 self.reRoot()
249 self.addCleanup(shutil.rmtree, new_root)
250 self._patchIn(new_root)
251 initer = stages.Init()237 initer = stages.Init()
252 initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)238 initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)
253 initer.read_cfg()239 initer.read_cfg()
@@ -281,9 +267,7 @@ vendor_data:
281 enabled: True267 enabled: True
282 prefix: /bin/true268 prefix: /bin/true
283'''269'''
284 new_root = tempfile.mkdtemp()270 new_root = self.reRoot()
285 self.addCleanup(shutil.rmtree, new_root)
286 self._patchIn(new_root)
287 initer = stages.Init()271 initer = stages.Init()
288 initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)272 initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)
289 initer.read_cfg()273 initer.read_cfg()
@@ -342,10 +326,7 @@ p: 1
342 paths = c_helpers.Paths({}, ds=FakeDataSource(''))326 paths = c_helpers.Paths({}, ds=FakeDataSource(''))
343 cloud_cfg = handlers.cloud_config.CloudConfigPartHandler(paths)327 cloud_cfg = handlers.cloud_config.CloudConfigPartHandler(paths)
344328
345 new_root = tempfile.mkdtemp()329 self.reRoot()
346 self.addCleanup(shutil.rmtree, new_root)
347 self.patchUtils(new_root)
348 self.patchOS(new_root)
349 cloud_cfg.handle_part(None, handlers.CONTENT_START, None, None, None,330 cloud_cfg.handle_part(None, handlers.CONTENT_START, None, None, None,
350 None)331 None)
351 for i, m in enumerate(messages):332 for i, m in enumerate(messages):
@@ -365,6 +346,7 @@ p: 1
365346
366 def test_unhandled_type_warning(self):347 def test_unhandled_type_warning(self):
367 """Raw text without magic is ignored but shows warning."""348 """Raw text without magic is ignored but shows warning."""
349 self.reRoot()
368 ci = stages.Init()350 ci = stages.Init()
369 data = "arbitrary text\n"351 data = "arbitrary text\n"
370 ci.datasource = FakeDataSource(data)352 ci.datasource = FakeDataSource(data)
@@ -402,10 +384,7 @@ c: 4
402 message.attach(gzip_part(base_content2))384 message.attach(gzip_part(base_content2))
403 ci = stages.Init()385 ci = stages.Init()
404 ci.datasource = FakeDataSource(str(message))386 ci.datasource = FakeDataSource(str(message))
405 new_root = tempfile.mkdtemp()387 self.reRoot()
406 self.addCleanup(shutil.rmtree, new_root)
407 self.patchUtils(new_root)
408 self.patchOS(new_root)
409 ci.fetch()388 ci.fetch()
410 ci.consume_data()389 ci.consume_data()
411 contents = util.load_file(ci.paths.get_ipath("cloud_config"))390 contents = util.load_file(ci.paths.get_ipath("cloud_config"))
@@ -418,6 +397,7 @@ c: 4
418397
419 def test_mime_text_plain(self):398 def test_mime_text_plain(self):
420 """Mime message of type text/plain is ignored but shows warning."""399 """Mime message of type text/plain is ignored but shows warning."""
400 self.reRoot()
421 ci = stages.Init()401 ci = stages.Init()
422 message = MIMEBase("text", "plain")402 message = MIMEBase("text", "plain")
423 message.set_payload("Just text")403 message.set_payload("Just text")
@@ -435,6 +415,7 @@ c: 4
435415
436 def test_shellscript(self):416 def test_shellscript(self):
437 """Raw text starting #!/bin/sh is treated as script."""417 """Raw text starting #!/bin/sh is treated as script."""
418 self.reRoot()
438 ci = stages.Init()419 ci = stages.Init()
439 script = "#!/bin/sh\necho hello\n"420 script = "#!/bin/sh\necho hello\n"
440 ci.datasource = FakeDataSource(script)421 ci.datasource = FakeDataSource(script)
@@ -453,6 +434,7 @@ c: 4
453434
454 def test_mime_text_x_shellscript(self):435 def test_mime_text_x_shellscript(self):
455 """Mime message of type text/x-shellscript is treated as script."""436 """Mime message of type text/x-shellscript is treated as script."""
437 self.reRoot()
456 ci = stages.Init()438 ci = stages.Init()
457 script = "#!/bin/sh\necho hello\n"439 script = "#!/bin/sh\necho hello\n"
458 message = MIMEBase("text", "x-shellscript")440 message = MIMEBase("text", "x-shellscript")
@@ -473,6 +455,7 @@ c: 4
473455
474 def test_mime_text_plain_shell(self):456 def test_mime_text_plain_shell(self):
475 """Mime type text/plain starting #!/bin/sh is treated as script."""457 """Mime type text/plain starting #!/bin/sh is treated as script."""
458 self.reRoot()
476 ci = stages.Init()459 ci = stages.Init()
477 script = "#!/bin/sh\necho hello\n"460 script = "#!/bin/sh\necho hello\n"
478 message = MIMEBase("text", "plain")461 message = MIMEBase("text", "plain")
@@ -493,6 +476,7 @@ c: 4
493476
494 def test_mime_application_octet_stream(self):477 def test_mime_application_octet_stream(self):
495 """Mime type application/octet-stream is ignored but shows warning."""478 """Mime type application/octet-stream is ignored but shows warning."""
479 self.reRoot()
496 ci = stages.Init()480 ci = stages.Init()
497 message = MIMEBase("application", "octet-stream")481 message = MIMEBase("application", "octet-stream")
498 message.set_payload(b'\xbf\xe6\xb2\xc3\xd3\xba\x13\xa4\xd8\xa1\xcc')482 message.set_payload(b'\xbf\xe6\xb2\xc3\xd3\xba\x13\xa4\xd8\xa1\xcc')
@@ -516,6 +500,7 @@ c: 4
516 {'content': non_decodable}]500 {'content': non_decodable}]
517 message = b'#cloud-config-archive\n' + util.yaml_dumps(data).encode()501 message = b'#cloud-config-archive\n' + util.yaml_dumps(data).encode()
518502
503 self.reRoot()
519 ci = stages.Init()504 ci = stages.Init()
520 ci.datasource = FakeDataSource(message)505 ci.datasource = FakeDataSource(message)
521506

Subscribers

People subscribed via source and target branches