使用PyYAML库解析AWS CloudFormation模板

时间:2018-06-18 17:08:12

标签: amazon-web-services yaml amazon-cloudformation pyyaml

我正在使用需要在AWS CloudFormation YAML模板中读取的PyYAML库编写自定义Python应用程序。

我知道模板是有效的CloudFormation模板,因为我使用validate-template测试它们:

▶ aws cloudformation validate-template --template-body file://cloudformation.yml

但是当我尝试使用PyYAML库读取它们时,我收到的错误如下:

  

yaml.scanner.ScannerError:此处不允许使用映射值

  

无法确定标记“!Sub”的构造函数

和其他人。

举例来说,我尝试了这个AWS示例模板:

▶ curl -s \
    https://raw.githubusercontent.com/awslabs/aws-cloudformation-templates/master/aws/services/CloudFormation/FindInMap_Inside_Sub.yaml \
    -o FindInMap_Inside_Sub.yaml

然后:

▶ python
Python 2.7.15 (default, Nov 27 2018, 21:40:55) 
[GCC 4.2.1 Compatible Apple LLVM 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import yaml
>>> yaml.load(open('FindInMap_Inside_Sub.yaml'))

导致:

yaml.constructor.ConstructorError: could not determine a constructor for the tag '!FindInMap'
  in "FindInMap_Inside_Sub.yaml", line 89, column 45

如何使用PyYAML或其他库来解析CloudFormation YAML文件?

3 个答案:

答案 0 :(得分:4)

他们的aws-cfn-template-flip项目可以将cfn模板与json和yaml相互转换。 示例签出yaml_loader.py脚本。 它显示了如何添加yaml构造函数。 在底部,您将看到:

CfnYamlLoader.add_constructor(TAG_MAP, construct_mapping)
CfnYamlLoader.add_multi_constructor("!", multi_constructor)

您可能会对其中的construct_mapping方法感兴趣。从那里,您可以查看代码的工作原理。

答案 1 :(得分:0)

可以使用cfn_tools项目随附的aws-cfn-template-flip库。

安装库:

▶ pip install cfn_flip

那么在模板中读取的最简单的Python可能是:

#!/usr/bin/env python

import yaml
from cfn_tools import load_yaml, dump_yaml

text = open('./FindInMap_Inside_Sub.yaml').read()
data = load_yaml(text)

print dump_yaml(data)

该库并未真正记录下来,但是其中有多种方法可以自定义值得探索的输出格式。

答案 2 :(得分:0)

我在Alex's answer上遇到了一些麻烦,因为它会自动将CF模板转换为长格式。因此,任何!Ref Thing调用都将转换为字典映射。

如果要匹配input.template文件的原始输入,请使用以下命令:

from cfn_tools import load_yaml
import cfn_flip.yaml_dumper
import yaml


with open('input.template') as f:
    raw = f.read()
    data_dict = load_yaml(raw)

with open('output.template', 'w') as f:
    dumper = cfn_flip.yaml_dumper.get_dumper(clean_up=False, long_form=False)
    raw = yaml.dump(
        data_dict,
        Dumper=dumper,
        default_flow_style=False,
        allow_unicode=True
    )
    f.write(raw)

您也可以将clean_up=False更改为True以执行一些智能格式化,这在我的情况下效果很好。

在运行cfn cli工具并在模板上看到正确的简短格式输出后,我发现了这一点。然后,我使用that main file作为参考,并遵循了代码路径。