summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Moser <smoser@ubuntu.com>2016-06-22 10:08:29 -0400
committerScott Moser <smoser@ubuntu.com>2016-06-22 10:08:29 -0400
commitc1b11d5e5432dee0042e9e568bd63cfe05f8a9b2 (patch)
tree9831898dbfe7767d750227bd5d748713260f1586
parent94244b4b2375ae1aba1167dd2b03b1227bad89e3 (diff)
parentfe15c8d01619a62f50d19e84619d52cbba14cbea (diff)
downloadcloud-init-c1b11d5e5432dee0042e9e568bd63cfe05f8a9b2.tar.gz
user_data: fix error when user-data is not utf-8 decodable
when user-data was not decodable, cloud-init would raise exception. This also changes the signature of user_data.convert_string. The 'headers' argument was never used, and woudl have been broken if it was, as it was expected to be a dictionary but then was passed in with *headers.
-rw-r--r--ChangeLog1
-rw-r--r--cloudinit/user_data.py28
-rw-r--r--tests/unittests/test_data.py17
3 files changed, 34 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 8edf3249..fa5e7df4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -125,6 +125,7 @@
- Remove trailing dot from GCE metadata URL (LP: #1581200) [Phil Roche]
- support network rendering to sysconfig (for centos and RHEL)
- write_files: if no permissions are given, just use default without warn.
+ - user_data: fix error when user-data is not utf-8 decodable (LP: #1532072)
0.7.6:
- open 0.7.6
diff --git a/cloudinit/user_data.py b/cloudinit/user_data.py
index f0631906..393bf0bb 100644
--- a/cloudinit/user_data.py
+++ b/cloudinit/user_data.py
@@ -334,19 +334,23 @@ def is_skippable(part):
# Coverts a raw string into a mime message
-def convert_string(raw_data, headers=None):
+def convert_string(raw_data, content_type=NOT_MULTIPART_TYPE):
if not raw_data:
raw_data = ''
- if not headers:
- headers = {}
- data = util.decode_binary(util.decomp_gzip(raw_data))
- if "mime-version:" in data[0:4096].lower():
- msg = util.message_from_string(data)
- for (key, val) in headers.items():
- _replace_header(msg, key, val)
- else:
- mtype = headers.get(CONTENT_TYPE, NOT_MULTIPART_TYPE)
- maintype, subtype = mtype.split("/", 1)
- msg = MIMEBase(maintype, subtype, *headers)
+
+ def create_binmsg(data, content_type):
+ maintype, subtype = content_type.split("/", 1)
+ msg = MIMEBase(maintype, subtype)
msg.set_payload(data)
+ return msg
+
+ try:
+ data = util.decode_binary(util.decomp_gzip(raw_data))
+ if "mime-version:" in data[0:4096].lower():
+ msg = util.message_from_string(data)
+ else:
+ msg = create_binmsg(data, content_type)
+ except UnicodeDecodeError:
+ msg = create_binmsg(raw_data, content_type)
+
return msg
diff --git a/tests/unittests/test_data.py b/tests/unittests/test_data.py
index 1923e2af..13db8a4c 100644
--- a/tests/unittests/test_data.py
+++ b/tests/unittests/test_data.py
@@ -557,3 +557,20 @@ class TestUDProcess(helpers.ResourceUsingTestCase):
ud_proc = ud.UserDataProcessor(self.getCloudPaths())
message = ud_proc.process(msg)
self.assertTrue(count_messages(message) == 1)
+
+
+class TestConvertString(helpers.TestCase):
+ def test_handles_binary_non_utf8_decodable(self):
+ blob = b'\x32\x99'
+ msg = ud.convert_string(blob)
+ self.assertEqual(blob, msg.get_payload(decode=True))
+
+ def test_handles_binary_utf8_decodable(self):
+ blob = b'\x32\x32'
+ msg = ud.convert_string(blob)
+ self.assertEqual(blob, msg.get_payload(decode=True))
+
+ def test_handle_headers(self):
+ text = "hi mom"
+ msg = ud.convert_string(text)
+ self.assertEqual(text, msg.get_payload(decode=False))