diff options
author | Andrew Jorgensen <ajorgens@amazon.com> | 2017-08-14 17:08:37 +0000 |
---|---|---|
committer | Scott Moser <smoser@ubuntu.com> | 2017-08-25 14:46:19 -0700 |
commit | 20ca23cab0bdfdffa567f8fb4b49f3727bac6444 (patch) | |
tree | 50df8ca6773a7088357c1c7061dd728acd789320 | |
parent | 89579a68d9f51e51b24f96b933da656afd83edfb (diff) | |
download | vyos-cloud-init-20ca23cab0bdfdffa567f8fb4b49f3727bac6444.tar.gz vyos-cloud-init-20ca23cab0bdfdffa567f8fb4b49f3727bac6444.zip |
Log a helpful message if a user script does not include shebang.
A patch to allow scripts missing a #! to run by using shell=True was
proposed but rejected. Instead we emit a log message to help the user
understand what went wrong.
-rw-r--r-- | cloudinit/util.py | 20 | ||||
-rw-r--r-- | tests/unittests/test_util.py | 13 |
2 files changed, 24 insertions, 9 deletions
diff --git a/cloudinit/util.py b/cloudinit/util.py index ce2c6034..609e94c8 100644 --- a/cloudinit/util.py +++ b/cloudinit/util.py @@ -12,7 +12,6 @@ import contextlib import copy as obj_copy import ctypes import email -import errno import glob import grp import gzip @@ -34,6 +33,8 @@ import sys import tempfile import time +from errno import ENOENT, ENOEXEC + from base64 import b64decode, b64encode from six.moves.urllib import parse as urlparse @@ -239,7 +240,10 @@ class ProcessExecutionError(IOError): self.cmd = cmd if not description: - self.description = 'Unexpected error while running command.' + if not exit_code and errno == ENOEXEC: + self.description = 'Exec format error. Missing #! in script?' + else: + self.description = 'Unexpected error while running command.' else: self.description = description @@ -433,7 +437,7 @@ def read_conf(fname): try: return load_yaml(load_file(fname), default={}) except IOError as e: - if e.errno == errno.ENOENT: + if e.errno == ENOENT: return {} else: raise @@ -901,7 +905,7 @@ def read_file_or_url(url, timeout=5, retries=10, contents = load_file(file_path, decode=False) except IOError as e: code = e.errno - if e.errno == errno.ENOENT: + if e.errno == ENOENT: code = url_helper.NOT_FOUND raise url_helper.UrlError(cause=e, code=code, headers=None, url=url) @@ -1247,7 +1251,7 @@ def find_devs_with(criteria=None, oformat='device', try: (out, _err) = subp(cmd, rcs=[0, 2]) except ProcessExecutionError as e: - if e.errno == errno.ENOENT: + if e.errno == ENOENT: # blkid not found... out = "" else: @@ -1285,7 +1289,7 @@ def load_file(fname, read_cb=None, quiet=False, decode=True): except IOError as e: if not quiet: raise - if e.errno != errno.ENOENT: + if e.errno != ENOENT: raise contents = ofh.getvalue() LOG.debug("Read %s bytes from %s", len(contents), fname) @@ -1653,7 +1657,7 @@ def del_file(path): try: os.unlink(path) except OSError as e: - if e.errno != errno.ENOENT: + if e.errno != ENOENT: raise e @@ -2281,7 +2285,7 @@ def pathprefix2dict(base, required=None, optional=None, delim=os.path.sep): try: ret[f] = load_file(base + delim + f, quiet=False, decode=False) except IOError as e: - if e.errno != errno.ENOENT: + if e.errno != ENOENT: raise if f in required: missing.append(f) diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py index f38a664c..5f11c88f 100644 --- a/tests/unittests/test_util.py +++ b/tests/unittests/test_util.py @@ -568,7 +568,8 @@ class TestReadSeeded(helpers.TestCase): self.assertEqual(found_ud, ud) -class TestSubp(helpers.TestCase): +class TestSubp(helpers.CiTestCase): + with_logs = True stdin2err = [BASH, '-c', 'cat >&2'] stdin2out = ['cat'] @@ -650,6 +651,16 @@ class TestSubp(helpers.TestCase): self.assertEqual( ['FOO=BAR', 'HOME=/myhome', 'K1=V1', 'K2=V2'], out.splitlines()) + def test_subp_warn_missing_shebang(self): + """Warn on no #! in script""" + noshebang = self.tmp_path('noshebang') + util.write_file(noshebang, 'true\n') + + os.chmod(noshebang, os.stat(noshebang).st_mode | stat.S_IEXEC) + self.assertRaisesRegexp(util.ProcessExecutionError, + 'Missing #! in script\?', + util.subp, (noshebang,)) + def test_returns_none_if_no_capture(self): (out, err) = util.subp(self.stdin2out, data=b'', capture=False) self.assertIsNone(err) |