web-dev-qa-db-ja.com

YAMLエラー:タグのコンストラクターを判別できませんでした

これは questions/44786412 と非常に似ていますが、私のものはYAML safe_load()によってトリガーされているようです。 Ruamelの libraryYamlReader を使用して、CloudFormationの一連の部分を1つのマージされたテンプレートに接着しています。 bang-notationは適切なYAMLではありませんか?

Outputs:
  Vpc:
    Value: !Ref vpc
    Export:
      Name: !Sub "${AWS::StackName}-Vpc"

これらは問題ありません

Outputs:
  Vpc:
    Value:
      Ref: vpc
    Export:
      Name:
        Fn::Sub: "${AWS::StackName}-Vpc"

Resources:
  vpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock:
        Fn::FindInMap: [ CidrBlock, !Ref "AWS::Region", Vpc ]

パート2; load()を取得して、「Fn :: Select:」の右側をそのままにする方法。

  FromPort: 
    Fn::Select: [ 0, Fn::FindInMap: [ Service, https, Ports ] ]

これに変換されますが、CFは気に入らないようになりました。

  FromPort:
    Fn::Select: [0, {Fn::FindInMap: [Service, https, Ports]}]

ステートメントを完全に展開すれば、問題はありません。速記は問題があると思います。

  FromPort:
    Fn::Select:
    - 0
    - Fn::FindInMap: [Service, ssh, Ports]
7
Matthew Patton

「バング表記」は適切なYAMLであり、通常、これはタグと呼ばれます。 safe_load()をそれらと一緒に使用する場合は、!Refタグと!Subタグのコンストラクターを提供する必要があります。使用:

ruamel.yaml.add_constructor(u'!Ref', your_ref_constructor, constructor=ruamel.yaml.SafeConstructor)

ここで、両方のタグについて、スカラーを処理することを期待する必要があります。より一般的なマッピングではありません。

RoundTripLoaderの代わりにSafeLoaderを使用することをお勧めします。これにより、順序やコメントなども保持されます。 RoundTripLoaderSafeLoaderのサブクラスです。

ラウンドトリップスカラーをサポートするruamel.yaml> = 0.15.33を使用している場合は、次のことができます(新しいruamel.yaml APIを使用)。

import sys
from ruamel.yaml import YAML

yaml = YAML()
yaml.preserve_quotes = True

data = yaml.load("""\
Outputs:
  Vpc:
    Value: !Ref: vpc    # first tag
    Export:
      Name: !Sub "${AWS::StackName}-Vpc"  # second tag
""")

yaml.dump(data, sys.stdout)

取得するため:

Outputs:
  Vpc:
    Value: !Ref: vpc    # first tag
    Export:
      Name: !Sub "${AWS::StackName}-Vpc"  # second tag

古い0.15.Xバージョンでは、スカラーオブジェクトのクラスを自分で指定する必要があります。多くのオブジェクトがある場合、これは面倒ですが、追加の機能を使用できます。

import sys
from ruamel.yaml import YAML


class Ref:
    yaml_tag = u'!Ref:'

    def __init__(self, value, style=None):
        self.value = value
        self.style = style

    @classmethod
    def to_yaml(cls, representer, node):
        return representer.represent_scalar(cls.yaml_tag,
                                            u'{.value}'.format(node), node.style)

    @classmethod
    def from_yaml(cls, constructor, node):
        return cls(node.value, node.style)

    def __iadd__(self, v):
        self.value += str(v)
        return self

class Sub:
    yaml_tag = u'!Sub'
    def __init__(self, value, style=None):
        self.value = value
        self.style = style

    @classmethod
    def to_yaml(cls, representer, node):
        return representer.represent_scalar(cls.yaml_tag,
                                            u'{.value}'.format(node), node.style)

    @classmethod
    def from_yaml(cls, constructor, node):
        return cls(node.value, node.style)


yaml = YAML(typ='rt')
yaml.register_class(Ref)
yaml.register_class(Sub)

data = yaml.load("""\
Outputs:
  Vpc:
    Value: !Ref: vpc    # first tag
    Export:
      Name: !Sub "${AWS::StackName}-Vpc"  # second tag
""")

data['Outputs']['Vpc']['Value'] += '123'

yaml.dump(data, sys.stdout)

これは:

Outputs:
  Vpc:
    Value: !Ref: vpc123 # first tag
    Export:
      Name: !Sub "${AWS::StackName}-Vpc"  # second tag
5
Anthon