我正在开发一个解析AWS Cloudformation Yaml文件的项目,以从YAML模板中提取所有!ImportValue。
我试图使用ruamel.yaml解析(我是新的),我能够读取YAML文件并获取各个元素。
import ruamel.yaml
def general_constructor(loader, tag_suffix, node):
return node.value
ruamel.yaml.SafeLoader.add_multi_constructor(u'!', general_constructor)
with open(cfFile, 'r') as service:
stream = service.read()
yaml_data = ruamel.yaml.safe_load(stream)
print yaml_data
上面的代码获取指定的YAML文件的内容,输出如下所示。
{'Application': {'Properties': {'ApplicationName': [ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'-'),
SequenceNode(tag=u'tag:yaml.org,2002:seq', value=[ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'***'), ScalarNode(tag=u'!ImportValue', value=u'jkl')])],
*
*
ScalarNode(tag=u'!ImportValue', value=u'def'),
*
*
ScalarNode(tag=u'!ImportValue', value=u'rst')])]},
因此ScalarNode中列出了一堆!ImportValue(例如ScalarNode(tag = u'!ImportValue',value = u'rst')),我实际上想要提取它。现在这些ImportValues分散在模板的各个地方。什么是提取那些价值的最佳方式?在我们的cloudformation中,我们有大量的YAML文件,其中一些导出某些资源和其他YAML文件导入它们。所以,我想构建一种依赖关系图(可能是一个JSON文件),它将描述云形成文件之间的相互依赖关系。
如果你使用ruamel.yaml
的往返加载程序,你不需要做任何特殊的加载标记,并且在结果数据结构上递归步行相对容易。需要传递相应的密钥,因为至少第一个!ImportValue
在密钥下面的序列内。
假设input.yaml
包括:
Application:
Properties:
ApplicationName: ["-", ["**", !ImportValue "jkl"]]
AnotherKey:
- 42
- nested: !ImportValue xyz
(这可能不是您输入的内容,但可以用于演示目的),并使用新的ruamel.yaml
API(默认为往返加载/转储):
import sys
from pathlib import Path
import ruamel.yaml
ta = ruamel.yaml.comments.Tag.attrib
yaml = ruamel.yaml.YAML()
data = yaml.load(Path('input.yaml'))
def process(d, key=None):
if isinstance(d, dict):
for k, v in d.items():
for res in process(v, k): # recurse and pass on new key
yield res
elif isinstance(d, list):
for item in d:
for res in process(item, key):
yield res
else:
try:
if getattr(d, ta, None).value == '!ImportValue':
yield (key, d)
except AttributeError:
pass
for k, v in process(data):
print(k, '->', v)
这使:
ApplicationName -> jkl
nested -> xyz