lono 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ .DS_Store
2
+ *.gem
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg
6
+ tmp
7
+ output
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
@@ -0,0 +1,9 @@
1
+ # guard 'bundler' do
2
+ # watch('Gemfile')
3
+ # end
4
+
5
+ guard 'rspec' do
6
+ watch(%r{^spec/.+_spec\.rb$})
7
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
8
+ # watch('spec/spec_helper.rb') { "spec" }
9
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Tung Nguyen
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,27 @@
1
+ Lono
2
+ ===========
3
+
4
+ Lono generates Cloud Formation templates based on ERB templates.
5
+
6
+ Usage
7
+ ------------
8
+
9
+ <pre>
10
+ $ gem install lono
11
+ $ mkdir lono_project
12
+ $ lono init
13
+ </pre>
14
+
15
+ This sets up the basic lono project with an example template in source/app.json.erb.
16
+
17
+ <pre>
18
+ $ lono generate
19
+ </pre>
20
+
21
+ This generates the templates that have been defined in config/lono.rb.
22
+
23
+ <pre>
24
+ $ guard
25
+ </pre>
26
+
27
+ The lono init comamnd also sets up guard-lono and guard-cloudformation. Guard-lono continuously generates the cloud formation templates and guard-cloudformation continuously verifies that the cloud formation templates are valid via AWS's cfn-validate-template command.
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+
5
+ task :default => :spec
6
+
7
+ RSpec::Core::RakeTask.new
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path("../../lib/lono", __FILE__)
4
+ Lono::CLI.start
@@ -0,0 +1,11 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard "lono" do
5
+ watch(%r{^config/lono.rb$})
6
+ watch(%r{^templates/.*$})
7
+ end
8
+
9
+ guard "cloudformation", :templates_path => "output" do
10
+ watch(%r{^output/.+\.json$})
11
+ end
@@ -0,0 +1,39 @@
1
+ template "prod-api-app.json" do
2
+ source "app.json.erb"
3
+ variables(
4
+ :env => 'prod',
5
+ :app => 'api',
6
+ :role => "app",
7
+ :ami => "ami-123",
8
+ :instance_type => "c1.xlarge",
9
+ :port => "80",
10
+ :high_threshold => "15",
11
+ :high_periods => "4",
12
+ :low_threshold => "5",
13
+ :low_periods => "10",
14
+ :max_size => "24",
15
+ :min_size => "6",
16
+ :down_adjustment => "-3",
17
+ :up_adjustment => "3",
18
+ :ssl_cert => "arn:aws:iam::12345:server-certificate/wildcard"
19
+ )
20
+ end
21
+ template "prod-br-app.json" do
22
+ source "app.json.erb"
23
+ variables(
24
+ :env => "prod",
25
+ :app => 'br',
26
+ :role => "app",
27
+ :ami => "ami-456",
28
+ :instance_type => "m1.medium",
29
+ :port => "80",
30
+ :high_threshold => "35",
31
+ :high_periods => "4",
32
+ :low_threshold => "20",
33
+ :low_periods => "2",
34
+ :max_size => "6",
35
+ :min_size => "3",
36
+ :down_adjustment => "-1",
37
+ :up_adjustment => "2"
38
+ )
39
+ end
@@ -0,0 +1,424 @@
1
+ {
2
+ "AWSTemplateFormatVersion": "2010-09-09",
3
+ "Description": "<%= @app.capitalize %> Stack",
4
+ "Mappings": {
5
+ "AWSInstanceType2Arch": {
6
+ "c1.medium": {
7
+ "Arch": "64"
8
+ },
9
+ "c1.xlarge": {
10
+ "Arch": "64"
11
+ },
12
+ "cc1.4xlarge": {
13
+ "Arch": "64"
14
+ },
15
+ "cc2.8xlarge": {
16
+ "Arch": "64"
17
+ },
18
+ "cg1.4xlarge": {
19
+ "Arch": "64"
20
+ },
21
+ "m1.large": {
22
+ "Arch": "64"
23
+ },
24
+ "m1.medium": {
25
+ "Arch": "64"
26
+ },
27
+ "m1.small": {
28
+ "Arch": "64"
29
+ },
30
+ "m1.xlarge": {
31
+ "Arch": "64"
32
+ },
33
+ "m2.2xlarge": {
34
+ "Arch": "64"
35
+ },
36
+ "m2.4xlarge": {
37
+ "Arch": "64"
38
+ },
39
+ "m2.xlarge": {
40
+ "Arch": "64"
41
+ },
42
+ "t1.micro": {
43
+ "Arch": "64"
44
+ }
45
+ },
46
+ "AWSRegionArch2AMI": {
47
+ "us-east-1": {
48
+ "32": "",
49
+ "64": "<%= @ami %>"
50
+ },
51
+ "us-west-1": {
52
+ "32": "",
53
+ "64": ""
54
+ }
55
+ }
56
+ },
57
+ "Outputs": {
58
+ "ELBHostname": {
59
+ "Description": "The URL of the website",
60
+ "Value": {
61
+ "Fn::Join": [
62
+ "",
63
+ [
64
+ "http://",
65
+ {
66
+ "Fn::GetAtt": [
67
+ "elb",
68
+ "DNSName"
69
+ ]
70
+ }
71
+ ]
72
+ ]
73
+ }
74
+ }
75
+ },
76
+ "Parameters": {
77
+ "Application": {
78
+ "Default": "<%= @app %>",
79
+ "Description": "Application name",
80
+ "Type": "String"
81
+ },
82
+ "Environment": {
83
+ "Default": "<%= @env %>",
84
+ "Description": "stag, prod etc",
85
+ "Type": "String"
86
+ },
87
+ "InstanceType": {
88
+ "AllowedValues": [
89
+ "t1.micro",
90
+ "m1.small",
91
+ "m1.medium",
92
+ "m1.large",
93
+ "m1.xlarge",
94
+ "m2.xlarge",
95
+ "m2.2xlarge",
96
+ "m2.4xlarge",
97
+ "c1.medium",
98
+ "c1.xlarge",
99
+ "cc1.4xlarge",
100
+ "cc2.8xlarge",
101
+ "cg1.4xlarge"
102
+ ],
103
+ "ConstraintDescription": "must be a valid EC2 instance type.",
104
+ "Default": "<%= @instance_type %>",
105
+ "Description": "WebServer EC2 instance type",
106
+ "Type": "String"
107
+ },
108
+ "KeyName": {
109
+ "Default": "default",
110
+ "Description": "The EC2 Key Pair to allow SSH access to the instances",
111
+ "Type": "String"
112
+ },
113
+ "Role": {
114
+ "Default": "<%= @role %>",
115
+ "Description": "redis, psql, app, etc",
116
+ "Type": "String"
117
+ },
118
+ "StackNumber": {
119
+ "Description": "s1, s2, s3, etc",
120
+ "Type": "String"
121
+ },
122
+ "WebServerPort": {
123
+ "Default": "<%= @port %>",
124
+ "Description": "The TCP port for the Web Server",
125
+ "Type": "Number"
126
+ }
127
+ },
128
+ "Resources": {
129
+ "CPUAlarmHigh": {
130
+ "Properties": {
131
+ "AlarmActions": [
132
+ {
133
+ "Ref": "WebServerScaleUpPolicy"
134
+ }
135
+ ],
136
+ "AlarmDescription": "Scale-up if CPU > <%= @high_threshold %>% for <%= @high_mins %> minutes",
137
+ "ComparisonOperator": "GreaterThanThreshold",
138
+ "Dimensions": [
139
+ {
140
+ "Name": "AutoScalingGroupName",
141
+ "Value": {
142
+ "Ref": "WebServerGroup"
143
+ }
144
+ }
145
+ ],
146
+ "EvaluationPeriods": "<%= @high_periods %>",
147
+ "MetricName": "CPUUtilization",
148
+ "Namespace": "AWS/EC2",
149
+ "Period": "60",
150
+ "Statistic": "Average",
151
+ "Threshold": "<%= @high_threshold %>"
152
+ },
153
+ "Type": "AWS::CloudWatch::Alarm"
154
+ },
155
+ "CPUAlarmLow": {
156
+ "Properties": {
157
+ "AlarmActions": [
158
+ {
159
+ "Ref": "WebServerScaleDownPolicy"
160
+ }
161
+ ],
162
+ "AlarmDescription": "Scale-down if CPU < <%= @low_threshold %>% for 10 minutes",
163
+ "ComparisonOperator": "LessThanThreshold",
164
+ "Dimensions": [
165
+ {
166
+ "Name": "AutoScalingGroupName",
167
+ "Value": {
168
+ "Ref": "WebServerGroup"
169
+ }
170
+ }
171
+ ],
172
+ "EvaluationPeriods": "<%= @low_periods %>",
173
+ "MetricName": "CPUUtilization",
174
+ "Namespace": "AWS/EC2",
175
+ "Period": "60",
176
+ "Statistic": "Average",
177
+ "Threshold": "<%= @low_threshold %>"
178
+ },
179
+ "Type": "AWS::CloudWatch::Alarm"
180
+ },
181
+ "HostRecord": {
182
+ "Properties": {
183
+ "Comment": "DNS name for my stack.",
184
+ "HostedZoneName": "mydomain.net.",
185
+ "Name": {
186
+ "Fn::Join": [
187
+ "",
188
+ [
189
+ {
190
+ "Ref": "AWS::StackName"
191
+ },
192
+ ".mydomain.net"
193
+ ]
194
+ ]
195
+ },
196
+ "ResourceRecords": [
197
+ {
198
+ "Fn::GetAtt": [
199
+ "elb",
200
+ "DNSName"
201
+ ]
202
+ }
203
+ ],
204
+ "TTL": "60",
205
+ "Type": "CNAME"
206
+ },
207
+ "Type": "AWS::Route53::RecordSet"
208
+ },
209
+ "LaunchConfig": {
210
+ "Properties": {
211
+ "BlockDeviceMappings": [
212
+ {
213
+ "DeviceName": "/dev/sdb",
214
+ "VirtualName": "ephemeral0"
215
+ }
216
+ ],
217
+ "ImageId": {
218
+ "Fn::FindInMap": [
219
+ "AWSRegionArch2AMI",
220
+ {
221
+ "Ref": "AWS::Region"
222
+ },
223
+ {
224
+ "Fn::FindInMap": [
225
+ "AWSInstanceType2Arch",
226
+ {
227
+ "Ref": "InstanceType"
228
+ },
229
+ "Arch"
230
+ ]
231
+ }
232
+ ]
233
+ },
234
+ "InstanceType": {
235
+ "Ref": "InstanceType"
236
+ },
237
+ "KeyName": {
238
+ "Ref": "KeyName"
239
+ },
240
+ "SecurityGroups": [
241
+ "global",
242
+ {
243
+ "Fn::Join": [
244
+ "-",
245
+ [
246
+ {
247
+ "Ref": "Environment"
248
+ },
249
+ {
250
+ "Ref": "Application"
251
+ }
252
+ ]
253
+ ]
254
+ },
255
+ {
256
+ "Ref": "ServiceSecurityGroup"
257
+ }
258
+ ],
259
+ "UserData": {
260
+ "Fn::Base64": {
261
+ "Fn::Join": [
262
+ "",
263
+ [
264
+ "#!/bin/bash -lexv\n",
265
+ "exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1\n",
266
+ "echo ",
267
+ {
268
+ "Ref": "AWS::StackName"
269
+ },
270
+ " > /tmp/stackname\n",
271
+ "echo \"\" >> /etc/profile.d/base.sh\n",
272
+ "'\" >> /etc/profile.d/base.sh\n",
273
+ "source /etc/profile.d/base.sh\n",
274
+ "set +e\n",
275
+ "rvm use system --default\n",
276
+ "set -e\n",
277
+ "echo 'running' > /tmp/type-of-instance\n",
278
+ "cat /proc/uptime | cut -f1 -d'.' > /tmp/time-to-boot\n"
279
+ ]
280
+ ]
281
+ }
282
+ }
283
+ },
284
+ "Type": "AWS::AutoScaling::LaunchConfiguration"
285
+ },
286
+ "ServiceSecurityGroup": {
287
+ "Properties": {
288
+ "GroupDescription": "Enable SSH access and HTTP from the load balancer only",
289
+ "SecurityGroupIngress": [
290
+ {
291
+ "CidrIp": "0.0.0.0/0",
292
+ "FromPort": "22",
293
+ "IpProtocol": "tcp",
294
+ "ToPort": "22"
295
+ },
296
+ {
297
+ "FromPort": {
298
+ "Ref": "WebServerPort"
299
+ },
300
+ "IpProtocol": "tcp",
301
+ "SourceSecurityGroupName": {
302
+ "Fn::GetAtt": [
303
+ "elb",
304
+ "SourceSecurityGroup.GroupName"
305
+ ]
306
+ },
307
+ "SourceSecurityGroupOwnerId": {
308
+ "Fn::GetAtt": [
309
+ "elb",
310
+ "SourceSecurityGroup.OwnerAlias"
311
+ ]
312
+ },
313
+ "ToPort": {
314
+ "Ref": "WebServerPort"
315
+ }
316
+ }
317
+ ]
318
+ },
319
+ "Type": "AWS::EC2::SecurityGroup"
320
+ },
321
+ "WebServerGroup": {
322
+ "Properties": {
323
+ "AvailabilityZones": [
324
+ "us-east-1a",
325
+ "us-east-1d",
326
+ "us-east-1e"
327
+ ],
328
+ "HealthCheckGracePeriod": "300",
329
+ "HealthCheckType": "ELB",
330
+ "LaunchConfigurationName": {
331
+ "Ref": "LaunchConfig"
332
+ },
333
+ "LoadBalancerNames": [
334
+ {
335
+ "Ref": "elb"
336
+ }
337
+ ],
338
+ "MaxSize": "<%= @max_size %>",
339
+ "MinSize": "<%= @min_size %>",
340
+ "NotificationConfiguration": {
341
+ "NotificationTypes": [
342
+ "autoscaling:EC2_INSTANCE_LAUNCH",
343
+ "autoscaling:EC2_INSTANCE_LAUNCH_ERROR",
344
+ "autoscaling:EC2_INSTANCE_TERMINATE",
345
+ "autoscaling:EC2_INSTANCE_TERMINATE_ERROR"
346
+ ],
347
+ "TopicARN": [
348
+ "arn:aws:sns:us-east-1:867690557112:ops"
349
+ ]
350
+ }
351
+ },
352
+ "Type": "AWS::AutoScaling::AutoScalingGroup"
353
+ },
354
+ "WebServerScaleDownPolicy": {
355
+ "Properties": {
356
+ "AdjustmentType": "ChangeInCapacity",
357
+ "AutoScalingGroupName": {
358
+ "Ref": "WebServerGroup"
359
+ },
360
+ "Cooldown": "120",
361
+ "ScalingAdjustment": "<%= @down_adjustment %>"
362
+ },
363
+ "Type": "AWS::AutoScaling::ScalingPolicy"
364
+ },
365
+ "WebServerScaleUpPolicy": {
366
+ "Properties": {
367
+ "AdjustmentType": "ChangeInCapacity",
368
+ "AutoScalingGroupName": {
369
+ "Ref": "WebServerGroup"
370
+ },
371
+ "Cooldown": "120",
372
+ "ScalingAdjustment": "<%= @up_adjustment %>"
373
+ },
374
+ "Type": "AWS::AutoScaling::ScalingPolicy"
375
+ },
376
+ "elb": {
377
+ "Properties": {
378
+ "AvailabilityZones": [
379
+ "us-east-1a",
380
+ "us-east-1d",
381
+ "us-east-1e"
382
+ ],
383
+ "HealthCheck": {
384
+ "HealthyThreshold": "3",
385
+ "Interval": "6",
386
+ "Target": {
387
+ "Fn::Join": [
388
+ "",
389
+ [
390
+ "HTTP:",
391
+ {
392
+ "Ref": "WebServerPort"
393
+ },
394
+ "/up/elb"
395
+ ]
396
+ ]
397
+ },
398
+ "Timeout": "5",
399
+ "UnhealthyThreshold": "5"
400
+ },
401
+ "Listeners": [
402
+ {
403
+ "InstancePort": {
404
+ "Ref": "WebServerPort"
405
+ },
406
+ "LoadBalancerPort": "80",
407
+ "Protocol": "HTTP"
408
+ },
409
+ {
410
+ "InstancePort": {
411
+ "Ref": "WebServerPort"
412
+ },
413
+ "LoadBalancerPort": "443",
414
+ "PolicyNames": [],
415
+ "Protocol": "HTTPS",
416
+ "SSLCertificateId": "<%= @ssl_cert %>"
417
+ }
418
+
419
+ ]
420
+ },
421
+ "Type": "AWS::ElasticLoadBalancing::LoadBalancer"
422
+ }
423
+ }
424
+ }