Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse an AWS CloudFormation template with the PyYAML library

I am writing a custom Python application using the PyYAML library that needs to read in AWS CloudFormation YAML templates.

I know the templates are valid CloudFormation templates, because I tested them using validate-template:

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

When I try to read them using the PyYAML library, however, I get errors like:

yaml.scanner.ScannerError: mapping values are not allowed here

and

could not determine a constructor for the tag "!Sub"

and others.

By way of example, I try this AWS example template:

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

And then:

▶ 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'))

Which leads to:

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

How can I parse a CloudFormation YAML file using a library like PyYAML or others?

like image 770
nixmind Avatar asked Jun 18 '18 17:06

nixmind


People also ask

What is AWS CloudFormation and how can I use it?

You can create templates for the service or application architectures you want and have AWS CloudFormation use those templates for quick and reliable provisioning of the services or applications (called “stacks”). You can also easily update or replicate the stacks as needed.

How do I provision resources in AWS CloudFormation?

To provision and configure your stack resources, you must understand AWS CloudFormation templates, which are formatted text files in JSON or YAML. These templates describe the resources that you want to provision in your AWS CloudFormation stacks. You can use AWS CloudFormation Designer or any text editor to create and save templates.

How do I create and save CloudFormation templates?

You can use AWS CloudFormation Designer or any text editor to create and save templates. For information about the structure and syntax of a template, see Template anatomy . If you're unfamiliar with JSON or YAML, you can use AWS CloudFormation Designer to help you get started with AWS CloudFormation templates.

What is CloudFormation?

what is CloudFormation? What is CloudFormation? AWS CloudFormation is an Amazon infrastructure-as-a-code service to easily group and automate the deployment of resources in the AWS Cloud.


2 Answers

It is possible to use the cfn_tools library that ships with the aws-cfn-template-flip project.

Install the library:

▶ pip install cfn_flip

Then the simplest Python to read in the template might be:

#!/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))

This library is not really documented but there are also various methods in there for customising the formatting of the output worth exploring.

like image 60
Alex Harvey Avatar answered Sep 22 '22 07:09

Alex Harvey


I had some trouble with Alex's answer, because it was automatically converting my CF template into long form. So any !Ref Thing call was being converted into a dictionary mapping.

If you want to match the original input of your input.template file, use this:

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)

You can also change clean_up=False to True to perform some smart formatting, which worked well in my case.

I found this after running the cfn cli tool and seeing the correct short form output on my template. Then I used that main file as a reference and followed the code path.

like image 25
CornSmith Avatar answered Sep 22 '22 07:09

CornSmith