EzDevInfo.com

troposphere

troposphere - Python library to create AWS CloudFormation descriptions

In python the Jinja2 template returns a backslash in front of a double quote, I need to remove that

One of the lines in my jinja2 template needs to return

   STACKNAME=\"",{"Ref":"AWS::StackName"},"\"

Putting the above into the template returns

   STACKNAME=\\\"\",{\"Ref\":\"AWS::StackName\"},\"\\\"

I tried creating a variable

 DQ = '"'

and setting the template as

STACKNAME="{{DQ}},{{{DQ}}Ref{{DQ}}:{{DQ}}AWS::StackName{{DQ}}},{{DQ}}"

but the result still puts a backslash in front of the {{DQ}} variable

I also tried putting in a unique string %%%DQ%%% and then getting the results and then doing a string replace but it still gives me the backslash.

How do I get the results I want?

UPDATE: My apologies. It turns out that it is not the jinja2 template that is returning the escaped quotes. I am making a later call in the script to:

lc.UserData=Base64(Join("", [commandList]))

And it is this call to the Troposphere Module for Base64 and/or Join that is causing the problem and inserting the escapes.

Testing Further shows specifically that it is Base64 that does the escaping.


Source: (StackOverflow)

Troposphere Add S3 LifecycleRule to the class LifecycleConfiguration

Method Signature: I have tried to change the implementation some different ways, but its not helping.

import troposphere.s3 as S3
class LifecycleConfiguration(AWSProperty):
props = {
    'Rules': ([LifecycleRule], True),
}

class LifecycleRule(AWSProperty):
props = {
    'ExpirationDate': (basestring, False),
    'ExpirationInDays': (positive_integer, False),
    'Id': (basestring, False),
    'Prefix': (basestring, False),
    'Status': (basestring, True),
    'Transition': (LifecycleRuleTransition, False),
}

Test Implimentation

myLifecycleConfiguration = S3.LifecycleConfiguration(title='myLifecycleConfiguration',
                                                 Rules=S3.LifecycleRule(title="check"))

Error Signature

TypeError: Rules is <class 'troposphere.s3.LifecycleRule'>, expected [<class 'troposphere.s3.LifecycleRule'>]

Source: (StackOverflow)

Advertisements

Trying to pass parameters from Master to child template

I'm trying to pass list parameters from master to child template, however I'm running into two errors.. These are my current parameters on the master template.

"Parameters": {
    "ELBSubnets": {
        "Default": "subnet-5d8fea67,subnet-3e35cf15",
        "Type": "CommaDelimitedList"
    },
    "LCKeyPair": {
        "Default": "key-master",
        "Type": "String"
    },
    "LCSecurityGroups": {
        "Default": "sg-10a15c74,sg-880e5fec",
        "Type": "CommaDelimitedList"
    }
},

They are being referenced in this method on the same template when passing on to the child template.

    "ChildTempate1": {
        "Properties": {
            "Parameters": {
                "ELBSubnets": {
                    "Ref": "ELBSubnets"
                },
                "KeyPair": {
                    "Ref": "LCKeyPair"
                },
                "LCSecurityGroups": {
                    "Ref": "LCSecurityGroups"
                }
            },

On the child template, they are declared exactly the same.

"Parameters": {
    "ELBSubnets": {
        "Type": "CommaDelimitedList"
    },
    "LCKeyPair": {
        "Type": "String"
    },
    "LCSecurityGroups": {
        "Type": "CommaDelimitedList"
    }
},

And they're being referenced in this method in the child template.

            "KeyName": {
                "Ref": "LCKeyPair"
            },
            "SecurityGroups": {
                "Fn::Join": [
                    ",",
                    [
                        {
                            "Ref": "LCSecurityGroups"
                        }
                    ]
                ]
            }
        },

This is another part of the template.

            "Subnets": {
                "Fn::Join": [
                    ",",
                    [
                        {
                            "Ref": "ELBSubnets"
                        }
                    ]
                ]
            }
        },

When I attempt to use the fn::join on the master template, it says

"Template validation error: Template error: every Fn::Join object requires two parameters, (1) a string delimiter and (2) a list of strings to be joined or a function that returns a list of strings (such as Fn::GetAZs) to be joined."

When I don't use fn::join on the master template the error is

Value of property Parameters must be an object with String (or simple type) properties

Regardless of whether I have fn::join on the same parameters in the child template.

Both templates can be found here: https://github.com/slimg00dy/Troposphere-CloudformationTests


Source: (StackOverflow)

How do I add a scaling policy into cloudformation with troposphere?

I've create a python troposphere script that's been working quite well overall. I just added in a new piece of code to add a policy to the autoscaling group for an alarm.

The code looks like:

tintScaleDown = autoscaling.ScalingPolicy("tintScaleDown1")
tintScaleDown.AdjustmentType = "ChangeInCapacity"
tintScaleDown.AutoScalingGroupName(Ref("tintASG"))
tintScaleDown.Cooldown = "900"
tintScaleDown.ScalingAdjustment = "1"
t.add_resource(tintScaleDown)

The error is:

Traceback (most recent call last): File "inPowered.py", line 395, in tintScaleDown.AutoScalingGroupName(Ref("tintASG")) File "/usr/lib/python2.7/site-packages/troposphere/init.py", line 79, in getattr raise AttributeError(name)

The Reference should have been established in this line:

asg = autoscaling.AutoScalingGroup("tintASG")

The section of the CloudFormation script should look like:

            "tintScaleDown1": {
                    "Type": "AWS::AutoScaling::ScalingPolicy",
                    "Properties": {
            "AdjustmentType": "ChangeInCapacity",
                            "AutoScalingGroupName": {
                                    "Ref": "tintASG"
                            },
                            "Cooldown": "900",
                            "ScalingAdjustment": "-1"
                    }
    },

Suggestions?


Source: (StackOverflow)

In python module troposphere I am getting an error "AttributeError: 'module' object has no attribute 'EBSBlockDeviceMapping'"

I'm following the example of some other code that has been written. The code in question looks like this:

   if virtualname == "ebs":
        if deviceSize == None:
            deviceSize = 8

            if delOnTerminate == None or delOnTerminate == "true":
                DOT = "true"
            else:
                DOT = "false"

        lc.BlockDeviceMappings.append(ec2.EBSBlockDeviceMapping(
                                            DeviceName=blockname,
                                            Ebs=ec2.EBSBlockDevice(VolumeSize=deviceSize,
                                                                   DeleteOnTermination=DOT)))
    else:
        lc.BlockDeviceMappings.append(ec2.BlockDeviceMapping(DeviceName=blockname,
                                                             VirtualName=virtualname))

Source: (StackOverflow)

AWS CloudFormation add condition in s3bucket using troposphere

Following code is working for EC2 and it is adding the condition statement in the output, but for S3 its not producing the condition statement. I can manually add this statement to make it work, but that has many disadvantages.

from __future__ import print_function
from troposphere import (Template, Parameter, Ref, Condition, Equals)
from troposphere import ec2
from troposphere import s3

parameters = {
    "One": Parameter(
        "One",
         Type="String",
    ),
}

conditions = {
    "OneEqualsFoo": Equals(
        Ref("One"),
        "Foo"
  ),
}

resources = {
    "MyS3bucket": s3.Bucket(
         "MybucketName",
         Condition="OneEqualsFoo",
   ),

   "Ec2Instance": ec2.Instance(
       "Ec2Instance",
       Condition="OneEqualsFoo",
       ImageId="ami-1234556",
       InstanceType="t1.micro",
       KeyName="mykeypair",
       SecurityGroups=["default"],
   )
}

def template():
     t = Template()
 for p in parameters.values():
    t.add_parameter(p)
 for k in conditions:
    t.add_condition(k, conditions[k])
 for r in resources.values():
    t.add_resource(r)
return t
print(template().to_json())

OUT-PUT-RESULT this result is missing condition statement in S3 template section

{
"Conditions": {
    "OneEqualsFoo": {
        "Fn::Equals": [
            {
                "Ref": "One"
            },
            "Foo"
        ]
    }
},
"Parameters": {
    "One": {
        "Type": "String"
    }
},
"Resources": {
    "Ec2Instance": {
        "Condition": "OneEqualsFoo",
        "Properties": {
            "ImageId": "ami-1234556",
            "InstanceType": "t1.micro",
            "KeyName": "mykeypair",
            "SecurityGroups": [
                "default"
            ]
        },
        "Type": "AWS::EC2::Instance"
    },
    "MybucketName": {
        "Type": "AWS::S3::Bucket"
    }
}
}

Source: (StackOverflow)

Using troposphere for cloud formation, how do I add "propagate at launch" to tags

I'm using the python module troposphere to generate tags in my cloud formation template. The current script generates:

       "Tags": [{"Key":"Name", "Value":"MyTagName"}, 
                {"Key":"Version", "Value":"123456"}]

but I need to generate

       "Tags":[{"Key":"Name", "Value":"MyTagName", "PropagateAtLaunch":"true"},
               {"Key":"Version", "Value":"123456", "PropagateAtLaunch":"true"}]

The portion of the script that applies is:

    asg = autoscaling.AutoScalingGroup("MyASG")
    asg.Tags = Tags(Name = "MyTagName", Version = "123456")
    t.add_resource(asg)

Source: (StackOverflow)

How do I add an array of RecordSets into Cloud Formation using troposphere?

I'm using the python module troposphere to create my cloud formation template. Most of it is complete but I seem to be confused about how to create my DNS entries for the load balancer with the RecordSets method/function. The output for this section is supposed to look like:

"devdevopsdemoELBDNSARecord0": {
    "Type": "AWS::Route53::RecordSetGroup",
    "Properties": {
        "HostedZoneName": "FOO.net.",
        "Comment": "Alias targeted to devdevopsdemoELB ELB.",
        "RecordSets": [
            {
             "Name": "devopsdemo.dev.FOO.net.",
             "Type": "A",
             "AliasTarget": {
             "HostedZoneId": {
                 "Fn::GetAtt": [
                    "devdevopsdemoELB",
                    "CanonicalHostedZoneNameID"
                 ]
             },
             "DNSName": {
                 "Fn::GetAtt": [
                 "devdevopsdemoELB",
                 "CanonicalHostedZoneName"
                 ]
             }
         }
     },
     {
         "Name": "devopsdemo-dev.FOO.net.",
         "Type": "A",
         "AliasTarget": {
            "HostedZoneId": {
            "Fn::GetAtt": [
               "devdevopsdemoELB",
               "CanonicalHostedZoneNameID"
             ]
         },
         "DNSName": {
             "Fn::GetAtt": [
             "devdevopsdemoELB",
             "CanonicalHostedZoneName"
             ]
         }
     }
 }

I've started with:

hostedzone = "FOO.net"
myRecordSet = RecordSetType("devdevopsdemoELBDNSARecord0")
myRecordSet.HostedZoneName=Join("", hostedzone, "."])
myRecordSet.Comment="Alias targeted to devdevopsdemoELB ELB."

But then I'm not clear on how the RecordSets values should be entered.

I supposed I could just use the straight

myRecordSet.RecordSets = 

And just put the json into place, but that seems a bit like a misuse of the purpose of using troposphere in the first place.

Update: Putting in the json results in this error

AttributeError: AWS::Route53::RecordSet object does not support attribute RecordSets

myRecordSet.RecordSets = [
                         {
                          "Name": "devopsdemo.dev.FOO.net.",
                          "Type": "A",
                          "AliasTarget": {
                              "HostedZoneId": {
                                  "Fn::GetAtt": [
                                      "devdevopsdemoELB",
                                      "CanonicalHostedZoneNameID"
                                  ]
                              },
                              "DNSName": {
                                  "Fn::GetAtt": [
                                      "devdevopsdemoELB",
                                      "CanonicalHostedZoneName"
                                      ]
                                  }
                              }
                         },
                         {
                          "Name": "devopsdemo-dev.FOO.net.",
                          "Type": "A",
                          "AliasTarget": {
                                 "HostedZoneId": {
                                  "Fn::GetAtt": [
                                      "devdevopsdemoELB",
                                      "CanonicalHostedZoneNameID"
                                      ]
                                  },
                                 "DNSName": {
                                     "Fn::GetAtt": [
                                         "devdevopsdemoELB",
                                         "CanonicalHostedZoneName"
                                         ]
                                     }
                                 }
                          }
                         ]

Then I tried this:

myDNSRecord = t.add_resource(RecordSetGroup(
        "devdevopsdemoELBDNSARecord0",
        HostedZoneName=Join("", ["inpwrd.net", "."]),
        Comment="DNS Entry to point to the ELB for devopsdemo",
        RecordSets=[
            RecordSet(
                Name="devopsdemo.dev.inpwrd.net.",
                Type="A",
                AliasTarget=[HostedZoneId(GetAtt("devdevopsdemoELB", "CanonicalHostedZoneNameID")),
                             DNSName(GetAtt("devdevopsdemoELB", "CanonicalHostedZoneName"))],
                ),
            RecordSet(
                Name="devopsdemo-dev.inpwrd.net.",
                Type="A",
                AliasTarget=[HostedZoneId(GetAtt("devdevopsdemoELB", "CanonicalHostedZoneNameID")),
                             DNSName(GetAtt("devdevopsdemoELB", "CanonicalHostedZoneName"))],
                ),
            ],
    )
)

HostedZoneId isn't found


Source: (StackOverflow)

Troposphere, passing output of a stack as input to another

Suppose I'm defined two stacks, A and B.

In stack A, I define a VPC and a subnet and I output that subnet's id

t = Template()
Subnet = t.add_resource(Subnet .....)
SubnetId = t.add_output(Output('SubnetId', Value=Ref(Subnet))

In Stack B, I have these instances that I want to live within the subnet defined in Stack A. How can I achieve that?


Source: (StackOverflow)