deb-murano/murano/engine/yaql_yaml_loader.py
Alexander Tivelkov 779fd3cd23 Fixed YAQL tag leakage to YAML loader
Implicit yaml tag resolver being registered for YaqlYamlLoader (which is
user to load MuranoPL classes as YAML documents with embedded YAQL
statements) was being registered in the default YAML Dumper which is
used for any YAML serialization.

This was leading to inability to load more then one HOT-based package
per API service lifetime: the first package which was uploaded was
causing the leakage of YAQL statements into the global tag resolver.
This global resolver was used for all subsequent load attempts, so plain
yaml documents with Heat templates were attempted to be loaded as
MuranoPL classes.

This patch fixes this behavior by registering the implicit resolver
without helper method (which actually registers the resolvers at default
Dumper).

Change-Id: Icd3b6d354bcb105c2c25f842ede077d539e9c246
Closes-Bug: #1450547
2015-04-30 20:27:40 +03:00

71 lines
2.1 KiB
Python

# Copyright (c) 2014 Mirantis Inc.
#
# 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 yaml
import yaml.composer
import yaml.constructor
from murano.dsl import yaql_expression
class MuranoPlDict(dict):
pass
class MuranoPlYamlConstructor(yaml.constructor.Constructor):
def construct_yaml_map(self, node):
data = MuranoPlDict()
data.source_file_position = build_position(node)
yield data
value = self.construct_mapping(node)
data.update(value)
class YaqlYamlLoader(yaml.Loader, MuranoPlYamlConstructor):
pass
YaqlYamlLoader.add_constructor(u'tag:yaml.org,2002:map',
MuranoPlYamlConstructor.construct_yaml_map)
# workaround for PyYAML bug: http://pyyaml.org/ticket/221
resolvers = {}
for k, v in yaml.Loader.yaml_implicit_resolvers.items():
resolvers[k] = v[:]
YaqlYamlLoader.yaml_implicit_resolvers = resolvers
def build_position(node):
return yaql_expression.YaqlExpressionFilePosition(
node.start_mark.name,
node.start_mark.line + 1,
node.start_mark.column + 1,
node.start_mark.index,
node.end_mark.line + 1,
node.end_mark.column + 1,
node.end_mark.index - node.start_mark.index)
def yaql_constructor(loader, node):
value = loader.construct_scalar(node)
result = yaql_expression.YaqlExpression(value)
result.source_file_position = build_position(node)
return result
YaqlYamlLoader.add_constructor(u'!yaql', yaql_constructor)
YaqlYamlLoader.add_implicit_resolver(u'!yaql', yaql_expression.YaqlExpression,
None)