cfndsl 0.1.16 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3639153a22d283db62bc8c36f03ae111675e6482
4
- data.tar.gz: 8295dfbcbdc172a276a6b192ed99b5cc1d7769b3
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MzU3YmUxZDJhYTg1YWNjNmE5MWE5OWY3NDBiNzM5NjNhMTMxYmM4Mw==
5
+ data.tar.gz: !binary |-
6
+ OGM0MGQ3ZjY4YzllMDFiMGM2N2ZjNWNhZDhkN2U2OTVjY2QwYjhjMQ==
5
7
  SHA512:
6
- metadata.gz: 89870880a076338d49b2b5d05770206cb7ef30b3f179098331f9424b883b4e61ae6c2e33bc240808b91c4a441429429d332ddb3533db460c67f4becbd20ea866
7
- data.tar.gz: ce0e651c1738128b3513ac6da3badcf184795a21410952434685d71f83a3bebd64eabc579377c82d46467dd4ca80cd5cc442af21a31012bb058ecf82141e17f2
8
+ metadata.gz: !binary |-
9
+ ZmUwNTYyZmY0NjM4YWJmYzdhZmY2ZmVjNThmOTZhZTc0OGZjZDRmZmZjMzE5
10
+ N2UyNzg2NmM0MTJjZGUzMDNmMTc4YTk0ZmYxMjViMWY5MGQ0ZTI4ZDIzZmU2
11
+ MGNiZWU5Y2QxNWJlZmEyMTY3ZjMzNGQxYzBlYWFmOWNjNDlmMjE=
12
+ data.tar.gz: !binary |-
13
+ ZTczZDA1NTAzNDUyNDIwNGYxY2M4YjcxMjI3OWE1Mzc5YzQwNTM2MGQ3MjNi
14
+ ZWZiMWM0Y2ZhMWRkMGI4NGU2MDE5NDUyNDU0YjljYTQyNWNhY2JlNjU5Y2Qy
15
+ MDM1OWRkMTBlMTUxZDFiNzQ2NjU1NDQxNDYxMWNmNWQ2YmM4MjE=
@@ -0,0 +1,3 @@
1
+ *.gem
2
+ *~
3
+ Gemfile.lock
@@ -0,0 +1,19 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
4
+ sudo: false
5
+
6
+ deploy:
7
+ provider: rubygems
8
+ api_key:
9
+ secure: AH+4R+m6U0kmALFYAYEQl2oF/dj1yOnu/M1ZOtWttk+Zjwnw6kFc0hFLbvxdy6uivq1XmMXVa9eXzDPsRjW4ow2g+UuDLxvkvfT45SMmJ5sYQpoiD7AIJnEvMu6TXnmfiRNgM5bHnV3oilNJ8KKCbCFCd+imGRLTkBuhLkhkejA=
10
+ gem: cfndsl
11
+ on:
12
+ tags: true
13
+ repo: stevenjack/cfndsl
14
+ notifications:
15
+ email:
16
+ recipients:
17
+ - stevenmajack@gmail.com
18
+ on_failure: change
19
+ on_success: never
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'rake'
7
+ gem 'rspec'
8
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Steven Jack
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,221 @@
1
+ cfndsl
2
+ ======
3
+
4
+ [![Build Status](https://travis-ci.org/stevenjack/cfndsl.png?branch=master)](https://travis-ci.org/stevenjack/cfndsl)
5
+ [![Gem Version](https://badge.fury.io/rb/cfndsl.png)](http://badge.fury.io/rb/cfndsl)
6
+ [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/stevenjack/cfndsl?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
7
+
8
+ [AWS Cloudformation](http://docs.amazonwebservices.com/AWSCloudFormation/latest/UserGuide/GettingStarted.html) templates are an incredibly powerful way to build
9
+ sets of resources in Amazon's AWS environment. Unfortunately, because
10
+ they are specified in JSON, they are also difficult to write and
11
+ maintain:
12
+
13
+ * JSON does not allow comments
14
+
15
+ * All structures are JSON, so it is sometimes easy for a person
16
+ reading a template to get lost.
17
+
18
+ * References and internal functions have a particularly unpleasant syntax.
19
+
20
+
21
+ The cnfdsl gem provides a simple DSL that allows you to write equivalent
22
+ templates in a more friendly language and generate the correct json
23
+ templates by running ruby.
24
+
25
+ ## Getting Started
26
+
27
+ sudo gem install cfndsl
28
+
29
+ Now write a template in the dsl
30
+
31
+ ```ruby
32
+
33
+ CloudFormation {
34
+ Description "Test"
35
+
36
+ Parameter("One") {
37
+ String
38
+ Default "Test"
39
+ MaxLength 15
40
+ }
41
+
42
+ Output(:One,FnBase64( Ref("One")))
43
+
44
+ EC2_Instance(:MyInstance) {
45
+ ImageId "ami-12345678"
46
+ }
47
+
48
+ }
49
+ ```
50
+
51
+ Then run cfndsl on the file
52
+
53
+ ```
54
+ chris@raspberrypi:~/git/cfndsl$ cfndsl test.rb | json_pp
55
+ {
56
+ "Parameters" : {
57
+ "One" : {
58
+ "Type" : "String",
59
+ "Default" : "Test",
60
+ "MaxLength" : 15
61
+ }
62
+ },
63
+ "Resources" : {
64
+ "MyInstance" : {
65
+ "Type" : "AWS::EC2::Instance",
66
+ "Properties" : {
67
+ "ImageId" : "ami-12345678"
68
+ }
69
+ }
70
+ },
71
+ "AWSTemplateFormatVersion" : "2010-09-09",
72
+ "Outputs" : {
73
+ "One" : {
74
+ "Value" : {
75
+ "Fn::Base64" : {
76
+ "Ref" : "One"
77
+ }
78
+ }
79
+ }
80
+ },
81
+ "Description" : "Test"
82
+ }
83
+ ```
84
+
85
+ *Aside: that is correct - a significant amount of the development for
86
+ this gem was done on a [Raspberry Pi](http://www.raspberrypi.org).*
87
+
88
+ ## Samples
89
+
90
+ There is a more detailed example in the samples directory. The file
91
+ "autoscale.template" is one of the standard Amazon sample templates.
92
+ "autoscale.rb" generates an equivalent template file.
93
+
94
+ ## Command Line Options
95
+
96
+ The cfndsl command line program now accepts some command line options.
97
+
98
+ ```
99
+ Usage: cfndsl [options] FILE
100
+ -o, --output FILE Write output to file
101
+ -y, --yaml FILE Import yaml file as local variables
102
+ -r, --ruby FILE Evaluate ruby file before template
103
+ -j, --json FILE Import json file as local variables
104
+ -D, --define "VARIABLE=VALUE" Directly set local VARIABLE as VALUE
105
+ -v, --verbose Turn on verbose ouptut
106
+ -h, --help Display this screen
107
+ ```
108
+
109
+ By default, cfndsl will attempt to evaluate FILE as cfndsl template and print
110
+ the resulting cloudformation json template to stdout. With the -o option, you
111
+ can instead have it write the resulting json template to a given file. The -v
112
+ option prints out additional information (to stderr) about what is happening
113
+ in the model generation process.
114
+
115
+ The -y, -j, -r and -D options can be used to control some things about the
116
+ environment that the template code gets evaluate in. For instance, the -D
117
+ option allows you to set a variable at the command line that can then be
118
+ referred to within the template itself.
119
+
120
+ This is best illustrated with a example. Consider the following cfndsl
121
+ template
122
+
123
+ ```ruby
124
+ # cfndsl template t1.rb
125
+ CloudFormation {
126
+
127
+ DESCRIPTION ||= "default description"
128
+ MACHINES ||= 3
129
+
130
+ Description DESCRIPTION
131
+
132
+ (1..MACHINES).each do |i|
133
+ name = "machine#{i}"
134
+ EC2_Instance(name) {
135
+ ImageId "ami-12345678"
136
+ Type "t1.micro"
137
+ }
138
+ end
139
+
140
+ }
141
+ ```
142
+
143
+ Note the two variables "DESCRIPTION" and "MACHINES". The template
144
+ sets these to some reasonable default values, and if you run cfndsl
145
+ on it without changing them in any way you get the following cloudformation
146
+ template:
147
+
148
+ ```json
149
+ {
150
+ "Resources": {
151
+ "machine1": {
152
+ "Type": "AWS::EC2::Instance",
153
+ "Properties": {
154
+ "ImageId": "ami-12345678"
155
+ }
156
+ }
157
+ },
158
+ "Description": "default description",
159
+ "AWSTemplateFormatVersion": "2010-09-09"
160
+ }
161
+ ```
162
+
163
+ However if you run the command
164
+
165
+ ```bash
166
+ $ cfndsl t1.rb -D 'DESCRIPTION="3 machine cluster"' -D 'MACHINES=3'
167
+ ```
168
+
169
+ you get the following generated template.
170
+
171
+ ```json
172
+ {
173
+ "Resources": {
174
+ "machine3": {
175
+ "Type": "AWS::EC2::Instance",
176
+ "Properties": {
177
+ "ImageId": "ami-12345678"
178
+ }
179
+ },
180
+ "machine2": {
181
+ "Type": "AWS::EC2::Instance",
182
+ "Properties": {
183
+ "ImageId": "ami-12345678"
184
+ }
185
+ },
186
+ "machine1": {
187
+ "Type": "AWS::EC2::Instance",
188
+ "Properties": {
189
+ "ImageId": "ami-12345678"
190
+ }
191
+ }
192
+ },
193
+ "Description": "3 machine cluster",
194
+ "AWSTemplateFormatVersion": "2010-09-09"
195
+ }
196
+ ```
197
+
198
+ The -y and -j options allow you to group several variable definitions
199
+ into a single file (formated as either yaml or ruby respectively). If
200
+ you had a file called 't1.yaml' that contained the following,
201
+
202
+ ```yaml
203
+ # t1.yaml
204
+ DESCRIPTION: 5 machine cluster
205
+ MACHINES: 5
206
+ ```
207
+
208
+ the command
209
+
210
+ ```bash
211
+ $ cfndsl t1.rb -y t1.yaml
212
+ ```
213
+
214
+ would generate a template with 5 instances declared.
215
+
216
+ Finally, the -r option gives you the opportunity to execute some
217
+ arbitrary ruby code in the evaluation context before the cloudformation
218
+ template is evaluated.
219
+
220
+
221
+
@@ -0,0 +1,55 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require "cfndsl/version"
4
+
5
+ RSpec::Core::RakeTask.new
6
+
7
+ task default: [:spec]
8
+
9
+ task :bump, :type do |t, args|
10
+ type = args[:type].downcase
11
+ version_path = "lib/cfndsl/version.rb"
12
+
13
+ fail unless %w(major minor patch).include? type
14
+
15
+ if `git rev-parse --abbrev-ref HEAD` != "master"
16
+ fail "Looks like you're trying to create a release in a branch, you can only create one in 'master'"
17
+ end
18
+
19
+ version_segments = CfnDsl::VERSION.split(".").map(&:to_i)
20
+
21
+ case type
22
+ when "major"
23
+ version_segments[0]+= 1
24
+ version_segments[1] = 0
25
+ version_segments[2] = 0
26
+ when "minor"
27
+ version_segments[1]+= 1
28
+ version_segments[2] = 0
29
+ when "patch"
30
+ version_segments[2]+= 1
31
+ end
32
+
33
+ version = version_segments.join(".")
34
+
35
+ puts "Bumping gem from version #{CfnDsl::VERSION} to #{version} as a '#{type.capitalize}' release"
36
+
37
+ contents = File.read version_path
38
+ updated_contents = contents.gsub(/([0-9\.]+)/, version)
39
+ File.write(version_path, updated_contents)
40
+
41
+ puts "Commiting version update"
42
+ `git add #{version_path}`
43
+ `git commit --message='#{type.capitalize} release #{version}'`
44
+
45
+ puts "Tagging release"
46
+ `git tag -a v#{version} -m 'Version #{version}'`
47
+
48
+ puts "Pushing branch"
49
+ `git push origin master`
50
+
51
+ puts "Pushing tag"
52
+ `git push origin v#{version}`
53
+
54
+ puts "All done, travis should pick up and release the gem now!"
55
+ end
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "cfndsl/version"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "cfndsl"
8
+ s.version = CfnDsl::VERSION
9
+ s.summary = "AWS Cloudformation DSL"
10
+ s.description = "DSL for creating AWS Cloudformation templates"
11
+ s.authors = ["Steven Jack", "Chris Howe"]
12
+ s.email = ["stevenmajack@gmail.com", "chris@howeville.com"]
13
+ s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
14
+ s.executables << "cfndsl"
15
+ s.homepage = "https://github.com/stevenjack/cfndsl"
16
+ s.license = "MIT"
17
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_development_dependency "bundler"
21
+ end
@@ -0,0 +1,3 @@
1
+ module CfnDsl
2
+ VERSION = "0.1.17"
3
+ end
@@ -0,0 +1,243 @@
1
+
2
+ # We start things off by calling the CloudFormation function.
3
+ CloudFormation {
4
+ # Declare the template format version
5
+ AWSTemplateFormatVersion "2010-09-09"
6
+
7
+ # As the DSL is really ruby, we get all of the different
8
+ # ways to quote strings that come with ruby.
9
+ Description %Q/
10
+ Create a multi-az, load balanced, Auto Scaled sample web site. The
11
+ Auto Scaling trigger is based on the CPU utilization of the web
12
+ servers. The AMI is chosen based on the region in which the stack is
13
+ run. This example creates a web service running across all
14
+ availability zones in a region. The instances are load balanced with a
15
+ simple health check. The web site is available on port 80, however,
16
+ the instances can be configured to listen on any port (8888 by
17
+ default).
18
+
19
+ **WARNING** This template creates one or more Amazon EC2
20
+ instances. You will be billed for the AWS resources used if you create
21
+ a stack from this template.
22
+ /
23
+
24
+ # We can declare Parameters anywhere in the CloudFormation
25
+ # block - these will get rolled up into the Parameters container
26
+ # in the output.
27
+ Parameter("InstanceType") {
28
+ Description "Type of EC2 instance to launch"
29
+ Type "String"
30
+ Default "m1.small"
31
+ }
32
+
33
+ Parameter( "WebServerPort") {
34
+ Description "The TCP port for the Web Server"
35
+ Type "String"
36
+ Default "8888"
37
+ }
38
+ Parameter("KeyName") {
39
+ Description "The EC2 Key Pair to allow SSH access to the instances"
40
+ Type "String"
41
+ }
42
+
43
+ # The same kind of thing for parameters works for mappings,
44
+ # except that there is not a special object declared for mappings,
45
+ # so we just have to build a hash of hashes which will be turned
46
+ # directly into json.
47
+
48
+ Mapping("AWSRegionArch2AMI", {
49
+ "us-east-1" => { "32" => "ami-6411e20d", "64" => "ami-7a11e213" },
50
+ "us-west-1" => { "32" => "ami-c9c7978c", "64" => "ami-cfc7978a" },
51
+ "eu-west-1" => { "32" => "ami-37c2f643", "64" => "ami-31c2f645" },
52
+ "ap-southeast-1" => { "32" => "ami-66f28c34", "64" => "ami-60f28c32" },
53
+ "ap-northeast-1" => { "32" => "ami-9c03a89d", "64" => "ami-a003a8a1" }
54
+ })
55
+
56
+
57
+ # We can also write arbitrary ruby code
58
+
59
+ # Here we build up a ruby hash
60
+ architectures = {}
61
+ [ "t1.micro", "m1.large", "m1.xlarge", "m2.xlarge",
62
+ "m2.2xlarge", "m2.4xlarge", "c1.xlarge", "cc1.4xlarge"
63
+ ].each do |arch|
64
+ # Iterate through the 64 bit machines to build a mapping for
65
+ # 64 bit architecture
66
+ architectures[arch] = { "Arch" => "64" }
67
+ end
68
+
69
+ [ "m1.small", "c1.medium"
70
+ ].each do |arch|
71
+ # iterate throught he 32 bit machine to build a mapping for
72
+ # 32 bit architectures
73
+ architectures[arch] = { "Arch" => "32" }
74
+ end
75
+
76
+ Mapping("AWSInstanceType2Arch", architectures )
77
+ # This will add a mapping entry equivalent to the following to the
78
+ # template:
79
+ #
80
+ # "AWSInstanceType2Arch" : {
81
+ # "m2.4xlarge" : { "Arch" : "64" },
82
+ # "c1.xlarge" : { "Arch" : "64" },
83
+ # "c1.medium" : { "Arch" : "32" },
84
+ # "m1.xlarge" : { "Arch" : "64" },
85
+ # "m1.large" : { "Arch" : "64" },
86
+ # "t1.micro" : { "Arch" : "64" },
87
+ # "m1.small" : { "Arch" : "32" },
88
+ # "m2.2xlarge" : { "Arch" : "64" },
89
+ # "m2.xlarge" : { "Arch" : "64" },
90
+ # "cc1.4xlarge" : { "Arch" : "64" }
91
+ # }
92
+
93
+
94
+ # Resources work similar to Parameters
95
+ Resource("WebServerGroup") {
96
+ Type "AWS::AutoScaling::AutoScalingGroup"
97
+
98
+ # To call aws template defined functions, call them like
99
+ # functios (leaving out the double colons). For example
100
+ # the following:
101
+ Property("AvailabilityZones", FnGetAZs("") )
102
+ # will generate JSON that includes
103
+ # { "Fn::GetAZs : "" }
104
+ # as the value of the AvailabilityZones property for the
105
+ # "WebServerGroup" reqource.
106
+
107
+ # The same works for references
108
+ Property("LaunchConfigurationName", Ref( "LaunchConfig") )
109
+ Property("MinSize", "1")
110
+ Property("MaxSize", "3")
111
+
112
+ # If you need to set a property value to a JSON array in
113
+ # the template, you can just use a ruby array in the DSL.
114
+ Property("LoadBalancerNames", [ Ref( "ElasticLoadBalancer") ] )
115
+
116
+ }
117
+
118
+ # You can use either strings or symbols for
119
+ # Resource/Parameter/Mapping/Output names
120
+ Resource( :LaunchConfig ) {
121
+ Type "AWS::AutoScaling::LaunchConfiguration"
122
+
123
+ Property("KeyName", Ref("KeyName") )
124
+ Property( "ImageId",
125
+ FnFindInMap( "AWSRegionArch2AMI", Ref("AWS::Region"),
126
+ FnFindInMap( "AWSInstanceType2Arch", Ref("InstanceType"),"Arch")))
127
+ Property("UserData", FnBase64( Ref("WebServerPort")))
128
+ Property("SecurityGroups", [ Ref("InstanceSecurityGroup")])
129
+ Property("InstanceType", Ref("InstanceType") )
130
+ }
131
+
132
+
133
+ Resource( "WebServerScaleUpPolicy" ) {
134
+ Type "AWS::AutoScaling::ScalingPolicy"
135
+ Property("AdjustmentType", "ChangeInCapacity")
136
+ Property("AutoScalingGroupName", Ref( "WebServerGroup") )
137
+ Property("Cooldown", "60")
138
+ Property("ScalingAdjustment", "1")
139
+ }
140
+
141
+ Resource("WebServerScaleDownPolicy") {
142
+ Type "AWS::AutoScaling::ScalingPolicy"
143
+ Property("AdjustmentType", "ChangeInCapacity")
144
+ Property("AutoScalingGroupName", Ref( "WebServerGroup" ))
145
+ Property("Cooldown", "60")
146
+ Property("ScalingAdjustment", "-1")
147
+ }
148
+
149
+
150
+ # You can use ruby language constructs to keep from repeating
151
+ # yourself
152
+
153
+ # declare an aray - we are going to use it to collect some
154
+ # resources that we create
155
+ alarms = [];
156
+
157
+ # When we declare a resource with "Resource", we are
158
+ # actually calling a method on CfnDsl::CloudFormationTemplate
159
+ # that sets up the resource, and then returns it. We can use
160
+ # the return value for other means.
161
+ alarms.push Resource("CPUAlarmHigh") {
162
+ Type "AWS::CloudWatch::Alarm"
163
+ Property("AlarmDescription", "Scale-up if CPU > 90% for 10 minutes")
164
+ Property("Threshold", "90")
165
+ Property("AlarmActions", [ Ref("WebServerScaleUpPolicy" ) ])
166
+ Property("ComparisonOperator", "GreaterThanThreshold")
167
+ }
168
+
169
+ # Declare a second alarm resource and add it to our list
170
+ alarms.push Resource("CPUAlarmLow") {
171
+ Type "AWS::CloudWatch::Alarm"
172
+ Property("AlarmDescription", "Scale-down if CPU < 70% for 10 minutes")
173
+ Property("Threshold", "70")
174
+ Property("AlarmActions", [ Ref("WebServerScaleDownPolicy" ) ])
175
+ Property("ComparisonOperator", "LessThanThreshold")
176
+ }
177
+
178
+ # Ok, the alarms that we previously declared actually share a bunch
179
+ # of property declarations. Here we iterate through the alarms and
180
+ # call declare on each one, passing in a code block. This works the
181
+ # same as the declarations placed in the code blocks that went along
182
+ # with the call to Resource that was used to create the resouce above.
183
+ alarms.each do |alarm|
184
+ alarm.declare {
185
+ Property("MetricName", "CPUUtilization")
186
+ Property("Namespace", "AWS/EC2")
187
+ Property("Statistic", "Average")
188
+ Property("Period", "300")
189
+ Property("EvaluationPeriods", "2")
190
+ Property("Dimensions", [
191
+ {
192
+ "Name" => "AutoScalingGroupName",
193
+ "Value" => Ref("WebServerGroup" )
194
+ }
195
+ ])
196
+
197
+ }
198
+ end
199
+
200
+
201
+ Resource( "ElasticLoadBalancer" ) {
202
+ Type "AWS::ElasticLoadBalancing::LoadBalancer"
203
+ Property( "AvailabilityZones", FnGetAZs(""))
204
+ Property( "Listeners" , [ {
205
+ "LoadBalancerPort" => "80",
206
+ "InstancePort" => Ref( "WebServerPort" ),
207
+ "Protocol" => "HTTP"
208
+ } ] )
209
+ Property( "HealthCheck" , {
210
+ # FnFormat replaces %0, %1, etc with passed in parameters
211
+ # Note that it renders to a call to Fn::Join in the json.
212
+ "Target" => FnFormat("HTTP:%0/", Ref( "WebServerPort" ) ),
213
+ "HealthyThreshold" => "3",
214
+ "UnhealthyThreshold" => "5",
215
+ "Interval" => "30",
216
+ "Timeout" => "5"
217
+ })
218
+ }
219
+
220
+ Resource("InstanceSecurityGroup" ) {
221
+ Type "AWS::EC2::SecurityGroup"
222
+ Property("GroupDescription" , "Enable SSH access and HTTP access on the inbound port")
223
+ Property("SecurityGroupIngress", [ {
224
+ "IpProtocol" => "tcp",
225
+ "FromPort" => "22",
226
+ "ToPort" => "22",
227
+ "CidrIp" => "0.0.0.0/0"
228
+ },
229
+ {
230
+ "IpProtocol" => "tcp",
231
+ "FromPort" => Ref( "WebServerPort" ),
232
+ "ToPort" => Ref( "WebServerPort" ),
233
+ "SourceSecurityGroupOwnerId" => FnGetAtt("ElasticLoadBalancer", "SourceSecurityGroup.OwnerAlias"),
234
+ "SourceSecurityGroupName" => FnGetAtt("ElasticLoadBalancer", "SourceSecurityGroup.GroupName")
235
+ } ])
236
+ }
237
+
238
+ Output( "URL" ) {
239
+ Description "The URL of the website"
240
+ Value FnJoin( "", [ "http://", FnGetAtt( "ElasticLoadBalancer", "DNSName" ) ] )
241
+ }
242
+
243
+ }