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 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