Repository: libcloud Updated Branches: refs/heads/trunk 9e8fa1b85 -> 860674ac7
Resolve a bug introduced by the original fix of the issue. 1- Add separated verifications for "None" and malformed metadata. A clear error will be raised upon malformed metadata. If undefined or already None, we assume None. 2- Provide comments explaining the odd GCE dictionary format. 3- Perform check on metadata dictionary structure. We expect one "items" key and a tuple of arbitrary values. 4- Prefix the keys/values provided by a simple dictionary by "items" if not found, enforcing point 3's structure. Closes #353 Signed-off-by: Tomaz Muraus <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/860674ac Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/860674ac Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/860674ac Branch: refs/heads/trunk Commit: 860674ac745a9c8b2e8b389d642257f3cce2329b Parents: 9e8fa1b Author: rtheberge <[email protected]> Authored: Fri Aug 29 09:41:14 2014 -0400 Committer: Tomaz Muraus <[email protected]> Committed: Fri Aug 29 18:18:02 2014 +0200 ---------------------------------------------------------------------- CHANGES.rst | 5 +++++ libcloud/compute/drivers/gce.py | 20 +++++++++++++++++--- libcloud/test/compute/test_gce.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/860674ac/CHANGES.rst ---------------------------------------------------------------------- diff --git a/CHANGES.rst b/CHANGES.rst index d52ab22..53345c8 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -73,6 +73,11 @@ Compute Libcloud. [Chris DeRamus] +- Fix a bug with ``ex_metadata`` argument handling in the Google Compute Engine + driver ``create_node`` method. + (LIBCLOUD-544, GITHUB-349, GITHUB-353) + [Raphael Theberge] + Storage ~~~~~~~ http://git-wip-us.apache.org/repos/asf/libcloud/blob/860674ac/libcloud/compute/drivers/gce.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/drivers/gce.py b/libcloud/compute/drivers/gce.py index a6f3c9f..9914324 100644 --- a/libcloud/compute/drivers/gce.py +++ b/libcloud/compute/drivers/gce.py @@ -1211,9 +1211,23 @@ class GCENodeDriver(NodeDriver): use_existing=use_existing_disk, ex_disk_type=ex_disk_type) - if ex_metadata is not None: - ex_metadata = {"items": [{"key": k, "value": v} - for k, v in ex_metadata.items()]} + if not ex_metadata: + ex_metadata = None + elif not isinstance(ex_metadata, dict): + raise ValueError('metadata field is not a dictionnary.') + else: + if 'items' not in ex_metadata: + # The expected GCE format is odd: + # items: [{'value': '1', 'key': 'one'}, + # {'value': '2', 'key': 'two'}, + # {'value': 'N', 'key': 'N'}] + # So the only real key is items, and the values are tuples + # Since arbitrary values are fine, we only check for the key. + # If missing, we prefix it to the items. + items = [] + for k, v in ex_metadata.items(): + items.append({'key': k, 'value': v}) + ex_metadata = {'items': items} request, node_data = self._create_node_req(name, size, image, location, ex_network, http://git-wip-us.apache.org/repos/asf/libcloud/blob/860674ac/libcloud/test/compute/test_gce.py ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/test_gce.py b/libcloud/test/compute/test_gce.py index 7d3855e..74cc8b6 100644 --- a/libcloud/test/compute/test_gce.py +++ b/libcloud/test/compute/test_gce.py @@ -19,6 +19,8 @@ import sys import unittest import datetime +from mock import Mock + from libcloud.utils.py3 import httplib from libcloud.compute.drivers.gce import (GCENodeDriver, API_VERSION, timestamp_to_datetime, @@ -291,6 +293,34 @@ class GCENodeDriverTest(LibcloudTestCase, TestCaseMixin): self.assertTrue(isinstance(node, Node)) self.assertEqual(node.name, node_name) + def test_create_node_with_metadata(self): + node_name = 'node-name' + image = self.driver.ex_get_image('debian-7') + size = self.driver.ex_get_size('n1-standard-1') + + self.driver._create_node_req = Mock() + self.driver._create_node_req.return_value = (None, None) + self.driver.connection.async_request = Mock() + self.driver.ex_get_node = Mock() + + # ex_metadata doesn't contain "items" key + ex_metadata = {'key1': 'value1', 'key2': 'value2'} + self.driver.create_node(node_name, size, image, + ex_metadata=ex_metadata) + + actual = self.driver._create_node_req.call_args[0][6] + self.assertTrue('items' in actual) + self.assertEqual(len(actual['items']), 2) + + # ex_metadata contains "items" key + ex_metadata = {'items': [{'key0': 'value0'}]} + self.driver.create_node(node_name, size, image, + ex_metadata=ex_metadata) + actual = self.driver._create_node_req.call_args[0][6] + self.assertTrue('items' in actual) + self.assertEqual(len(actual['items']), 1) + self.assertEqual(actual['items'][0], {'key0': 'value0'}) + def test_create_node_existing(self): node_name = 'libcloud-demo-europe-np-node' image = self.driver.ex_get_image('debian-7')
