troposphere
troposphere - Python library to create AWS CloudFormation descriptions
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)
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)
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)
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)
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)
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)
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)
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)
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)