lono 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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