lono 0.5.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/CHANGELOG.md +5 -0
  4. data/README.md +152 -23
  5. data/lib/lono.rb +1 -0
  6. data/lib/lono/cli.rb +3 -2
  7. data/lib/lono/dsl.rb +59 -12
  8. data/lib/lono/new.rb +4 -2
  9. data/lib/lono/template.rb +22 -9
  10. data/lib/lono/version.rb +1 -1
  11. data/lib/{starter_project → starter_project_json}/Gemfile +2 -1
  12. data/lib/{starter_project → starter_project_json}/Guardfile +0 -0
  13. data/lib/starter_project_json/config/lono.rb +20 -0
  14. data/lib/{starter_project → starter_project_json}/config/lono/api.rb +9 -9
  15. data/lib/{starter_project → starter_project_json}/templates/db.json.erb +1 -1
  16. data/lib/{starter_project → starter_project_json}/templates/partial/host_record.json.erb +0 -0
  17. data/lib/{starter_project → starter_project_json}/templates/partial/server.json.erb +0 -0
  18. data/lib/{starter_project → starter_project_json}/templates/user_data/app.sh.erb +1 -4
  19. data/lib/{starter_project → starter_project_json}/templates/user_data/db.sh.erb +0 -0
  20. data/lib/{starter_project → starter_project_json}/templates/user_data/db2.sh.erb +0 -0
  21. data/lib/{starter_project → starter_project_json}/templates/user_data/ruby_script.rb.erb +0 -0
  22. data/lib/{starter_project/templates/app.json.erb → starter_project_json/templates/web.json.erb} +1 -1
  23. data/lib/starter_project_yaml/Gemfile +4 -0
  24. data/lib/starter_project_yaml/Guardfile +12 -0
  25. data/lib/{starter_project → starter_project_yaml}/config/lono.rb +5 -5
  26. data/lib/starter_project_yaml/config/lono/api.rb +58 -0
  27. data/lib/starter_project_yaml/templates/db.yml.erb +148 -0
  28. data/lib/starter_project_yaml/templates/partial/host_record.yml.erb +14 -0
  29. data/lib/starter_project_yaml/templates/partial/server.yml.erb +59 -0
  30. data/lib/starter_project_yaml/templates/partial/user_data/bootstrap.sh.erb +5 -0
  31. data/lib/starter_project_yaml/templates/web.yml.erb +205 -0
  32. data/lono.gemspec +1 -1
  33. data/spec/lib/lono/dsl_spec.rb +184 -0
  34. data/spec/lib/lono/new_spec.rb +59 -0
  35. data/spec/lib/lono_spec.rb +6 -116
  36. data/spec/spec_helper.rb +1 -0
  37. metadata +42 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 95168f2761fc2cc741be8c7bd629397cda724e63
4
- data.tar.gz: 4c1deb7dff498115fdaa348e139e9cab1368c9aa
3
+ metadata.gz: 6375e08e65be7c8a3a1eec9356454c1975a40400
4
+ data.tar.gz: 753b81d7bc5b3d1b5dd6fab7ed01858db6aeb7e0
5
5
  SHA512:
6
- metadata.gz: f374bb0ef8c7bad94927613cd0497a7029ec607273132aeaa6a4a8829ef8a888354fba66cb9135a3dea133089de647c9f86135deec7f2cc463f4b6e085d00bdd
7
- data.tar.gz: c1d292f6a35608743516b947ddd0763d98f07ed3554b91ab2b602bb9c9ec7609515efab2ced0c08c1a0a14d9ba55c1125d8939a631e3d6b26a03cb07c729978a
6
+ metadata.gz: c1e1f22813a7e5ab6444aafc53d21fc6dfec39b71ea2992d027e832429283a196360a4e9dabbc839b9b1d7e24800c322ffb49df9627662e6687e8c543008d2c7
7
+ data.tar.gz: 05f0f728a8e87110ee5641ce3f0da27ebbcb12719e3b619eccb2dc634b9df156536ebbccc1a95581be1f300280a291c3d332f23cc4bb3a2e3abb5e387926ff5a
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.3.1
1
+ 2.3.3
data/CHANGELOG.md CHANGED
@@ -3,6 +3,11 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
5
5
 
6
+ ## [1.0.0]
7
+ - Yaml support added! Makes for much more clean and concise templates. The `lono new` command defaults to yaml format.
8
+ - The starter project is app centric instead of env centric. Example: blog-web-prod vs prod-blog-web.
9
+
10
+
6
11
  ## [0.5.2]
7
12
  - Add helper encode_base64 method in case you want to base64 encode a string in the ERB template and you are using lono outside of the context of CloudFormation where you will not have access to the FN::Base64 Function.
8
13
 
data/README.md CHANGED
@@ -12,7 +12,7 @@
12
12
  [3]: https://codeclimate.com/repos/51d7f1407e00a4042c010ab4/badges/5273fe6cdb5a13e58554/gpa.png
13
13
  [4]: https://codeclimate.com/repos/51d7f1407e00a4042c010ab4/feed
14
14
 
15
- Lono is a CloudFormation Template ruby generator. Lono generates CloudFormation templates based on ERB templates.
15
+ Lono is a CloudFormation Template generator. Lono generates CloudFormation templates based on ERB ruby templates.
16
16
 
17
17
  ## Usage
18
18
 
@@ -27,14 +27,14 @@ $ cd infra
27
27
  $ lono generate
28
28
  </pre>
29
29
 
30
- This generates the templates that have been defined in the config folder of the lono project to the output folder.
30
+ This generates the templates in the `config` and `templates` folders to the `output` folder.
31
31
 
32
32
  The starter lono template project config files looks like [this](lib/starter_project/config/lono.rb) and [this](lib/starter_project/config/lono/api.rb). Here's a snippet from one of the config files with the template call:
33
33
 
34
34
  ```ruby
35
- template "prod-api-app.json" do
36
- env,app,role = name.sub('.json','').split('-')
37
- source "app.json.erb"
35
+ template "api-web-prod.yml" do
36
+ app,role,env = name.sub('.yml','').split('-')
37
+ source "web.yml.erb"
38
38
  variables(
39
39
  env: env,
40
40
  app: app,
@@ -55,20 +55,122 @@ template "prod-api-app.json" do
55
55
  end
56
56
  ```
57
57
 
58
- The corresponding ERB template example file is [here](lib/starter_project/templates/app.json.erb).
58
+ The corresponding ERB template looks like the following. Note that some of the output has been shorten for brevity.
59
+
60
+ ```yaml
61
+ <% @app,@role,@env = name.sub('.yml','').split('-') %>
62
+ ---
63
+ AWSTemplateFormatVersion: '2010-09-09'
64
+ Description: <%= @app.capitalize %> Stack
65
+ Mappings:
66
+ ...
67
+ Outputs:
68
+ ...
69
+ Parameters:
70
+ Application:
71
+ Default: <%= @app %>
72
+ Description: Application name
73
+ Type: String
74
+ ...
75
+ Resources:
76
+ CPUAlarmHigh:
77
+ Properties:
78
+ AlarmActions:
79
+ - Ref: WebServerScaleUpPolicy
80
+ AlarmDescription: Scale-up if CPU > <%= @high_threshold %>% for <%= @high_mins %>
81
+ ...
82
+ <%= partial("host_record.yml.erb", domain: "mydomain.com") %>
83
+ LaunchConfig:
84
+ Properties:
85
+ BlockDeviceMappings:
86
+ - DeviceName: "/dev/sdb"
87
+ VirtualName: ephemeral0
88
+ ImageId:
89
+ ...
90
+ UserData:
91
+ Fn::Base64: !Sub | # No more Fn::Join needed
92
+ #!/bin/bash -lexv
93
+ <% stack_name = "#{@env}-#{@app}-#{@role}" %>
94
+ exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
95
+ echo <%= stack_name %> > /tmp/stack_name
96
+ cat /proc/uptime | cut -f1 -d'.' > /tmp/time-to-boot
97
+ Type: AWS::AutoScaling::LaunchConfiguration
98
+
99
+ ```
100
+
101
+ The output looks like this:
102
+
103
+ ```yaml
104
+ ---
105
+ AWSTemplateFormatVersion: '2010-09-09'
106
+ Description: Api Stack
107
+ Mappings:
108
+ ...
109
+ Outputs:
110
+ ...
111
+ Parameters:
112
+ Application:
113
+ Default: api
114
+ Description: Application name
115
+ Type: String
116
+ ...
117
+ Resources:
118
+ CPUAlarmHigh:
119
+ Properties:
120
+ AlarmActions:
121
+ - Ref: WebServerScaleUpPolicy
122
+ AlarmDescription: Scale-up if CPU > 15% for
123
+ ...
124
+ HostRecord:
125
+ Properties:
126
+ Comment: DNS name for mydomain.com
127
+ HostedZoneName: ".mydomain.net."
128
+ Name:
129
+ Fn::Join:
130
+ - ''
131
+ - - Ref: AWS::StackName
132
+ - mydomain.com
133
+ ResourceRecords:
134
+ - Fn::GetAtt:
135
+ - elb
136
+ - DNSName
137
+ TTL: '60'
138
+ Type: CNAME
139
+ Type: AWS::Route53::RecordSet
140
+ LaunchConfig:
141
+ Properties:
142
+ BlockDeviceMappings:
143
+ - DeviceName: "/dev/sdb"
144
+ VirtualName: ephemeral0
145
+ ImageId:
146
+ ...
147
+ UserData:
148
+ Fn::Base64: |
149
+ #!/bin/bash -lexv
150
+
151
+ exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
152
+ echo api-web-prod > /tmp/stack_name
153
+ cat /proc/uptime | cut -f1 -d'.' > /tmp/time-to-boot
154
+ Type: AWS::AutoScaling::LaunchConfiguration
155
+ ```
59
156
 
60
157
  ## Template helper methods
61
158
 
62
159
  There are helper methods that are available in templates.
63
160
 
64
- * 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:
65
- * partial('launch_config.json.erb') -> templates/partial/launch_config.json.erb
66
- * partial('launch_config.json.erb', foo: "bar", hello: "world") - variables can be passed to the partial helper method and will be available to the partial as instance variables. So, in this case @foo and @hello will be available in the launch_config.json.erb partial.
161
+ * partial(relative_path, variables, options) - can be use to embed other files in a template. The partial view should be placed in the `templates/partial` folder of the project. So:
162
+ * partial('launch\_config.json.erb') -> `templates/partial/launch_config.json.erb`
163
+ * partial('launch\_config.json.erb', foo: "bar", hello: "world") - variables can be passed to the partial helper method are available to the partial as instance variables. So, in this case `@foo` and `@hello` will be available in the `launch_config.json.erb` partial.
164
+ * partial('user_data/bootstrap.sh.erb', {}, indent: 10) - Indent the result partial by 10 spaces. Useful for yaml format.
165
+
166
+ ## user\_data helper for json format
167
+
168
+ The user\_data helper method is helpful for writting a script in bash form and having lono convert it to a json compatiable format. It is only really useful if you are using json as the CloudFormation format. If you are using yaml as the format, which is recommended, then you should simply use raw yaml.
67
169
 
68
- * 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:
69
- * user_data('bootstrap.sh.erb') -> templates/user_data/bootstrap.sh.erb
70
- * user_data('db.sh.erb') -> templates/user_data/db.sh.erb
71
- * user_data('script1.sh.erb', foo: "bar", hello: "world") - variables can be passed to the user_data helper method and will be available to the partial as instance variables. So, in this case @foo and @hello will be available in script1.sh.erb.
170
+ * 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:
171
+ * user\_data('bootstrap.sh.erb') -> templates/user\_data/bootstrap.sh.erb
172
+ * user\_data('db.sh.erb') -> templates/user\_data/db.sh.erb
173
+ * user\_data('script1.sh.erb', foo: "bar", hello: "world") - variables can be passed to the user\_data helper method and will be available to the partial as instance variables. So, in this case `@foo` and `@hello` will be available in `script1.sh.erb`.
72
174
 
73
175
  Here's how you would call it in the template.
74
176
 
@@ -84,9 +186,9 @@ Here's how you would call it in the template.
84
186
  }
85
187
  ```
86
188
 
87
- Within the user_data script you can use helper methods that correspond to CloudFormation [Instrinic Functions](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/concept-intrinsic-functions.html). Currently, base64, find_in_map, get_att, get_azs, join, and ref are supported. Here's a short example of a user_data script using a helper method:
189
+ Within the user\_data script you can use helper methods that correspond to CloudFormation [Instrinic Functions](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/concept-intrinsic-functions.html). Currently, `base64`, `find_in_map`, `get_att`, `get_azs`, `join`, and `ref` are supported. Here's a short example of a user\_data script using a helper method:
88
190
 
89
- If you have a templates/user_data/db.sh.erb that looks like this:
191
+ If you have a `templates/user_data/db.sh.erb` that looks like this:
90
192
 
91
193
  ```bash
92
194
  #!/bin/bash -lexv
@@ -118,7 +220,7 @@ chown -R redis:redis /media/redis
118
220
  /usr/local/bin/cfn-signal -e $? -r "Ready to rock" '<%= ref("WaitHandle") %>'
119
221
  ```
120
222
 
121
- The user_data helper will transform the bash script into a json array of elements for CloudFormation:
223
+ The user\_data helper will transform the bash script into a json array of elements for CloudFormation:
122
224
 
123
225
  ```json
124
226
  [
@@ -174,7 +276,7 @@ The user_data helper will transform the bash script into a json array of element
174
276
  ]
175
277
  ```
176
278
 
177
- More examples of user_data and instrinic function helper method usage are found in the starter [project template](https://github.com/tongueroo/lono/blob/master/lib/starter_project/templates/user_data/db.sh.erb)
279
+ More examples of user\_data and instrinic function helper method usage are found in the starter [project template](https://github.com/tongueroo/lono/blob/master/lib/starter_project_json/templates/user_data/db.sh.erb)
178
280
 
179
281
  ## Converting UserData scripts
180
282
 
@@ -186,11 +288,11 @@ $ lono bash cloud_formation_template.json # shorthand
186
288
  $ lono b https://s3.amazonaws.com/cloudformation-templates-us-east-1/LAMP_Single_Instance.template # shorthand and url
187
289
  </pre>
188
290
 
189
- This is useful if you want to take an existing [CloudFormation Template example](http://aws.amazon.com/cloudformation/aws-cloudformation-templates/) and quicklly change the UserData section into a bash script. The bashify command will generate a snippet that is meant to be copied and pasted into a bash script and used with user_data helper method. The bash script should work right off the bat as lono will transform the generated CloudFormation object references to json objects, there's no need to manually change what is generated to the helper methods, though you can if you prefer the look of the helper methods.
291
+ This is useful if you want to take an existing json [CloudFormation Template example](http://aws.amazon.com/cloudformation/aws-cloudformation-templates/) and quicklly change the UserData section into a bash script. The bashify command will generate a snippet that is meant to be copied and pasted into a bash script and used with user\_data helper method. The bash script should work right off the bat as lono will transform the generated CloudFormation object references to json objects, there's no need to manually change what is generated to the helper methods, though you can if you prefer the look of the helper methods.
190
292
 
191
293
  ## Breaking up config/lono.rb
192
294
 
193
- 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.
295
+ 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_yaml/config/lono/api.rb) is in the starter project.
194
296
 
195
297
 
196
298
  ## Generate
@@ -208,10 +310,37 @@ The lono init command also sets up guard-lono. Guard-lono continuously generate
208
310
  $ guard
209
311
  </pre>
210
312
 
211
- ## Extras
313
+ ## lono-cfn and lono-params
212
314
 
213
- There are some helper lono gems also useful for working with CloudFormation:
315
+ Running `lono generate` and building up the `aws cloudformation create-stack` command repeatedly gets old. The `lono-cfn` tool will automatically run `lono generate` and then launch the CloudFormation stack all in one command. Example usage:
214
316
 
215
- * [lono-cfn](https://github.com/tongueroo/lono-cfn) - Wrapper cfn tool to quickly create CloudFormation stacks from lono templates and params files.
216
- * [lono-params](https://github.com/tongueroo/lono-params) - Tool to generate a CloudFormation params json formatted file from a simplier env like file.
317
+ ```
318
+ $ lono-cfn create mystack-$(date +%Y%m%d%H%M%S) --template mystack --params mystack
319
+ $ lono-cfn create mystack-$(date +%Y%m%d%H%M%S) # shorthand if template and params file matches.
320
+ ```
321
+
322
+ More info about lono-cfn here: [lono-cfn](https://github.com/tongueroo/lono-cfn) - Wrapper cfn tool to quickly create CloudFormation stacks from lono templates and params files.
323
+
324
+ The params file is formatted with a simple `key=value`, env-like file. It is cleaner to have a `params/mystack.txt` file like so:
325
+
326
+ ```bash
327
+ Param1=1
328
+ Param2=2
329
+ ```
330
+
331
+ Verus the rather verbose standard CloudFormation parameters json file:
332
+
333
+ ```json
334
+ [
335
+ {
336
+ "ParameterKey": "Param1",
337
+ "ParameterValue": "1"
338
+ },
339
+ {
340
+ "ParameterKey": "Param2",
341
+ "ParameterValue": "2"
342
+ }
343
+ ]
344
+ ```
217
345
 
346
+ More info about lono-parmas here: [lono-params](https://github.com/tongueroo/lono-params) - Tool to generate a CloudFormation parameters json formatted file from a simplier env like file.
data/lib/lono.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'json'
2
+ require 'yaml'
2
3
  require 'pp'
3
4
  require 'colorize'
4
5
  require 'fileutils'
data/lib/lono/cli.rb CHANGED
@@ -8,6 +8,7 @@ module Lono
8
8
  Help.new_long_desc
9
9
  option :force, type: :boolean, aliases: "-f", desc: "override existing starter files"
10
10
  option :quiet, type: :boolean, aliases: "-q", desc: "silence the output"
11
+ option :format, type: :string, default: "yaml", desc: "starter project template format: json or yaml"
11
12
  def new(project_root)
12
13
  Lono::New.new(options.clone.merge(project_root: project_root)).run
13
14
  end
@@ -17,7 +18,7 @@ module Lono
17
18
  option :clean, type: :boolean, aliases: "-c", desc: "remove all output files before generating"
18
19
  option :project_root, default: ".", aliases: "-r", desc: "project root"
19
20
  option :quiet, type: :boolean, aliases: "-q", desc: "silence the output"
20
- option :pretty, type: :boolean, default: true, desc: "json pretty the output"
21
+ option :pretty, type: :boolean, default: true, desc: "json pretty the output. only applies with json format"
21
22
  def generate
22
23
  Lono::DSL.new(options.clone).run
23
24
  end
@@ -33,5 +34,5 @@ module Lono
33
34
  puts Lono::VERSION
34
35
  end
35
36
 
36
- end
37
+ end
37
38
  end
data/lib/lono/dsl.rb CHANGED
@@ -6,11 +6,38 @@ module Lono
6
6
  @path = "#{@options[:project_root]}/config/lono.rb"
7
7
  @templates = []
8
8
  @results = {}
9
+ @detected_format = nil
10
+ end
11
+
12
+ def run(options={})
13
+ evaluate
14
+ build
15
+ output
9
16
  end
10
17
 
11
18
  def evaluate
12
19
  instance_eval(File.read(@path), @path)
13
20
  load_subfolder
21
+ @detected_format = detect_format
22
+ end
23
+
24
+ # Detects the format of the templates. Simply checks the extension of all the
25
+ # templates files.
26
+ # All the templates must be of the same format, either all json or all yaml.
27
+ def detect_format
28
+ # @templates contains Array of Hashes. Example:
29
+ # [{name: ""blog-web-prod.json", block: ...},
30
+ # {name: ""api-web-prod.json", block: ...}]
31
+ formats = @templates.map{ |t| File.extname(t[:name]) }.uniq
32
+ if formats.size > 1
33
+ puts "ERROR: Detected multiple formats: #{formats.join(", ")}".colorize(:red)
34
+ puts "All the source values in the template blocks in the config folder must have the same format extension."
35
+ exit 1
36
+ else
37
+ detected_format = formats.first.sub(/^\./,'')
38
+ detected_format = "yaml" if detected_format == "yml"
39
+ end
40
+ detected_format
14
41
  end
15
42
 
16
43
  # load any templates defined in project/config/lono/*
@@ -35,40 +62,60 @@ module Lono
35
62
  FileUtils.rm_rf(output_path) if @options[:clean]
36
63
  FileUtils.mkdir(output_path) unless File.exist?(output_path)
37
64
  puts "Generating CloudFormation templates:" unless @options[:quiet]
38
- @results.each do |name,json|
65
+ @results.each do |name,text|
39
66
  path = "#{output_path}/#{name}"
40
67
  puts " #{path}" unless @options[:quiet]
41
68
  ensure_parent_dir(path)
42
- validate(json, path)
69
+ validate(text, path)
43
70
  File.open(path, 'w') do |f|
44
- f.write(output_json(json))
71
+ f.write(output_format(text))
45
72
  end
46
73
  end
47
74
  end
48
75
 
49
- def validate(json, path)
76
+ # TODO: set @detected_format upon DSL.new
77
+ def validate(text, path)
78
+ if @detected_format == "json"
79
+ validate_json(text, path)
80
+ else
81
+ validate_yaml(text, path)
82
+ end
83
+ end
84
+
85
+ def validate_yaml(yaml, path)
86
+ begin
87
+ YAML.load(yaml)
88
+ rescue Psych::SyntaxError => e
89
+ puts "Invalid yaml. Output written to #{path} for debugging".colorize(:red)
90
+ puts "ERROR: #{e.message}".colorize(:red)
91
+ File.open(path, 'w') {|f| f.write(yaml) }
92
+ exit 1
93
+ end
94
+ end
95
+
96
+ def validate_json(json, path)
50
97
  begin
51
98
  JSON.parse(json)
52
99
  rescue JSON::ParserError => e
53
100
  puts "Invalid json. Output written to #{path} for debugging".colorize(:red)
101
+ puts "ERROR: #{e.message}".colorize(:red)
54
102
  File.open(path, 'w') {|f| f.write(json) }
55
103
  exit 1
56
104
  end
57
105
  end
58
106
 
59
- def output_json(json)
60
- @options[:pretty] ? JSON.pretty_generate(JSON.parse(json)) : json
107
+ def output_format(text)
108
+ @options[:pretty] ? prettify(text) : text
109
+ end
110
+
111
+ # do not prettify yaml format because it removes the !Ref like CloudFormation notation
112
+ def prettify(text)
113
+ @detected_format == "json" ? JSON.pretty_generate(JSON.parse(text)) : text
61
114
  end
62
115
 
63
116
  def ensure_parent_dir(path)
64
117
  dir = File.dirname(path)
65
118
  FileUtils.mkdir_p(dir) unless File.exist?(dir)
66
119
  end
67
-
68
- def run(options={})
69
- evaluate
70
- build
71
- output
72
- end
73
120
  end
74
121
  end
data/lib/lono/new.rb CHANGED
@@ -4,15 +4,17 @@ module Lono
4
4
  def initialize(options)
5
5
  @options = options
6
6
  @project_root = options[:project_root] || '.'
7
+ @format = options[:format] || 'json'
7
8
  end
8
9
 
9
10
  def run
10
11
  puts "Setting up lono project" unless options[:quiet]
11
- source_root = File.expand_path("../../starter_project", __FILE__)
12
+ source_root = File.expand_path("../../starter_project_#{@format}", __FILE__)
12
13
  paths = Dir.glob("#{source_root}/**/*").
13
14
  select {|p| File.file?(p) }
14
15
  paths.each do |src|
15
- dest = src.gsub(%r{.*starter_project/},'')
16
+ regexp = Regexp.new(".*starter_project_#{@format}/")
17
+ dest = src.gsub(regexp,'')
16
18
  dest = "#{@project_root}/#{dest}"
17
19
 
18
20
  if File.exist?(dest) and !options[:force]
data/lib/lono/template.rb CHANGED
@@ -16,7 +16,7 @@ module Lono
16
16
  def build
17
17
  instance_eval(&@block)
18
18
  template = IO.read(@source)
19
- ERB.new(template).result(binding)
19
+ erb_result(template)
20
20
  end
21
21
 
22
22
  def source(path)
@@ -29,18 +29,31 @@ module Lono
29
29
  end
30
30
  end
31
31
 
32
- def partial(path,vars={})
32
+ def partial(path,vars={}, options={})
33
33
  path = "#{@options[:project_root]}/templates/partial/#{path}"
34
34
  template = IO.read(path)
35
35
  variables(vars)
36
- ERB.new(template).result(binding)
36
+ result = erb_result(template)
37
+ result = indent(result, options[:indent]) if options[:indent]
38
+ result
39
+ end
40
+
41
+ # add indentation
42
+ def indent(result, indentation_amount)
43
+ result.split("\n").map do |line|
44
+ " " * indentation_amount + line
45
+ end.join("\n")
46
+ end
47
+
48
+ def erb_result(template)
49
+ ERB.new(template, nil, "-").result(binding)
37
50
  end
38
51
 
39
52
  def user_data(path, vars={})
40
53
  path = "#{@options[:project_root]}/templates/user_data/#{path}"
41
54
  template = IO.read(path)
42
55
  variables(vars)
43
- result = ERB.new(template).result(binding)
56
+ result = erb_result(template)
44
57
  output = []
45
58
  result.split("\n").each do |line|
46
59
  output += transform(line)
@@ -87,7 +100,7 @@ module Lono
87
100
  def transform(data)
88
101
  data = evaluate(data)
89
102
  if data[-1].is_a?(String)
90
- data[0..-2] + ["#{data[-1]}\n"]
103
+ data[0..-2] + ["#{data[-1]}\n"]
91
104
  else
92
105
  data + ["\n"]
93
106
  end
@@ -98,7 +111,7 @@ module Lono
98
111
  # Output:
99
112
  # Array of parse positions
100
113
  #
101
- # The positions of tokens taking into account when brackets start and close,
114
+ # The positions of tokens taking into account when brackets start and close,
102
115
  # handles nested brackets.
103
116
  def bracket_positions(line)
104
117
  positions,pair,count = [],[],0
@@ -106,7 +119,7 @@ module Lono
106
119
  line.split('').each_with_index do |char,i|
107
120
  pair << i if pair.empty?
108
121
 
109
- first_pair_char = line[pair[0]]
122
+ first_pair_char = line[pair[0]]
110
123
  if first_pair_char == '{' # object logic
111
124
  if char == '{'
112
125
  count += 1
@@ -203,8 +216,8 @@ module Lono
203
216
  recompose(decompose(line))
204
217
  end
205
218
 
206
- # For simple just parameters files that can also be generated with lono, the CFN
207
- # Fn::Base64 function is not available and as lono is not being used in the context
219
+ # For simple just parameters files that can also be generated with lono, the CFN
220
+ # Fn::Base64 function is not available and as lono is not being used in the context
208
221
  # of CloudFormation. So this can be used in it's place.
209
222
  def encode_base64(text)
210
223
  Base64.strict_encode64(text).strip