diff --git a/heat/engine/clients/os/nova.py b/heat/engine/clients/os/nova.py index 1740efaa6d..52dca39f67 100644 --- a/heat/engine/clients/os/nova.py +++ b/heat/engine/clients/os/nova.py @@ -11,6 +11,7 @@ # License for the specific language governing permissions and limitations # under the License. +import collections import email from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText @@ -375,6 +376,10 @@ echo -e '%s\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers Serialize non-string metadata values before sending them to Nova. """ + if not isinstance(metadata, collections.Mapping): + raise exception.StackValidationFailed(message=_( + "nova server metadata needs to be a Map.")) + return dict((key, (value if isinstance(value, six.string_types) else json.dumps(value)) diff --git a/heat/tests/test_nova_client.py b/heat/tests/test_nova_client.py index 2120c8e98a..3eb6ff20aa 100644 --- a/heat/tests/test_nova_client.py +++ b/heat/tests/test_nova_client.py @@ -15,6 +15,7 @@ import mock from novaclient import exceptions as nova_exceptions from oslo.config import cfg +import six import uuid from heat.common import exception @@ -232,6 +233,14 @@ class NovaUtilsMetadataTests(NovaClientPluginTestCase): expected = {'test_key': 'null'} self.assertEqual(expected, self.nova_plugin.meta_serialize(original)) + def test_serialize_no_value(self): + """This test is to prove that the user can only pass in a dict to nova + metadata. + """ + excp = self.assertRaises(exception.StackValidationFailed, + self.nova_plugin.meta_serialize, "foo") + self.assertIn('metadata needs to be a Map', six.text_type(excp)) + def test_serialize_combined(self): original = { 'test_key_1': 123,