Skip to content

Commit fcb68a4

Browse files
committed
Move parse_data to utils.serialization
Move and rename VMwareGuestInfoService._parse_data to cloudbaseinit.utils.serialization.parse_json_yaml so that it can be easiliy reused. Change-Id: I3b86efd5e2b2062f89ffc7745f6f0481ec665078
1 parent 3e5b5f3 commit fcb68a4

File tree

4 files changed

+91
-47
lines changed

4 files changed

+91
-47
lines changed

cloudbaseinit/metadata/services/vmwareguestinfoservice.py

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,20 @@
1616
import base64
1717
import gzip
1818
import io
19-
import json
2019
import os
21-
import yaml
2220

2321
from oslo_log import log as oslo_logging
2422

2523
from cloudbaseinit import conf as cloudbaseinit_conf
2624
from cloudbaseinit import exception
2725
from cloudbaseinit.metadata.services import base
2826
from cloudbaseinit.osutils import factory as osutils_factory
27+
from cloudbaseinit.utils import serialization
2928

3029
CONF = cloudbaseinit_conf.CONF
3130
LOG = oslo_logging.getLogger(__name__)
3231

3332

34-
class YamlParserConfigError(Exception):
35-
"""Exception for Yaml parsing failures"""
36-
pass
37-
38-
3933
class VMwareGuestInfoService(base.BaseMetadataService):
4034
def __init__(self):
4135
super(VMwareGuestInfoService, self).__init__()
@@ -44,19 +38,6 @@ def __init__(self):
4438
self._meta_data = {}
4539
self._user_data = None
4640

47-
@staticmethod
48-
def _parse_data(raw_data):
49-
"""Parse data as json. Fallback to yaml if json parsing fails"""
50-
51-
try:
52-
return json.loads(raw_data)
53-
except (TypeError, ValueError, AttributeError):
54-
loader = getattr(yaml, 'CLoader', yaml.Loader)
55-
try:
56-
return yaml.load(raw_data, Loader=loader)
57-
except (TypeError, ValueError, AttributeError):
58-
raise YamlParserConfigError("Invalid yaml data provided.")
59-
6041
@staticmethod
6142
def _decode_data(raw_data, is_base64, is_gzip):
6243
"""Decode raw_data from base64 / ungzip"""
@@ -133,7 +114,8 @@ def load(self):
133114
% self._rpc_tool_path)
134115
return False
135116

136-
self._meta_data = self._parse_data(self._get_guest_data('metadata'))
117+
self._meta_data = serialization.parse_json_yaml(
118+
self._get_guest_data('metadata'))
137119
if not isinstance(self._meta_data, dict):
138120
LOG.warning("Instance metadata is not a dictionary.")
139121
self._meta_data = {}

cloudbaseinit/tests/metadata/services/test_vmwareguestinfoservice.py

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import unittest
1717

1818
import ddt
19-
import yaml
2019

2120
try:
2221
import unittest.mock as mock
@@ -46,30 +45,6 @@ def setUp(self, mock_os_utils):
4645
self._service = (self._module.VMwareGuestInfoService())
4746
self.snatcher = testutils.LogSnatcher(BASE_MODULE_PATH)
4847

49-
@ddt.data((b'', (None, False)),
50-
(b'{}', ({}, False)),
51-
(b'---', (None, True)),
52-
(b'test: test', ({"test": "test"}, True)))
53-
@ddt.unpack
54-
@mock.patch("json.loads")
55-
@mock.patch("yaml.load")
56-
def test_parse_data(self, stream, expected_parsed_output,
57-
mock_yaml_load, mock_json_loads):
58-
if not expected_parsed_output[1]:
59-
mock_json_loads.return_value = expected_parsed_output[0]
60-
else:
61-
mock_json_loads.side_effect = TypeError("Failed to parse json")
62-
mock_yaml_load.return_value = expected_parsed_output[0]
63-
64-
parsed_output = self._service._parse_data(stream)
65-
66-
mock_json_loads.assert_called_once_with(stream)
67-
if expected_parsed_output[1]:
68-
loader = getattr(yaml, 'CLoader', yaml.Loader)
69-
mock_yaml_load.assert_called_once_with(stream, Loader=loader)
70-
71-
self.assertEqual(parsed_output, expected_parsed_output[0])
72-
7348
@ddt.data(((None, False, False), None),
7449
(('', False, False), None),
7550
(('dGVzdCANCg==', True, False), b'test \r\n'),
@@ -111,7 +86,7 @@ def test_load_rpc_tool_not_existent(self):
11186
self._test_load_no_rpc_tool(expected_output, 'fake_path')
11287

11388
@mock.patch('os.path.exists')
114-
@mock.patch(MODULE_PATH + "._parse_data")
89+
@mock.patch('cloudbaseinit.utils.serialization.parse_json_yaml')
11590
@mock.patch(MODULE_PATH + "._get_guest_data")
11691
def _test_load_meta_data(self, mock_get_guestinfo, mock_parse,
11792
mock_os_path_exists, parse_return=None,
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Copyright 2014 Cloudbase Solutions Srl
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
15+
import unittest
16+
17+
import ddt
18+
import yaml
19+
20+
try:
21+
import unittest.mock as mock
22+
except ImportError:
23+
import mock
24+
25+
from cloudbaseinit.utils import serialization
26+
27+
28+
@ddt.ddt
29+
class SerializationUtilsTests(unittest.TestCase):
30+
31+
@ddt.data((b'', (None, False)),
32+
(b'{}', ({}, False)),
33+
(b'---', (None, True)),
34+
(b'test: test', ({"test": "test"}, True)))
35+
@ddt.unpack
36+
@mock.patch("json.loads")
37+
@mock.patch("yaml.load")
38+
def test_parse_data(self, stream, expected_parsed_output,
39+
mock_yaml_load, mock_json_loads):
40+
if not expected_parsed_output[1]:
41+
mock_json_loads.return_value = expected_parsed_output[0]
42+
else:
43+
mock_json_loads.side_effect = TypeError("Failed to parse json")
44+
mock_yaml_load.return_value = expected_parsed_output[0]
45+
46+
parsed_output = serialization.parse_json_yaml(stream)
47+
48+
mock_json_loads.assert_called_once_with(stream)
49+
if expected_parsed_output[1]:
50+
loader = getattr(yaml, 'CLoader', yaml.Loader)
51+
mock_yaml_load.assert_called_once_with(stream, Loader=loader)
52+
53+
self.assertEqual(parsed_output, expected_parsed_output[0])
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Copyright 2020 Cloudbase Solutions Srl
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
15+
import json
16+
import yaml
17+
18+
19+
class YamlParserConfigError(Exception):
20+
"""Exception for Yaml parsing failures"""
21+
pass
22+
23+
24+
def parse_json_yaml(raw_data):
25+
"""Parse data as json. Fallback to yaml if json parsing fails"""
26+
27+
try:
28+
return json.loads(raw_data)
29+
except (TypeError, ValueError, AttributeError):
30+
loader = getattr(yaml, 'CLoader', yaml.Loader)
31+
try:
32+
return yaml.load(raw_data, Loader=loader)
33+
except (TypeError, ValueError, AttributeError):
34+
raise YamlParserConfigError("Invalid yaml data provided.")

0 commit comments

Comments
 (0)