使用Python加载CloudFormation YAML

4
我有一组AWS Cloud Formation Templates的YAML版本,这些模板最近被我从JSON版本转换而来。在使用JSON时,我可以加载这些模板并使用jinja进行转换,以生成一些markdown文档。现在我想在Python中实现相同的功能,但使用了缩写函数语法的cloudformation模板,其中使用了YAML标签。例如:
Properties:
  MinSize: !Ref ClusterSize
  MaxSize: !Ref ClusterSize

尝试使用ruamel.yaml包加载这些内容时,构造器会失败,因为它无法处理标签,因为它没有关于它们的知识。是否有方法可以解决这个问题,以便我能够加载YAML文档,以便检索/查询输出和资源?

“Outputs”和“Resources”是什么? - Anthon
1个回答

3

你误解了ruamel.yaml无法处理标签。但是,当然你必须提供如何处理任何未知标签的信息,它不能猜测你想要使用!Ref加载什么类型的数据:

import ruamel.yaml

yaml_str = """\
Properties:
  MinSize: !Ref ClusterSize
  MaxSize: !Ref ClusterSize
"""


class Blob(object):
    def update(self, value):
        self.value = value

    def __str__(self):
        return str(self.value)


def my_constructor(self, node):
    data = Blob()
    yield data
    value = self.construct_scalar(node)
    data.update(value)

ruamel.yaml.SafeLoader.add_constructor(u'!Ref', my_constructor)

data = ruamel.yaml.safe_load(yaml_str)
print('data', data['Properties']['MinSize'])

打印:

ClusterSize

如果您想摆脱许多不同的标签,并且不关心“一切都是字符串”,您也可以这样做:
import ruamel.yaml

yaml_str = """\
Properties:
  MinSize: !Ref ClusterSize
  MaxSize: !Ref ClusterSize
  SizeList:
     - !abc 1
     - !xyz 3
"""


def general_constructor(loader, tag_suffix, node):
    return node.value


ruamel.yaml.SafeLoader.add_multi_constructor(u'!', general_constructor)


data = ruamel.yaml.safe_load(yaml_str)
print(data)

这将会得到:

{'Properties': {'SizeList': ['1', '3'], 'MinSize': 'ClusterSize', 'MaxSize': 'ClusterSize'}}

请注意,标量13被加载为字符串而不是正常的整数。

2
谢谢Anthon,我并不是想暗示ruamel.yaml不能处理标签 - 我只是不知道这些标签的行为和实现方式,因为我不知道如何指定它们,所以我无法加载YAML。除了!Ref之外还有更多的标签,有些接受列表,其他则接受其他类型 - 是否有一种方法可以忽略标签,或将它们视为字符串,或者在更基本的层面上这样做行不通? - georgealton
如果一切都可以是字符串,那就相对简单了。有点不幸的是,你把示例 YAML 缩减到只有一个这样的标记和仅嵌套字典的程度,我会更新答案。 - Anthon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接