Red Bottle
Red Bottle

Reputation: 3080

Creating YAML using Python: Cloudformation Template

Hi I'm trying to create a Cloudformation template using Python. I'm using yaml library to do so.

Here's my code:

import yaml

dict_file =     {
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "ding dong",
    "Parameters": {
        "Environment":{
            "Description": "Environment for Deployment",
            "Type": "String"
        }
    },
    "Resources":{
        "Queue": {
            "Type": "AWS::SQS::Queue",
            "Properties":{
                "DelaySeconds": 0,
                "MaximumMessageSize": 262144,
                "MessageRetentionPeriod": 1209600,
                "QueueName": '!Sub "${Environment}-Queue"',
                "ReceiveMessageWaitTimeSeconds": 0,
                "VisibilityTimeout": 150
            }
        }
    }
}

with open(r'TopicName.yml', 'w') as file:
    documents = yaml.dump(dict_file, file, sort_keys=False)

The problem is with Cloudformation tags like !Sub as you can see in the key "QueueName". The !Sub needs to be outside of quote in the resulting yaml. The resulting yaml this gives looks like this QueueName: '!Sub "${LSQRegion}-TelephonyLogCall-Distributor"'

How do I fix this? Any idea? Pleas help!!

Upvotes: 0

Views: 1690

Answers (2)

CK__
CK__

Reputation: 1311

You could try troposphere library too. It supports all the AWS services (which are supported by AWS CloudFormation) and really more pythonic to create CloudFormation template in Python.

I have pasted troposphere code for your CloudFormation template. You can try it out too:

from troposphere import Template, Parameter, Sub
from troposphere.sqs import Queue


def get_cfn_template():
    template = Template()
    template.set_version("2010-09-09")
    template.set_description("ding dong")
    template.add_parameter(Parameter(
        "Environment",
        Type="String",
        Description="Environment for Deployment"
    ))
    template.add_resource(
        Queue(
            'Queue',
            DelaySeconds=0,
            MaximumMessageSize=262144,
            MessageRetentionPeriod=1209600,
            QueueName=Sub("${Environment}-Queue"),
            ReceiveMessageWaitTimeSeconds=0,
            VisibilityTimeout=150
        )
    )
    return template.to_json()


print get_cfn_template()

Output

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "ding dong",
    "Parameters": {
        "Environment": {
            "Description": "Environment for Deployment",
            "Type": "String"
        }
    },
    "Resources": {
        "Queue": {
            "Properties": {
                "DelaySeconds": 0,
                "MaximumMessageSize": 262144,
                "MessageRetentionPeriod": 1209600,
                "QueueName": {
                    "Fn::Sub": "${Environment}-Queue"
                },
                "ReceiveMessageWaitTimeSeconds": 0,
                "VisibilityTimeout": 150
            },
            "Type": "AWS::SQS::Queue"
        }
    }
}

Troposphere can convert your code to YAML too.

Upvotes: 1

larsks
larsks

Reputation: 311713

In YAML, an unquoted value beginning with ! represents a custom type. You're never going to be able to generate that with yaml.dump from a simple string value. You're going to need to create a custom class and an associated representer to get the output you want. For example:

import yaml


class Sub(object):
    def __init__(self, content):
        self.content = content

    @classmethod
    def representer(cls, dumper, data):
        return dumper.represent_scalar('!Sub', data.content)


dict_file = {
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "ding dong",
    "Parameters": {
        "Environment": {
            "Description": "Environment for Deployment",
            "Type": "String"
        }
    },
    "Resources": {
        "Queue": {
            "Type": "AWS::SQS::Queue",
            "Properties": {
                "DelaySeconds": 0,
                "MaximumMessageSize": 262144,
                "MessageRetentionPeriod": 1209600,
                "QueueName": Sub("${Environment}-Queue"),
                "ReceiveMessageWaitTimeSeconds": 0,
                "VisibilityTimeout": 150,
            },
        }
    },
}


yaml.add_representer(Sub, Sub.representer)
print(yaml.dump(dict_file))

This will output:

AWSTemplateFormatVersion: '2010-09-09'
Description: ding dong
Parameters:
  Environment:
    Description: Environment for Deployment
    Type: String
Resources:
  Queue:
    Properties:
      DelaySeconds: 0
      MaximumMessageSize: 262144
      MessageRetentionPeriod: 1209600
      QueueName: !Sub '${Environment}-Queue'
      ReceiveMessageWaitTimeSeconds: 0
      VisibilityTimeout: 150
    Type: AWS::SQS::Queue

Upvotes: 3

Related Questions