I decided to go the custom script route since I couldn't get the MetaData resource to install and configure packages with apt (see: https://s3.amazonaws.com/cloudformation-examples/BoostrappingApplicationsWithAWSCloudFormation.pdf).
The custom bash script does the install work to bootstrap the puppet master instance. I needed it to be in JSON format so I used this handy Ruby script from http://allanfeid.com/content/using-amazons-cloudformation-cloud-init-chef-and-fog-automate-infrastructure:
#!/usr/bin/ruby
require 'rubygems'
require 'json'
if ARGV.size != 1
puts "Usage: #{$0} <file>"
exit 1
end
def escape(string)
parse = JSON.parse({ 'json' => string }.to_json)
parse['json']
end
data = ''
File.open(ARGV[0]) {|f| data << f.read}
p escape(data)
# ./json_encode.rb combined-userdata.txt
This should work for now, but it would be nice to eventually manage the bootstrap procces as intended with cfn-init MetaData and apt. For example, this still doesn't work for me with apt:
"Resources": {
"MyInstance": {
"Type": "AWS::EC2::Instance",
"Metadata" : {
"AWS::CloudFormation::Init" : {
"config" : {
"sources" : {
:
},
"packages" : {
:
}
"files" : {
:
}
"services" : {
:
}
}
}
},
"Properties": {
:
}
}
}
UPDATE
An easier solution is to also use Ubuntu CloudInit (https://help.ubuntu.com/community/CloudInit) and have it install the packages for you. My template for EC2 Puppet Client instances looks like this now:
"webserver" : {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"KeyName" : { "Ref" : "KeyName" },
"ImageId" : { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "AMI" ]},
"InstanceType": { "Ref" : "InstanceType" },
"SecurityGroups" : [ { "Ref" : "PuppetGroup" }, { "Ref" : "WebServerGroup" } ],
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#cloud-config","\n",
"packages:","\n",
"- ruby","\n",
"- ruby-dev","\n",
"- rubygems","\n",
"- puppet","\n",
"- vim-puppet","\n",
"- puppet-el","\n",
"puppet:","\n",
"conf:","\n",
"agent:","\n",
"server: ",,"\n",
"runcmd:","\n"
]]}}
}
}
That's basically the CloudConfig boot strap process minus the runcmd magic that makes it work. I'm still trying to figure out how to get my puppet manifests down to the puppet master and assigned to nodes but that should help anyone who's using an Ubuntu UEC AMI.
Best Answer
Generally speaking, no. CloudFormation's resources are always created.
The reason for this is to ensure that a CloudFormation stack's resouces are isolated and can be fully controlled by one-and-only-one stack.
If you want to use an existing subnet, you have a few options:
If you really need to use a create-if-not-exists resource, you may be able to do it using custom resources. However, you'll have to worry about what to do on stack cleanup and rollbacks.