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
This commit is contained in:
parent
3e5b5f37ff
commit
fcb68a4dc7
@ -16,9 +16,7 @@
|
||||
import base64
|
||||
import gzip
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import yaml
|
||||
|
||||
from oslo_log import log as oslo_logging
|
||||
|
||||
@ -26,16 +24,12 @@ from cloudbaseinit import conf as cloudbaseinit_conf
|
||||
from cloudbaseinit import exception
|
||||
from cloudbaseinit.metadata.services import base
|
||||
from cloudbaseinit.osutils import factory as osutils_factory
|
||||
from cloudbaseinit.utils import serialization
|
||||
|
||||
CONF = cloudbaseinit_conf.CONF
|
||||
LOG = oslo_logging.getLogger(__name__)
|
||||
|
||||
|
||||
class YamlParserConfigError(Exception):
|
||||
"""Exception for Yaml parsing failures"""
|
||||
pass
|
||||
|
||||
|
||||
class VMwareGuestInfoService(base.BaseMetadataService):
|
||||
def __init__(self):
|
||||
super(VMwareGuestInfoService, self).__init__()
|
||||
@ -44,19 +38,6 @@ class VMwareGuestInfoService(base.BaseMetadataService):
|
||||
self._meta_data = {}
|
||||
self._user_data = None
|
||||
|
||||
@staticmethod
|
||||
def _parse_data(raw_data):
|
||||
"""Parse data as json. Fallback to yaml if json parsing fails"""
|
||||
|
||||
try:
|
||||
return json.loads(raw_data)
|
||||
except (TypeError, ValueError, AttributeError):
|
||||
loader = getattr(yaml, 'CLoader', yaml.Loader)
|
||||
try:
|
||||
return yaml.load(raw_data, Loader=loader)
|
||||
except (TypeError, ValueError, AttributeError):
|
||||
raise YamlParserConfigError("Invalid yaml data provided.")
|
||||
|
||||
@staticmethod
|
||||
def _decode_data(raw_data, is_base64, is_gzip):
|
||||
"""Decode raw_data from base64 / ungzip"""
|
||||
@ -133,7 +114,8 @@ class VMwareGuestInfoService(base.BaseMetadataService):
|
||||
% self._rpc_tool_path)
|
||||
return False
|
||||
|
||||
self._meta_data = self._parse_data(self._get_guest_data('metadata'))
|
||||
self._meta_data = serialization.parse_json_yaml(
|
||||
self._get_guest_data('metadata'))
|
||||
if not isinstance(self._meta_data, dict):
|
||||
LOG.warning("Instance metadata is not a dictionary.")
|
||||
self._meta_data = {}
|
||||
|
@ -16,7 +16,6 @@ import importlib
|
||||
import unittest
|
||||
|
||||
import ddt
|
||||
import yaml
|
||||
|
||||
try:
|
||||
import unittest.mock as mock
|
||||
@ -46,30 +45,6 @@ class VMwareGuestInfoServiceTest(unittest.TestCase):
|
||||
self._service = (self._module.VMwareGuestInfoService())
|
||||
self.snatcher = testutils.LogSnatcher(BASE_MODULE_PATH)
|
||||
|
||||
@ddt.data((b'', (None, False)),
|
||||
(b'{}', ({}, False)),
|
||||
(b'---', (None, True)),
|
||||
(b'test: test', ({"test": "test"}, True)))
|
||||
@ddt.unpack
|
||||
@mock.patch("json.loads")
|
||||
@mock.patch("yaml.load")
|
||||
def test_parse_data(self, stream, expected_parsed_output,
|
||||
mock_yaml_load, mock_json_loads):
|
||||
if not expected_parsed_output[1]:
|
||||
mock_json_loads.return_value = expected_parsed_output[0]
|
||||
else:
|
||||
mock_json_loads.side_effect = TypeError("Failed to parse json")
|
||||
mock_yaml_load.return_value = expected_parsed_output[0]
|
||||
|
||||
parsed_output = self._service._parse_data(stream)
|
||||
|
||||
mock_json_loads.assert_called_once_with(stream)
|
||||
if expected_parsed_output[1]:
|
||||
loader = getattr(yaml, 'CLoader', yaml.Loader)
|
||||
mock_yaml_load.assert_called_once_with(stream, Loader=loader)
|
||||
|
||||
self.assertEqual(parsed_output, expected_parsed_output[0])
|
||||
|
||||
@ddt.data(((None, False, False), None),
|
||||
(('', False, False), None),
|
||||
(('dGVzdCANCg==', True, False), b'test \r\n'),
|
||||
@ -111,7 +86,7 @@ class VMwareGuestInfoServiceTest(unittest.TestCase):
|
||||
self._test_load_no_rpc_tool(expected_output, 'fake_path')
|
||||
|
||||
@mock.patch('os.path.exists')
|
||||
@mock.patch(MODULE_PATH + "._parse_data")
|
||||
@mock.patch('cloudbaseinit.utils.serialization.parse_json_yaml')
|
||||
@mock.patch(MODULE_PATH + "._get_guest_data")
|
||||
def _test_load_meta_data(self, mock_get_guestinfo, mock_parse,
|
||||
mock_os_path_exists, parse_return=None,
|
||||
|
53
cloudbaseinit/tests/utils/test_serialization.py
Normal file
53
cloudbaseinit/tests/utils/test_serialization.py
Normal file
@ -0,0 +1,53 @@
|
||||
# Copyright 2014 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import unittest
|
||||
|
||||
import ddt
|
||||
import yaml
|
||||
|
||||
try:
|
||||
import unittest.mock as mock
|
||||
except ImportError:
|
||||
import mock
|
||||
|
||||
from cloudbaseinit.utils import serialization
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class SerializationUtilsTests(unittest.TestCase):
|
||||
|
||||
@ddt.data((b'', (None, False)),
|
||||
(b'{}', ({}, False)),
|
||||
(b'---', (None, True)),
|
||||
(b'test: test', ({"test": "test"}, True)))
|
||||
@ddt.unpack
|
||||
@mock.patch("json.loads")
|
||||
@mock.patch("yaml.load")
|
||||
def test_parse_data(self, stream, expected_parsed_output,
|
||||
mock_yaml_load, mock_json_loads):
|
||||
if not expected_parsed_output[1]:
|
||||
mock_json_loads.return_value = expected_parsed_output[0]
|
||||
else:
|
||||
mock_json_loads.side_effect = TypeError("Failed to parse json")
|
||||
mock_yaml_load.return_value = expected_parsed_output[0]
|
||||
|
||||
parsed_output = serialization.parse_json_yaml(stream)
|
||||
|
||||
mock_json_loads.assert_called_once_with(stream)
|
||||
if expected_parsed_output[1]:
|
||||
loader = getattr(yaml, 'CLoader', yaml.Loader)
|
||||
mock_yaml_load.assert_called_once_with(stream, Loader=loader)
|
||||
|
||||
self.assertEqual(parsed_output, expected_parsed_output[0])
|
34
cloudbaseinit/utils/serialization.py
Normal file
34
cloudbaseinit/utils/serialization.py
Normal file
@ -0,0 +1,34 @@
|
||||
# Copyright 2020 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import yaml
|
||||
|
||||
|
||||
class YamlParserConfigError(Exception):
|
||||
"""Exception for Yaml parsing failures"""
|
||||
pass
|
||||
|
||||
|
||||
def parse_json_yaml(raw_data):
|
||||
"""Parse data as json. Fallback to yaml if json parsing fails"""
|
||||
|
||||
try:
|
||||
return json.loads(raw_data)
|
||||
except (TypeError, ValueError, AttributeError):
|
||||
loader = getattr(yaml, 'CLoader', yaml.Loader)
|
||||
try:
|
||||
return yaml.load(raw_data, Loader=loader)
|
||||
except (TypeError, ValueError, AttributeError):
|
||||
raise YamlParserConfigError("Invalid yaml data provided.")
|
Loading…
Reference in New Issue
Block a user