Search code examples
pythonamazon-web-servicesaws-cloudformation

Fixing yaml indentation with python


I'm manipulating existing yaml file (CloudFormation template) and copying needed resources into a new file.

The thing is, I'm getting part of the resource in a new line - not according to the correct indentation.
It seems the 3rd line is not adhering to the indentation configuration.

I've checked Python modules: yaml-indent, ruamel.yaml config, yamlfix, pyymal and off course our AI friends.. but the issue persists.

How can I write it in a correct manner ?

Code snippet:

    with open(entrypath, 'r') as magic:
        yaml_object = yaml.load(magic, Loader=yaml.SafeLoader)
        # print(yaml_object['Resources'][rscItem])

        with open('{}_Restore.yaml'.format(resourcename), 'a+') as s:
            s.write('  {}:'.format(rscItem))
            s.write('\n')
            s.write('    {}'.format(yaml.safe_dump(yaml_object['Resources'][rscItem], default_flow_style=False, indent=4)))

(I am aware of the spaces in s.write(' {}', that part is working as it should (-:)

Yaml file: How it looks like:

Resources:
  defaulteventbus:
    DeletionPolicy: Retain
Properties:
  Name: default
  Tags: []
Type: AWS::Events::EventBus
UpdateReplacePolicy: Retain

  LambdaEventSourceMapping:
    DeletionPolicy: Retain
Properties:
  BatchSize: 1
  BisectBatchOnFunctionError: true
  DestinationConfig:
    OnFailure:
      Destination:
        Ref: SNSTopicName
  Enabled: true

How it should looks like:

Resources:
  defaulteventbus:
    DeletionPolicy: Retain
    Properties:
      Name: default
      Tags: []
    Type: AWS::Events::EventBus
    UpdateReplacePolicy: Retain

  LambdaEventSourceMapping:
    DeletionPolicy: Retain
    Properties:
      BatchSize: 1
      BisectBatchOnFunctionError: true
      DestinationConfig:
        OnFailure:
          Destination:
            Ref: SNSTopicName
      Enabled: true

Updated code that @Michael wrote:

    with open(entrypath, 'r') as magic:
            yaml_object = yaml.load(magic, Loader=yaml.SafeLoader)
            # print(yaml_object['Resources'][rscItem])

    with open('{}_Restore.yaml'.format(resourcename), 'a+') as s:
            data = {rscItem: yaml_object['Resources'][rscItem]}
            text = yaml.safe_dump(data, default_flow_style=False, indent=2)
            s.write(textwrap.indent(text, ' ' * 2))


Solution

  • The question is not totally clear, but maybe this will help:

    import textwrap
    import yaml
    
    with open('source.yaml', 'r') as magic:
        source = yaml.load(magic, Loader=yaml.SafeLoader)
        for rscItem in source['Resources'].keys():
            with open('{}_Restore.yaml'.format(rscItem), 'a+') as s:
                data = {rscItem: source['Resources'][rscItem]}
                text = yaml.safe_dump(data, default_flow_style=False, indent=4)
                s.write(textwrap.indent(text, ' ' * 4)
    

    Assuming you have input file source.yaml

    Resources:
      defaulteventbus:
        DeletionPolicy: Retain
        Properties:
          Name: default
          Tags: []
        Type: AWS::Events::EventBus
        UpdateReplacePolicy: Retain
    
      LambdaEventSourceMapping:
        DeletionPolicy: Retain
        Properties:
          BatchSize: 1
          BisectBatchOnFunctionError: true
          DestinationConfig:
            OnFailure:
              Destination:
                Ref: SNSTopicName
          Enabled: true
    

    the script above outputs files

        defaulteventbus:
            DeletionPolicy: Retain
            Properties:
                Name: default
                Tags: []
            Type: AWS::Events::EventBus
            UpdateReplacePolicy: Retain
    

    and

        LambdaEventSourceMapping:
            DeletionPolicy: Retain
            Properties:
                BatchSize: 1
                BisectBatchOnFunctionError: true
                DestinationConfig:
                    OnFailure:
                        Destination:
                            Ref: SNSTopicName
                Enabled: true