Added support to '!include' mechanism

The '!include' idiom is used to include an external YAML file into
current one. Currently, it supports protocol like 'file', 'http' and
'https'(not tested).
This commit is contained in:
tengqm 2014-12-27 20:08:52 +08:00
parent d5fc91b091
commit db29298dad

View File

@ -11,7 +11,10 @@
# under the License. # under the License.
import json import json
import os
import requests
import six import six
from six.moves import urllib
import yaml import yaml
from senlin.common import i18n from senlin.common import i18n
@ -22,27 +25,56 @@ LOG = logging.getLogger(__name__)
# Try LibYAML if available # Try LibYAML if available
if hasattr(yaml, 'CSafeLoader'): if hasattr(yaml, 'CSafeLoader'):
YamlLoader = yaml.CSafeLoader Loader = yaml.CSafeLoader
else: else:
YamlLoader = yaml.SafeLoader Loader = yaml.SafeLoader
if hasattr(yaml, 'CSafeDumper'): if hasattr(yaml, 'CSafeDumper'):
YamlDumper = yaml.CSafeDumper Dumper = yaml.CSafeDumper
else: else:
YamlDumper = yaml.SafeDumper Dumper = yaml.SafeDumper
def _construct_yaml_str(self, node): class YamlLoader(Loader):
# Override the default string handling function def __init__(self, stream):
# to always return unicode objects self._curdir = os.path.split(stream.name)[0]
return self.construct_scalar(node) super(YamlLoader, self).__init__(stream)
YamlLoader.add_constructor(u'tag:yaml.org,2002:str', _construct_yaml_str) def include(self, node):
url = self.construct_scalar(node)
components = urllib.parse.urlparse(url)
# Unquoted dates in YAML files get loaded as objects of type datetime.date if components.scheme == '':
# which may cause problems in API layer. Therefore, make unicode string try:
# out of timestamps until openstack.common.jsonutils can handle dates. url = os.path.join(self._curdir, url)
YamlLoader.add_constructor(u'tag:yaml.org,2002:timestamp', _construct_yaml_str) with open(url, 'r') as f:
return yaml.load(f, Loader)
except Exception as ex:
raise Exception('Failed loading file %s: %s' % (url,
six.text_type(ex)))
try:
resp = requests.get(url, stream=True)
resp.raise_for_status()
reader = resp.iter_content(chunk_size=1024)
result = ''
for chunk in reader:
result += chunk
return yaml.load(result, Loader)
except Exception as ex:
raise Exception('Failed retrieving file %s: %s' % (url,
six.text_type(ex)))
def process_unicode(self, node):
# Override the default string handling function to always return
# unicode objects
return self.construct_scalar(node)
YamlLoader.add_constructor('!include', YamlLoader.include)
YamlLoader.add_constructor(u'tag:yaml.org,2002:str',
YamlLoader.process_unicode)
YamlLoader.add_constructor(u'tag:yaml.org,2002:timestamp',
YamlLoader.process_unicode)
def simple_parse(in_str): def simple_parse(in_str):