lono 0.2.1 → 0.2.2

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.
@@ -233,9 +233,7 @@
233
233
  "Fn::Base64": {
234
234
  "Fn::Join": [
235
235
  "",
236
- [
237
- <%= user_data("app.sh.erb") %>
238
- ]
236
+ <%= user_data('app.sh.erb') %>
239
237
  ]
240
238
  }
241
239
  }
@@ -0,0 +1,211 @@
1
+ {
2
+ "AWSTemplateFormatVersion": "2010-09-09",
3
+ "Description": "<%= @app.capitalize %> <%= @role %>",
4
+ "Outputs": {
5
+ "DBHostname": {
6
+ "Description": "Hostname for Redis",
7
+ "Value": {
8
+ "Fn::Join": [
9
+ "",
10
+ [
11
+ "",
12
+ {
13
+ "Fn::GetAtt": [
14
+ "server",
15
+ "PublicDnsName"
16
+ ]
17
+ }
18
+ ]
19
+ ]
20
+ }
21
+ }
22
+ },
23
+ "Parameters": {
24
+ "Ami": {
25
+ "Default": "<%= @ami %>",
26
+ "Description": "deploy ami",
27
+ "Type": "String"
28
+ },
29
+ "Application": {
30
+ "Default": "<%= @app %>",
31
+ "Description": "foo, bar, etc",
32
+ "Type": "String"
33
+ },
34
+ "Environment": {
35
+ "Default": "<%= @env %>",
36
+ "Description": "stag, prod etc",
37
+ "Type": "String"
38
+ },
39
+ "InstanceType": {
40
+ "AllowedValues": [
41
+ "t1.micro",
42
+ "m1.small",
43
+ "m1.medium",
44
+ "m1.large",
45
+ "m1.xlarge",
46
+ "m2.xlarge",
47
+ "m2.2xlarge",
48
+ "m2.4xlarge",
49
+ "c1.medium",
50
+ "c1.xlarge",
51
+ "cc1.4xlarge",
52
+ "cc2.8xlarge",
53
+ "cg1.4xlarge"
54
+ ],
55
+ "ConstraintDescription": "must be a valid EC2 instance type.",
56
+ "Default": "<%= @instance_type %>",
57
+ "Description": "server EC2 instance type",
58
+ "Type": "String"
59
+ },
60
+ "KeyName": {
61
+ "AllowedPattern": "[-_ a-zA-Z0-9]*",
62
+ "ConstraintDescription": "can contain only alphanumeric characters, spaces, dashes and underscores.",
63
+ "Default": "default",
64
+ "Description": "Name of an existing EC2 KeyPair to enable SSH access to the instances",
65
+ "MaxLength": "64",
66
+ "MinLength": "1",
67
+ "Type": "String"
68
+ },
69
+ "Role": {
70
+ "Default": "<%= @role %>",
71
+ "Description": "redis, psql, app, etc",
72
+ "Type": "String"
73
+ },
74
+ "StackNumber": {
75
+ "Default": "<%= @stack_number %>",
76
+ "Description": "s1, s2, s3, etc",
77
+ "Type": "String"
78
+ },
79
+ "VolumeSize": {
80
+ "ConstraintDescription": "must be between 5 and 1024 Gb.",
81
+ "Default": "<%= @volume_size %>",
82
+ "Description": "Size of Volume",
83
+ "MaxValue": "1024",
84
+ "MinValue": "5",
85
+ "Type": "Number"
86
+ }
87
+ },
88
+ "Resources": {
89
+ "CfnUser": {
90
+ "Properties": {
91
+ "Path": "/",
92
+ "Policies": [
93
+ {
94
+ "PolicyDocument": {
95
+ "Statement": [
96
+ {
97
+ "Action": "cloudformation:DescribeStackResource",
98
+ "Effect": "Allow",
99
+ "Resource": "*"
100
+ }
101
+ ]
102
+ },
103
+ "PolicyName": "root"
104
+ }
105
+ ]
106
+ },
107
+ "Type": "AWS::IAM::User"
108
+ },
109
+ "DataVolume": {
110
+ "DeletionPolicy": "Snapshot",
111
+ "Properties": {
112
+ "AvailabilityZone": {
113
+ "Fn::GetAtt": [
114
+ "server",
115
+ "AvailabilityZone"
116
+ ]
117
+ },
118
+ "Size": {
119
+ "Ref": "VolumeSize"
120
+ },
121
+ "Tags": [
122
+ {
123
+ "Key": "Usage",
124
+ "Value": "Data Volume"
125
+ }
126
+ ]
127
+ },
128
+ "Type": "AWS::EC2::Volume"
129
+ },
130
+ "HostKeys": {
131
+ "Properties": {
132
+ "UserName": {
133
+ "Ref": "CfnUser"
134
+ }
135
+ },
136
+ "Type": "AWS::IAM::AccessKey"
137
+ },
138
+ "HostRecord": {
139
+ "Properties": {
140
+ "Comment": "DNS name for my stack.",
141
+ "HostedZoneName": ".mydomain.net.",
142
+ "Name": {
143
+ "Fn::Join": [
144
+ "",
145
+ [
146
+ {
147
+ "Ref": "AWS::StackName"
148
+ },
149
+ ".mydomain.net."
150
+ ]
151
+ ]
152
+ },
153
+ "ResourceRecords": [
154
+ {
155
+ "Fn::GetAtt": [
156
+ "server",
157
+ "PublicDnsName"
158
+ ]
159
+ }
160
+ ],
161
+ "TTL": "60",
162
+ "Type": "CNAME"
163
+ },
164
+ "Type": "AWS::Route53::RecordSet"
165
+ },
166
+ "MountPoint": {
167
+ "Properties": {
168
+ "Device": "/dev/sdf",
169
+ "InstanceId": {
170
+ "Ref": "server"
171
+ },
172
+ "VolumeId": {
173
+ "Ref": "DataVolume"
174
+ }
175
+ },
176
+ "Type": "AWS::EC2::VolumeAttachment"
177
+ },
178
+ "ServiceSecurityGroup": {
179
+ "Properties": {
180
+ "GroupDescription": "Enable SSH access.",
181
+ "SecurityGroupIngress": [
182
+ {
183
+ "CidrIp": "0.0.0.0/0",
184
+ "FromPort": "22",
185
+ "IpProtocol": "tcp",
186
+ "ToPort": "22"
187
+ }
188
+ ]
189
+ },
190
+ "Type": "AWS::EC2::SecurityGroup"
191
+ },
192
+ "WaitCondition": {
193
+ "DependsOn": "MountPoint",
194
+ "Metadata": {
195
+ "Comment1": "Note that the WaitCondition is dependent on the volume mount point allowing the volume to be created and attached to the EC2 instance",
196
+ "Comment2": "The instance bootstrap script waits for the volume to be attached to the instance prior to signalling completion."
197
+ },
198
+ "Properties": {
199
+ "Handle": {
200
+ "Ref": "WaitHandle"
201
+ },
202
+ "Timeout": "3000"
203
+ },
204
+ "Type": "AWS::CloudFormation::WaitCondition"
205
+ },
206
+ "WaitHandle": {
207
+ "Type": "AWS::CloudFormation::WaitConditionHandle"
208
+ },
209
+ <%= partial("server.json.erb") %>
210
+ }
211
+ }
@@ -1,7 +1,7 @@
1
1
  "HostRecord": {
2
2
  "Properties": {
3
3
  "Comment": "DNS name for my stack.",
4
- "HostedZoneName": "mydomain.net.",
4
+ "HostedZoneName": ".mydomain.net.",
5
5
  "Name": {
6
6
  "Fn::Join": [
7
7
  "",
@@ -0,0 +1,42 @@
1
+ "server": {
2
+ "Properties": {
3
+ "AvailabilityZone": "<%= @availability_zone %>",
4
+ "ImageId": {
5
+ "Ref": "Ami"
6
+ },
7
+ "InstanceType": {
8
+ "Ref": "InstanceType"
9
+ },
10
+ "KeyName": {
11
+ "Ref": "KeyName"
12
+ },
13
+ "SecurityGroups": [
14
+ "global",
15
+ {
16
+ "Fn::Join": [
17
+ "-",
18
+ [
19
+ {
20
+ "Ref": "Environment"
21
+ },
22
+ {
23
+ "Ref": "Application"
24
+ }
25
+ ]
26
+ ]
27
+ },
28
+ {
29
+ "Ref": "ServiceSecurityGroup"
30
+ }
31
+ ],
32
+ "UserData": {
33
+ "Fn::Base64": {
34
+ "Fn::Join": [
35
+ "",
36
+ <%= user_data('db.sh.erb') %>
37
+ ]
38
+ }
39
+ }
40
+ },
41
+ "Type": "AWS::EC2::Instance"
42
+ }
@@ -0,0 +1,27 @@
1
+ #!/bin/bash -lexv
2
+ exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
3
+
4
+ echo <%= ref("AWS::StackName") %> > /tmp/stack_name
5
+ # Helper function
6
+ function error_exit
7
+ {
8
+ /usr/local/bin/cfn-signal -e 1 -r "$1" '<%= ref("WaitHandle") %>'
9
+ exit 1
10
+ }
11
+ # Wait for the EBS volume to show up
12
+ while [ ! -e /dev/xvdf ]; do echo Waiting for EBS volume to attach; sleep 1; done
13
+ /bin/mkdir /media/redis
14
+ /sbin/mkfs -t ext4 /dev/xvdf
15
+ echo "/dev/xvdf /media/redis auto defaults 0 0" >> /etc/fstab
16
+ /bin/mount /media/redis
17
+ /usr/bin/redis-cli shutdown
18
+ sleep 10
19
+ mv /var/lib/redis/* /media/redis/
20
+ rm -r /var/lib/redis
21
+ ln -s /media/redis /var/lib/redis
22
+ chown -R redis:redis /var/lib/redis
23
+ chown -R redis:redis /media/redis
24
+ /usr/bin/redis-server
25
+ # If all is well so signal success
26
+ /usr/local/bin/cfn-signal -e $? -r "Ready to rock" '<%= ref("WaitHandle") %>'
27
+ cat /proc/uptime | cut -f1 -d'.' > /tmp/time-to-boot
@@ -2,36 +2,69 @@ require File.expand_path("../../spec_helper", __FILE__)
2
2
 
3
3
  describe Lono do
4
4
  before(:each) do
5
- @project_root = File.expand_path("../../project", __FILE__)
6
- @dsl = Lono::DSL.new(
7
- :config_path => "#{@project_root}/config/lono.rb",
8
- :project_root => @project_root
9
- )
10
- @dsl.evaluate
5
+ @project = File.expand_path("../../project", __FILE__)
6
+ FileUtils.mkdir(@project) unless File.exist?(@project)
7
+ execute("./bin/lono init -f -q --project-root #{@project}")
11
8
  end
12
9
 
13
10
  after(:each) do
14
- FileUtils.rm_rf("#{@project_root}/output")
11
+ FileUtils.rm_rf(@project)
15
12
  end
16
13
 
17
- it "should generate cloud formation template" do
18
- @dsl.build
19
- @dsl.output(:output_path => "#{@project_root}/output")
20
- raw = IO.read("#{@project_root}/output/prod-api-app.json")
21
- json = JSON.load(raw)
22
- json['Description'].should == "Api Stack"
23
- json['Mappings']['AWSRegionArch2AMI']['us-east-1']['64'].should == 'ami-123'
14
+ describe "ruby specs" do
15
+ before(:each) do
16
+ @dsl = Lono::DSL.new(
17
+ :project_root => @project,
18
+ :quiet => true
19
+ )
20
+ @dsl.run
21
+ end
22
+
23
+ it "should generate cloud formation template" do
24
+ raw = IO.read("#{@project}/output/prod-api-app.json")
25
+ json = JSON.load(raw)
26
+ json['Description'].should == "Api Stack"
27
+ json['Mappings']['AWSRegionArch2AMI']['us-east-1']['64'].should == 'ami-123'
28
+ end
29
+
30
+ it "should generate db template" do
31
+ raw = IO.read("#{@project}/output/prod-api-redis.json")
32
+ json = JSON.load(raw)
33
+ json['Description'].should == "Api redis"
34
+ user_data = json['Resources']['server']['Properties']['UserData']['Fn::Base64']['Fn::Join'][1]
35
+ user_data.should include({"Ref" => "AWS::StackName"})
36
+ user_data.should include({"Ref" => "WaitHandle"})
37
+ end
38
+
39
+ it "should transform bash script to CF template user_data" do
40
+ block = Proc.new { }
41
+ template = Lono::Template.new("foo", block)
42
+
43
+ line = 'echo {"Ref"=>"AWS::StackName"} > /tmp/stack_name ; {"Ref"=>"Ami"}'
44
+ data = template.transform(line)
45
+ data.should == ["echo ", {"Ref"=>"AWS::StackName"}, " > /tmp/stack_name ; ", {"Ref"=>"Ami"}, "\n"]
46
+
47
+ line = 'echo {"Ref"=>"AWS::StackName"} > /tmp/stack_name'
48
+ data = template.transform(line)
49
+ data.should == ["echo ", {"Ref"=>"AWS::StackName"}, " > /tmp/stack_name\n"]
50
+ end
51
+
52
+ it "task should generate cloud formation templates" do
53
+ Lono::Task.generate(
54
+ :project_root => @project,
55
+ :quiet => true
56
+ )
57
+ raw = IO.read("#{@project}/output/prod-api-app.json")
58
+ json = JSON.load(raw)
59
+ json['Description'].should == "Api Stack"
60
+ json['Mappings']['AWSRegionArch2AMI']['us-east-1']['64'].should == 'ami-123'
61
+ end
24
62
  end
25
63
 
26
- it "task should generate cloud formation templates" do
27
- Lono::Task.generate(
28
- :project_root => @project_root,
29
- :config_path => "#{@project_root}/config/lono.rb",
30
- :output_path => "#{@project_root}/output"
31
- )
32
- raw = IO.read("#{@project_root}/output/prod-api-app.json")
33
- json = JSON.load(raw)
34
- json['Description'].should == "Api Stack"
35
- json['Mappings']['AWSRegionArch2AMI']['us-east-1']['64'].should == 'ami-123'
64
+ describe "cli specs" do
65
+ it "should generate templates" do
66
+ out = execute("./bin/lono generate -c --project-root #{@project}")
67
+ out.should match /Generating Cloud Formation templates/
68
+ end
36
69
  end
37
70
  end
data/spec/spec_helper.rb CHANGED
@@ -5,4 +5,17 @@ Bundler.require(:development)
5
5
 
6
6
  $root = File.expand_path('../../', __FILE__)
7
7
 
8
- require "#{$root}/lib/lono"
8
+ require "#{$root}/lib/lono"
9
+
10
+ module Helpers
11
+ def execute(cmd)
12
+ puts "Running: #{cmd}" if ENV['DEBUG']
13
+ out = `#{cmd}`
14
+ puts out if ENV['DEBUG']
15
+ out
16
+ end
17
+ end
18
+
19
+ RSpec.configure do |c|
20
+ c.include Helpers
21
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lono
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-21 00:00:00.000000000 Z
12
+ date: 2013-03-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -206,21 +206,23 @@ files:
206
206
  - Rakefile
207
207
  - bin/lono
208
208
  - lib/ext/hash.rb
209
- - lib/files/Guardfile
210
- - lib/files/config/lono.rb
211
- - lib/files/templates/app.json.erb
212
209
  - lib/lono.rb
213
210
  - lib/lono/cli.rb
214
211
  - lib/lono/dsl.rb
215
212
  - lib/lono/task.rb
213
+ - lib/lono/template.rb
216
214
  - lib/lono/version.rb
215
+ - lib/starter_project/Guardfile
216
+ - lib/starter_project/config/lono.rb
217
+ - lib/starter_project/config/lono/api.rb
218
+ - lib/starter_project/templates/app.json.erb
219
+ - lib/starter_project/templates/db.json.erb
220
+ - lib/starter_project/templates/partial/host_record.json.erb
221
+ - lib/starter_project/templates/partial/server.json.erb
222
+ - lib/starter_project/templates/user_data/app.sh.erb
223
+ - lib/starter_project/templates/user_data/db.sh.erb
217
224
  - lono.gemspec
218
225
  - spec/lib/lono_spec.rb
219
- - spec/project/config/lono.rb
220
- - spec/project/config/lono/api.rb
221
- - spec/project/templates/app.json.erb
222
- - spec/project/templates/partial/host_record.json.erb
223
- - spec/project/templates/user_data/app.sh.erb
224
226
  - spec/spec_helper.rb
225
227
  homepage: http://github.com/tongueroo/lono
226
228
  licenses: []
@@ -249,9 +251,4 @@ summary: Lono is a Cloud Formation Template ruby generator. Lono generates Clou
249
251
  Formation templates based on ERB templates.
250
252
  test_files:
251
253
  - spec/lib/lono_spec.rb
252
- - spec/project/config/lono.rb
253
- - spec/project/config/lono/api.rb
254
- - spec/project/templates/app.json.erb
255
- - spec/project/templates/partial/host_record.json.erb
256
- - spec/project/templates/user_data/app.sh.erb
257
254
  - spec/spec_helper.rb