lono 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -5,3 +5,4 @@ Gemfile.lock
5
5
  pkg
6
6
  tmp
7
7
  output
8
+ spec/project
data/Guardfile CHANGED
@@ -1,6 +1,6 @@
1
- # guard 'bundler' do
2
- # watch('Gemfile')
3
- # end
1
+ guard 'bundler' do
2
+ watch('Gemfile')
3
+ end
4
4
 
5
5
  guard 'rspec' do
6
6
  watch(%r{^spec/.+_spec\.rb$})
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 lono_project
15
- $ lono init
14
+ $ mkdir lono
15
+ $ cd lono
16
+ $ lono init
16
17
  </pre>
17
18
 
18
- This sets up the basic lono project with an example template in source/app.json.erb.
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/lono.rb.
25
+ This generates the templates that have been defined in config folder of the lono project.
25
26
 
26
- The example starter config/lono.rb looks like this:
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 => 'prod',
33
- :app => 'api',
34
- :role => "app",
34
+ :env => env,
35
+ :app => app,
36
+ :role => role,
35
37
  :ami => "ami-123",
36
- :instance_type => "c1.xlarge",
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 example ERB template file is in templates/app.json.erb.
53
+ The corresponding ERB template example file is [here](lib/starter_project/templates/app.json.erb).
54
+
55
+ ## Template helper methods
71
56
 
72
- ## User Data Helper
57
+ There are helper methods that available in templates.
73
58
 
74
- In the template files, there's user_data helper method available which can be used to include a user data script. The user data script should be in in the templates/user_data folder of the project. So:
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('bootstrap.sh.erb') -> templates/user_data/bootstrap.sh.erb
77
- * user_data('db.sh.erb') -> templates/user_data/db.sh.erb
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
- ## Breaking up config/lono.rb
78
+ Within a user_data script you can call another helper method called ref.
94
79
 
95
- 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.
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 spec/project folder:
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
@@ -4,4 +4,5 @@ $:.unshift File.dirname(__FILE__)
4
4
  require 'ext/hash'
5
5
  require 'lono/cli'
6
6
  require 'lono/task'
7
+ require 'lono/template'
7
8
  require 'lono/dsl'
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.dup.merge(:verbose => true))
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
- @path = options[:config_path] || 'config/lono.rb'
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(options={})
36
- output_path = options[:output_path] || 'output'
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:" if options[:verbose]
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}" if options[:verbose]
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
- options.empty? ? output : output(options)
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
- %w[Guardfile config/lono.rb templates/app.json.erb].each do |name|
7
- source = File.expand_path("../../files/#{name}", __FILE__)
8
- dirname = File.dirname(name)
9
- FileUtils.mkdir(dirname) unless File.exist?(dirname)
10
- dest = "#{project_root}/#{name}"
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
- FileUtils.cp(source, dest)
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
- if options.empty?
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
@@ -1,3 +1,3 @@
1
1
  module Lono
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
3
3
  end
File without changes
@@ -1,11 +1,12 @@
1
- template "prod-br-app.json" do
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 => "prod",
5
- :app => 'br',
6
- :role => "app",
5
+ :env => env,
6
+ :app => app,
7
+ :role => role,
7
8
  :ami => "ami-456",
8
- :instance_type => "m1.medium",
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 => 'prod',
5
- :app => 'api',
6
- :role => "app",
5
+ :env => env,
6
+ :app => app,
7
+ :role => role,
7
8
  :ami => "ami-123",
8
- :instance_type => "c1.xlarge",
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
- template "prod-br-app.json" do
22
- source "app.json.erb"
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 => "prod",
25
- :app => 'br',
26
- :role => "app",
27
+ :env => env,
28
+ :app => app,
29
+ :role => role,
27
30
  :ami => "ami-456",
28
- :instance_type => "m1.medium",
31
+ :instance_type => "m1.small",
29
32
  :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"
33
+ :volume_size => "20",
34
+ :availability_zone => "us-east-1e"
38
35
  )
39
36
  end