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.
- data/.gitignore +1 -0
- data/Guardfile +3 -3
- data/README.md +27 -40
- data/lib/lono.rb +1 -0
- data/lib/lono/cli.rb +9 -3
- data/lib/lono/dsl.rb +8 -49
- data/lib/lono/task.rb +12 -12
- data/lib/lono/template.rb +66 -0
- data/lib/lono/version.rb +1 -1
- data/lib/{files → starter_project}/Guardfile +0 -0
- data/{spec/project → lib/starter_project}/config/lono.rb +6 -5
- data/lib/{files/config/lono.rb → starter_project/config/lono/api.rb} +15 -18
- data/{spec/project → lib/starter_project}/templates/app.json.erb +1 -3
- data/lib/starter_project/templates/db.json.erb +211 -0
- data/{spec/project → lib/starter_project}/templates/partial/host_record.json.erb +1 -1
- data/lib/starter_project/templates/partial/server.json.erb +42 -0
- data/{spec/project → lib/starter_project}/templates/user_data/app.sh.erb +0 -0
- data/lib/starter_project/templates/user_data/db.sh.erb +27 -0
- data/spec/lib/lono_spec.rb +57 -24
- data/spec/spec_helper.rb +14 -1
- metadata +12 -15
- data/lib/files/templates/app.json.erb +0 -424
- data/spec/project/config/lono/api.rb +0 -20
data/.gitignore
CHANGED
data/Guardfile
CHANGED
data/README.md
CHANGED
@@ -11,29 +11,31 @@ Lono is a Cloud Formation Template ruby generator. Lono generates Cloud Formati
|
|
11
11
|
|
12
12
|
<pre>
|
13
13
|
$ gem install lono
|
14
|
-
$ mkdir
|
15
|
-
$ lono
|
14
|
+
$ mkdir lono
|
15
|
+
$ cd lono
|
16
|
+
$ lono init
|
16
17
|
</pre>
|
17
18
|
|
18
|
-
This sets up
|
19
|
+
This sets up a starter lono project with example templates.
|
19
20
|
|
20
21
|
<pre>
|
21
22
|
$ lono generate
|
22
23
|
</pre>
|
23
24
|
|
24
|
-
This generates the templates that have been defined in config
|
25
|
+
This generates the templates that have been defined in config folder of the lono project.
|
25
26
|
|
26
|
-
The
|
27
|
+
The one of starter lono config files looks like this:
|
27
28
|
|
28
29
|
```ruby
|
29
30
|
template "prod-api-app.json" do
|
31
|
+
env,app,role = name.sub('.json','').split('-')
|
30
32
|
source "app.json.erb"
|
31
33
|
variables(
|
32
|
-
:env =>
|
33
|
-
:app =>
|
34
|
-
:role =>
|
34
|
+
:env => env,
|
35
|
+
:app => app,
|
36
|
+
:role => role,
|
35
37
|
:ami => "ami-123",
|
36
|
-
:instance_type => "
|
38
|
+
:instance_type => "m1.small",
|
37
39
|
:port => "80",
|
38
40
|
:high_threshold => "15",
|
39
41
|
:high_periods => "4",
|
@@ -46,35 +48,20 @@ template "prod-api-app.json" do
|
|
46
48
|
:ssl_cert => "arn:aws:iam::12345:server-certificate/wildcard"
|
47
49
|
)
|
48
50
|
end
|
49
|
-
template "prod-br-app.json" do
|
50
|
-
source "app.json.erb"
|
51
|
-
variables(
|
52
|
-
:env => "prod",
|
53
|
-
:app => 'br',
|
54
|
-
:role => "app",
|
55
|
-
:ami => "ami-456",
|
56
|
-
:instance_type => "m1.medium",
|
57
|
-
:port => "80",
|
58
|
-
:high_threshold => "35",
|
59
|
-
:high_periods => "4",
|
60
|
-
:low_threshold => "20",
|
61
|
-
:low_periods => "2",
|
62
|
-
:max_size => "6",
|
63
|
-
:min_size => "3",
|
64
|
-
:down_adjustment => "-1",
|
65
|
-
:up_adjustment => "2"
|
66
|
-
)
|
67
|
-
end
|
68
51
|
```
|
69
52
|
|
70
|
-
The
|
53
|
+
The corresponding ERB template example file is [here](lib/starter_project/templates/app.json.erb).
|
54
|
+
|
55
|
+
## Template helper methods
|
71
56
|
|
72
|
-
|
57
|
+
There are helper methods that available in templates.
|
73
58
|
|
74
|
-
|
59
|
+
* partial - can be use to embed other files in a template. The partial should be placed in the templates/partial folder of the project. So:
|
60
|
+
* partial('launch_config.json.erb') -> templates/partial/launch_config.json.erb
|
75
61
|
|
76
|
-
* user_data
|
77
|
-
* user_data('
|
62
|
+
* user_data - can be used to include a user data script which is written in bash script form. The user data script should be placed in the templates/user_data folder of the project. So:
|
63
|
+
* user_data('bootstrap.sh.erb') -> templates/user_data/bootstrap.sh.erb
|
64
|
+
* user_data('db.sh.erb') -> templates/user_data/db.sh.erb
|
78
65
|
|
79
66
|
Here's how you would call it in the template.
|
80
67
|
|
@@ -83,20 +70,19 @@ Here's how you would call it in the template.
|
|
83
70
|
"Fn::Base64": {
|
84
71
|
"Fn::Join": [
|
85
72
|
"",
|
86
|
-
|
87
|
-
<%= user_data('bootstrap.sh.erb') %>
|
88
|
-
]
|
73
|
+
<%= user_data('bootstrap.sh.erb') %>
|
89
74
|
]
|
90
75
|
}
|
91
76
|
```
|
92
77
|
|
93
|
-
|
78
|
+
Within a user_data script you can call another helper method called ref.
|
94
79
|
|
95
|
-
|
80
|
+
* ref - can be use to reference other parameter or resource value within the cloud formation template. An [example](lib/starter_project/templates/user_data/db.sh.erb) is in the [starter_project](lib/starter_project).
|
81
|
+
|
82
|
+
## Breaking up config/lono.rb
|
96
83
|
|
97
|
-
An example is in the
|
84
|
+
If you have a lot of templates, the config/lono.rb file can get unwieldy long. You can break up the lono.rb file and put template defintions in the config/lono directory. Any file in this directory will be automatically loaded. An [example](lib/starter_project/config/lono/api.rb) is in the starter project.
|
98
85
|
|
99
|
-
* config/lono/api.rb
|
100
86
|
|
101
87
|
## Generate
|
102
88
|
|
@@ -104,6 +90,7 @@ You can generate the CF templates by running:
|
|
104
90
|
|
105
91
|
<pre>
|
106
92
|
$ lono generate
|
93
|
+
$ lono g -c # shortcut
|
107
94
|
</pre>
|
108
95
|
|
109
96
|
The lono init command also sets up guard-lono. Guard-lono continuously generates the cloud formation templates. Just run guard.
|
data/lib/lono.rb
CHANGED
data/lib/lono/cli.rb
CHANGED
@@ -3,10 +3,13 @@ require 'thor'
|
|
3
3
|
module Lono
|
4
4
|
class CLI < Thor
|
5
5
|
|
6
|
-
desc "init", "Setup lono project"
|
6
|
+
desc "init", "Setup lono starter project"
|
7
7
|
long_desc "Sets up config/lono.rb"
|
8
|
+
method_option :force, :type => :boolean, :aliases => "-f", :desc => "override existing starter files"
|
9
|
+
method_option :project_root, :default => ".", :aliases => "-r", :desc => "project root"
|
10
|
+
method_option :quiet, :type => :boolean, :aliases => "-q", :desc => "silence the output"
|
8
11
|
def init
|
9
|
-
Lono::Task.init
|
12
|
+
Lono::Task.init(options)
|
10
13
|
end
|
11
14
|
|
12
15
|
desc "generate", "Generate the cloud formation templates"
|
@@ -14,12 +17,15 @@ module Lono
|
|
14
17
|
Examples:
|
15
18
|
|
16
19
|
1. lono generate
|
20
|
+
2. lono g -c # shortcut
|
17
21
|
|
18
22
|
Builds the cloud formation templates files based on config/lono.rb and writes them to the output folder on the filesystem.
|
19
23
|
EOL
|
20
24
|
method_option :clean, :type => :boolean, :aliases => "-c", :desc => "remove all output files before generating"
|
25
|
+
method_option :project_root, :default => ".", :aliases => "-r", :desc => "project root"
|
26
|
+
method_option :quiet, :type => :boolean, :aliases => "-q", :desc => "silence the output"
|
21
27
|
def generate
|
22
|
-
Lono::Task.generate(options
|
28
|
+
Lono::Task.generate(options)
|
23
29
|
end
|
24
30
|
end
|
25
31
|
|
data/lib/lono/dsl.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
-
require 'erb'
|
2
|
-
require 'json'
|
3
|
-
|
4
1
|
module Lono
|
5
2
|
class DSL
|
6
3
|
def initialize(options={})
|
7
4
|
@options = options
|
8
|
-
@
|
5
|
+
@options[:project_root] ||= '.'
|
6
|
+
@path = "#{@options[:project_root]}/config/lono.rb"
|
9
7
|
@templates = []
|
10
8
|
@results = {}
|
11
9
|
end
|
@@ -32,14 +30,14 @@ module Lono
|
|
32
30
|
end
|
33
31
|
end
|
34
32
|
|
35
|
-
def output
|
36
|
-
output_path = options[:
|
37
|
-
FileUtils.rm_rf(output_path) if options[:clean]
|
33
|
+
def output
|
34
|
+
output_path = "#{@options[:project_root]}/output"
|
35
|
+
FileUtils.rm_rf(output_path) if @options[:clean]
|
38
36
|
FileUtils.mkdir(output_path) unless File.exist?(output_path)
|
39
|
-
puts "Generating Cloud Formation templates:"
|
37
|
+
puts "Generating Cloud Formation templates:" unless @options[:quiet]
|
40
38
|
@results.each do |name,json|
|
41
39
|
path = "#{output_path}/#{name}"
|
42
|
-
puts " #{path}"
|
40
|
+
puts " #{path}" unless @options[:quiet]
|
43
41
|
pretty_json = JSON.pretty_generate(JSON.parse(json))
|
44
42
|
File.open(path, 'w') {|f| f.write(pretty_json) }
|
45
43
|
end
|
@@ -48,46 +46,7 @@ module Lono
|
|
48
46
|
def run(options={})
|
49
47
|
evaluate
|
50
48
|
build
|
51
|
-
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
class Template
|
56
|
-
include ERB::Util
|
57
|
-
|
58
|
-
def initialize(name, block, options={})
|
59
|
-
@name = name
|
60
|
-
@block = block
|
61
|
-
@options = options
|
62
|
-
@options[:project_root] ||= '.'
|
63
|
-
end
|
64
|
-
|
65
|
-
def build
|
66
|
-
instance_eval(&@block)
|
67
|
-
template = IO.read(@source)
|
68
|
-
ERB.new(template).result(binding)
|
69
|
-
end
|
70
|
-
|
71
|
-
def source(path)
|
72
|
-
@source = "#{@options[:project_root]}/templates/#{path}"
|
73
|
-
end
|
74
|
-
|
75
|
-
def variables(vars={})
|
76
|
-
vars.each do |var,value|
|
77
|
-
instance_variable_set("@#{var}", value)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def partial(path)
|
82
|
-
path = "#{@options[:project_root]}/templates/partial/#{path}"
|
83
|
-
template = IO.read(path)
|
84
|
-
ERB.new(template).result(binding)
|
85
|
-
end
|
86
|
-
|
87
|
-
def user_data(path)
|
88
|
-
path = "#{@options[:project_root]}/templates/user_data/#{path}"
|
89
|
-
template = IO.read(path)
|
90
|
-
ERB.new(template).result(binding).split("\n").collect {|l| "#{l}\n"}.to_json
|
49
|
+
output
|
91
50
|
end
|
92
51
|
end
|
93
52
|
end
|
data/lib/lono/task.rb
CHANGED
@@ -3,19 +3,23 @@ module Lono
|
|
3
3
|
def self.init(options={})
|
4
4
|
project_root = options[:project_root] || '.'
|
5
5
|
puts "Setting up lono project" unless options[:quiet]
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
dest =
|
6
|
+
source_root = File.expand_path("../../starter_project", __FILE__)
|
7
|
+
paths = Dir.glob("#{source_root}/**/*").
|
8
|
+
select {|p| File.file?(p) }
|
9
|
+
paths.each do |src|
|
10
|
+
dest = src.gsub(%r{.*starter_project/},'')
|
11
|
+
dest = "#{project_root}/#{dest}"
|
11
12
|
|
12
|
-
if File.exist?(dest)
|
13
|
+
if File.exist?(dest) and !options[:force]
|
13
14
|
puts "already exists: #{dest}" unless options[:quiet]
|
14
15
|
else
|
15
16
|
puts "creating: #{dest}" unless options[:quiet]
|
16
|
-
|
17
|
+
dirname = File.dirname(dest)
|
18
|
+
FileUtils.mkdir_p(dirname) unless File.exist?(dirname)
|
19
|
+
FileUtils.cp(src, dest)
|
17
20
|
end
|
18
21
|
end
|
22
|
+
puts "Starter lono project created"
|
19
23
|
end
|
20
24
|
def self.generate(options)
|
21
25
|
new(options).generate
|
@@ -23,11 +27,7 @@ module Lono
|
|
23
27
|
|
24
28
|
def initialize(options={})
|
25
29
|
@options = options
|
26
|
-
|
27
|
-
@dsl = DSL.new
|
28
|
-
else
|
29
|
-
@dsl = DSL.new(options)
|
30
|
-
end
|
30
|
+
@dsl = options.empty? ? DSL.new : DSL.new(options)
|
31
31
|
end
|
32
32
|
def generate
|
33
33
|
@dsl.run(@options)
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Lono
|
5
|
+
class Template
|
6
|
+
include ERB::Util
|
7
|
+
|
8
|
+
attr_reader :name
|
9
|
+
def initialize(name, block, options={})
|
10
|
+
@name = name
|
11
|
+
@block = block
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def build
|
16
|
+
instance_eval(&@block)
|
17
|
+
template = IO.read(@source)
|
18
|
+
ERB.new(template).result(binding)
|
19
|
+
end
|
20
|
+
|
21
|
+
def source(path)
|
22
|
+
@source = path[0..0] == '/' ? path : "#{@options[:project_root]}/templates/#{path}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def variables(vars={})
|
26
|
+
vars.each do |var,value|
|
27
|
+
instance_variable_set("@#{var}", value)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def partial(path)
|
32
|
+
path = "#{@options[:project_root]}/templates/partial/#{path}"
|
33
|
+
template = IO.read(path)
|
34
|
+
ERB.new(template).result(binding)
|
35
|
+
end
|
36
|
+
|
37
|
+
def user_data(path)
|
38
|
+
path = "#{@options[:project_root]}/templates/user_data/#{path}"
|
39
|
+
template = IO.read(path)
|
40
|
+
result = ERB.new(template).result(binding)
|
41
|
+
output = []
|
42
|
+
lines = result.split("\n")
|
43
|
+
lines.each do |line|
|
44
|
+
output += transform(line)
|
45
|
+
end
|
46
|
+
output.to_json
|
47
|
+
end
|
48
|
+
|
49
|
+
def ref(name)
|
50
|
+
%Q|{"Ref"=>"#{name}"}|
|
51
|
+
end
|
52
|
+
|
53
|
+
# transform each line of the bash script into a UserData compatiable with CF template.
|
54
|
+
# any {"Ref"=>"..."} string get turned into CF Hash elements
|
55
|
+
def transform(line)
|
56
|
+
regex = /({"Ref"=>".*?"})/
|
57
|
+
data = line.split(regex)
|
58
|
+
data.map! {|l| l.match(regex) ? eval(l) : l }
|
59
|
+
if data[-1].is_a?(String)
|
60
|
+
data[0..-2] + ["#{data[-1]}\n"]
|
61
|
+
else
|
62
|
+
data + ["\n"]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/lono/version.rb
CHANGED
File without changes
|
@@ -1,11 +1,12 @@
|
|
1
|
-
template "prod-
|
1
|
+
template "prod-blog-app.json" do
|
2
|
+
env,app,role = name.sub('.json','').split('-')
|
2
3
|
source "app.json.erb"
|
3
4
|
variables(
|
4
|
-
:env =>
|
5
|
-
:app =>
|
6
|
-
:role =>
|
5
|
+
:env => env,
|
6
|
+
:app => app,
|
7
|
+
:role => role,
|
7
8
|
:ami => "ami-456",
|
8
|
-
:instance_type => "m1.
|
9
|
+
:instance_type => "m1.small",
|
9
10
|
:port => "80",
|
10
11
|
:high_threshold => "35",
|
11
12
|
:high_periods => "4",
|
@@ -1,11 +1,12 @@
|
|
1
1
|
template "prod-api-app.json" do
|
2
|
+
env,app,role = name.sub('.json','').split('-')
|
2
3
|
source "app.json.erb"
|
3
4
|
variables(
|
4
|
-
:env =>
|
5
|
-
:app =>
|
6
|
-
:role =>
|
5
|
+
:env => env,
|
6
|
+
:app => app,
|
7
|
+
:role => role,
|
7
8
|
:ami => "ami-123",
|
8
|
-
:instance_type => "
|
9
|
+
:instance_type => "m1.small",
|
9
10
|
:port => "80",
|
10
11
|
:high_threshold => "15",
|
11
12
|
:high_periods => "4",
|
@@ -18,22 +19,18 @@ template "prod-api-app.json" do
|
|
18
19
|
:ssl_cert => "arn:aws:iam::12345:server-certificate/wildcard"
|
19
20
|
)
|
20
21
|
end
|
21
|
-
|
22
|
-
|
22
|
+
|
23
|
+
template "prod-api-redis.json" do
|
24
|
+
env,app,role = name.sub('.json','').split('-')
|
25
|
+
source "db.json.erb"
|
23
26
|
variables(
|
24
|
-
:env =>
|
25
|
-
:app =>
|
26
|
-
:role =>
|
27
|
+
:env => env,
|
28
|
+
:app => app,
|
29
|
+
:role => role,
|
27
30
|
:ami => "ami-456",
|
28
|
-
:instance_type => "m1.
|
31
|
+
:instance_type => "m1.small",
|
29
32
|
:port => "80",
|
30
|
-
:
|
31
|
-
:
|
32
|
-
:low_threshold => "20",
|
33
|
-
:low_periods => "2",
|
34
|
-
:max_size => "6",
|
35
|
-
:min_size => "3",
|
36
|
-
:down_adjustment => "-1",
|
37
|
-
:up_adjustment => "2"
|
33
|
+
:volume_size => "20",
|
34
|
+
:availability_zone => "us-east-1e"
|
38
35
|
)
|
39
36
|
end
|