← Back to team overview

cloud-init-dev team mailing list archive

[Merge] ~smoser/cloud-init:bug/1619394 into cloud-init:master

 

Scott Moser has proposed merging ~smoser/cloud-init:bug/1619394 into cloud-init:master.

Requested reviews:
  cloud init development team (cloud-init-dev)
Related bugs:
  Bug #1619394 in cloud-init: "OVF datasource broken"
  https://bugs.launchpad.net/cloud-init/+bug/1619394

For more details, see:
https://code.launchpad.net/~smoser/cloud-init/+git/cloud-init/+merge/305496
-- 
Your team cloud init development team is requested to review the proposed merge of ~smoser/cloud-init:bug/1619394 into cloud-init:master.
diff --git a/cloudinit/sources/DataSourceOVF.py b/cloudinit/sources/DataSourceOVF.py
index 43347cf..f108ad1 100644
--- a/cloudinit/sources/DataSourceOVF.py
+++ b/cloudinit/sources/DataSourceOVF.py
@@ -268,9 +268,9 @@ def read_ovf_environment(contents):
             cfg[prop] = val
         elif prop == "user-data":
             try:
-                ud = base64.decodestring(val)
+                ud = base64.decodestring(val.encode())
             except Exception:
-                ud = val
+                ud = val.encode()
     return (md, ud, cfg)
 
 
diff --git a/tests/unittests/test_datasource/test_ovf.py b/tests/unittests/test_datasource/test_ovf.py
new file mode 100644
index 0000000..98c2a30
--- /dev/null
+++ b/tests/unittests/test_datasource/test_ovf.py
@@ -0,0 +1,85 @@
+# vi: ts=4 expandtab
+#
+#    Copyright (C) 2016 Canonical Ltd.
+#
+#    Author: Scott Moser <scott.moser@xxxxxxxxxxxxx>
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License version 3, as
+#    published by the Free Software Foundation.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import base64
+import json
+
+from .. import helpers as test_helpers
+
+from cloudinit.sources import DataSourceOVF as dsovf
+
+OVF_ENV_CONTENT = """<?xml version="1.0" encoding="UTF-8"?>
+<Environment xmlns="http://schemas.dmtf.org/ovf/environment/1";
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+    xmlns:oe="http://schemas.dmtf.org/ovf/environment/1";
+    xsi:schemaLocation="http://schemas.dmtf.org/ovf/environment/1 ../dsp8027.xsd"
+    oe:id="WebTier">
+    <!-- This example reference a local schema file, to validate against online schema use:
+    xsi:schemaLocation="http://schemas.dmtf.org/ovf/envelope/1 http://schemas.dmtf.org/ovf/envelope/1/dsp8027_1.0.0.xsd";
+    -->
+    <!-- Information about hypervisor platform -->
+    <oe:PlatformSection>
+        <Kind>ESX Server</Kind>
+        <Version>3.0.1</Version>
+        <Vendor>VMware, Inc.</Vendor>
+        <Locale>en_US</Locale>
+    </oe:PlatformSection>
+    <!--- Properties defined for this virtual machine -->
+    <PropertySection>
+{properties}
+    </PropertySection>
+</Environment>
+"""
+
+def fill_properties(props, template=OVF_ENV_CONTENT):
+    lines = []
+    prop_tmpl = '<Property oe:key="{key}" oe:value="{val}"/>'
+    for key, val in props.items():
+        lines.append(prop_tmpl.format(key=key, val=val))
+    indent = "        "
+    properties = ''.join([indent + l + "\n" for l in lines])
+    return template.format(properties=properties)
+
+
+class TestReadOvfEnv(test_helpers.TestCase):
+    def test_with_b64_userdata(self):
+        user_data = "#!/bin/sh\necho hello world\n"
+        user_data_b64 = base64.b64encode(user_data.encode()).decode()
+        props = {"user-data": user_data_b64, "password": "passw0rd",
+                 "instance-id": "inst-001"}
+        env = fill_properties(props)
+        md, ud, cfg = dsovf.read_ovf_environment(env)
+        self.assertEqual({"instance-id": "inst-001"}, md)
+        self.assertEqual(user_data.encode(), ud)
+        self.assertEqual({'password': "passw0rd"}, cfg)
+
+    def test_with_non_b64_userdata(self):
+        user_data = "my-user-data"
+        props = {"user-data": user_data, "instance-id": "inst-001"}
+        env = fill_properties(props)
+        md, ud, cfg = dsovf.read_ovf_environment(env)
+        self.assertEqual({"instance-id": "inst-001"}, md)
+        self.assertEqual(user_data.encode(), ud)
+        self.assertEqual({}, cfg)
+
+    def test_with_no_userdata(self):
+        props = {"password": "passw0rd", "instance-id": "inst-001"}
+        env = fill_properties(props)
+        md, ud, cfg = dsovf.read_ovf_environment(env)
+        self.assertEqual({"instance-id": "inst-001"}, md)
+        self.assertEqual({'password': "passw0rd"}, cfg)

Follow ups