【问题标题】:How to parse Cloudformation YAML to get all the !ImportValue from YAML template?如何解析 Cloudformation YAML 以从 YAML 模板中获取所有 !ImportValue?
【发布时间】:2019-08-23 16:14:46
【问题描述】:

我正在开发一个项目来解析 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 文件)来描述云形成文件之间的相互依赖关系。

【问题讨论】:

  • this 是否为您提供了比自己用 Python 编写所有这些内容更好的选择?
  • 这有一点帮助,但只是我在第一个代码 sn-p 中所说的阅读部分。这里的主要问题是提取那些分散在 YAML 文件中的 !ImportValue。

标签: python yaml amazon-cloudformation pyyaml ruamel.yaml


【解决方案1】:

如果您使用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

【讨论】:

  • 我看到你更新了你的问题,不再需要密钥,你可以删除那部分代码,或者在最后的 for 循环中忽略它。
猜你喜欢
  • 2020-08-06
  • 2021-12-04
  • 2022-12-17
  • 2017-08-20
  • 1970-01-01
  • 2020-12-16
  • 2019-02-13
  • 1970-01-01
  • 2021-10-17
相关资源
最近更新 更多