lono 1.1.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitmodules +3 -0
- data/CHANGELOG.md +8 -0
- data/README.md +150 -39
- data/bin/lono +2 -2
- data/circle.yml +4 -0
- data/lib/lono.rb +16 -7
- data/lib/lono/cfn.rb +64 -0
- data/lib/lono/cfn/aws_services.rb +37 -0
- data/lib/lono/cfn/base.rb +144 -0
- data/lib/lono/cfn/create.rb +34 -0
- data/lib/lono/cfn/delete.rb +26 -0
- data/lib/lono/cfn/diff.rb +43 -0
- data/lib/lono/cfn/help.rb +93 -0
- data/lib/lono/cfn/preview.rb +133 -0
- data/lib/lono/cfn/update.rb +62 -0
- data/lib/lono/cfn/util.rb +21 -0
- data/lib/lono/cli.rb +19 -10
- data/lib/lono/command.rb +25 -0
- data/lib/lono/help.rb +59 -0
- data/lib/lono/new.rb +3 -2
- data/lib/lono/param.rb +20 -0
- data/lib/lono/param/generator.rb +90 -0
- data/lib/lono/param/help.rb +15 -0
- data/lib/lono/project_checker.rb +44 -0
- data/lib/lono/template.rb +22 -248
- data/lib/lono/template/bashify.rb +39 -0
- data/lib/lono/template/dsl.rb +139 -0
- data/lib/lono/template/help.rb +25 -0
- data/lib/lono/template/template.rb +251 -0
- data/lib/lono/version.rb +1 -1
- data/lib/{starter_project_yaml → starter_projects/json_project}/Gemfile +0 -1
- data/lib/{starter_project_json → starter_projects/json_project}/Guardfile +0 -0
- data/lib/{starter_project_json → starter_projects/json_project}/config/lono.rb +0 -0
- data/lib/{starter_project_json → starter_projects/json_project}/config/lono/api.rb +0 -0
- data/lib/starter_projects/json_project/params/api-web-prod.txt +20 -0
- data/lib/{starter_project_json → starter_projects/json_project}/templates/db.json.erb +0 -0
- data/lib/{starter_project_json → starter_projects/json_project}/templates/partial/host_record.json.erb +0 -0
- data/lib/{starter_project_json → starter_projects/json_project}/templates/partial/server.json.erb +0 -0
- data/lib/{starter_project_json → starter_projects/json_project}/templates/user_data/app.sh.erb +0 -0
- data/lib/{starter_project_json → starter_projects/json_project}/templates/user_data/db.sh.erb +0 -0
- data/lib/{starter_project_json → starter_projects/json_project}/templates/user_data/db2.sh.erb +0 -0
- data/lib/{starter_project_json → starter_projects/json_project}/templates/user_data/ruby_script.rb.erb +0 -0
- data/lib/{starter_project_json → starter_projects/json_project}/templates/web.json.erb +0 -0
- data/lib/{starter_project_json → starter_projects/yaml_project}/Gemfile +0 -1
- data/lib/{starter_project_yaml → starter_projects/yaml_project}/Guardfile +0 -0
- data/lib/{starter_project_yaml → starter_projects/yaml_project}/config/lono.rb +0 -0
- data/lib/{starter_project_yaml → starter_projects/yaml_project}/config/lono/api.rb +0 -0
- data/lib/starter_projects/yaml_project/params/api-web-prod.txt +20 -0
- data/lib/{starter_project_yaml → starter_projects/yaml_project}/templates/db.yml.erb +0 -0
- data/lib/{starter_project_yaml → starter_projects/yaml_project}/templates/partial/host_record.yml.erb +0 -0
- data/lib/{starter_project_yaml → starter_projects/yaml_project}/templates/partial/server.yml.erb +0 -0
- data/lib/{starter_project_yaml → starter_projects/yaml_project}/templates/partial/user_data/bootstrap.sh.erb +0 -0
- data/lib/{starter_project_yaml → starter_projects/yaml_project}/templates/web.yml.erb +0 -0
- data/lono.gemspec +15 -10
- data/spec/fixtures/my_project/config/lono.rb +1 -0
- data/spec/fixtures/my_project/params/my-stack.txt +3 -0
- data/spec/fixtures/my_project/templates/.gitkeep +0 -0
- data/spec/fixtures/my_project/templates/my-stack.yml.erb +0 -0
- data/spec/lib/lono/cfn_spec.rb +35 -0
- data/spec/lib/lono/new_spec.rb +3 -3
- data/spec/lib/lono/param_spec.rb +15 -0
- data/spec/lib/lono/{dsl_spec.rb → template/dsl_spec.rb} +9 -9
- data/spec/lib/lono/template/template_spec.rb +104 -0
- data/spec/lib/lono/template_spec.rb +22 -37
- data/spec/lib/lono_spec.rb +6 -83
- data/vendor/plissken/Gemfile +14 -0
- data/vendor/plissken/LICENSE.txt +20 -0
- data/vendor/plissken/README.md +46 -0
- data/vendor/plissken/Rakefile +56 -0
- data/vendor/plissken/VERSION +1 -0
- data/vendor/plissken/lib/plissken.rb +1 -0
- data/vendor/plissken/lib/plissken/ext/hash/to_snake_keys.rb +45 -0
- data/vendor/plissken/plissken.gemspec +61 -0
- data/vendor/plissken/spec/lib/to_snake_keys_spec.rb +177 -0
- data/vendor/plissken/spec/spec_helper.rb +90 -0
- data/vendor/plissken/test/helper.rb +20 -0
- data/vendor/plissken/test/plissken/ext/hash/to_snake_keys_test.rb +184 -0
- data/vendor/plissken/test/test_plissken.rb +2 -0
- metadata +115 -39
- data/lib/lono/bashify.rb +0 -41
- data/lib/lono/cli/help.rb +0 -37
- data/lib/lono/dsl.rb +0 -132
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 380e874615eea57c1cc0788f77aef520d453e8c1
|
4
|
+
data.tar.gz: fb70edb0ff4a31521f6df6d3085fdde5fd47014d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c529da1117901155fe7ddc3033d779611370d3654ad01e76e5c5364a917f956911501d4014228166e22386457f3d2a2dbfa335ba9272eb1ef63ef0b85934dc4a
|
7
|
+
data.tar.gz: c31a6c825e2c42a1828d333fc22034c9605566c2cd6433104df21df25be0ea17e7990d555e55bb97ce07ecace12c119e8262153c12bf636b6e1c85df7bd74cd4
|
data/.gitmodules
ADDED
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,14 @@
|
|
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
|
+
## [2.0.0]
|
7
|
+
- added lono cfn subcommand to launch CloudFormation stacks
|
8
|
+
- added lono params subcommand to generate CloudFormation parameter files
|
9
|
+
- moved lono template methods into subcommand. lono generate still available at top level.
|
10
|
+
|
11
|
+
## [1.1.4]
|
12
|
+
- allow --help or -h at the end of the command
|
13
|
+
|
6
14
|
## [1.1.3]
|
7
15
|
- make display output path prettier
|
8
16
|
|
data/README.md
CHANGED
@@ -2,30 +2,27 @@
|
|
2
2
|
|
3
3
|
[![ReadmeCI](http://www.readmeci.com/images/readmeci-badge.svg)](http://www.readmeci.com/tongueroo/lono)
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/lono.png)](http://badge.fury.io/rb/lono)
|
5
|
-
[![
|
5
|
+
[![CircleCI](https://circleci.com/gh/tongueroo/lono.svg?style=svg)](https://circleci.com/gh/tongueroo/lono)
|
6
6
|
[![Code Climate][3]][4]
|
7
7
|
[![Dependency Status](https://gemnasium.com/tongueroo/lono.png)](https://gemnasium.com/tongueroo/lono)
|
8
8
|
[![Coverage Status](https://coveralls.io/repos/tongueroo/lono/badge.png)](https://coveralls.io/r/tongueroo/lono)
|
9
9
|
|
10
|
-
[1]: http://travis-ci.org/tongueroo/lono
|
11
|
-
[2]: https://secure.travis-ci.org/tongueroo/lono.png?branch=master
|
12
10
|
[3]: https://codeclimate.com/repos/51d7f1407e00a4042c010ab4/badges/5273fe6cdb5a13e58554/gpa.png
|
13
11
|
[4]: https://codeclimate.com/repos/51d7f1407e00a4042c010ab4/feed
|
14
12
|
|
15
|
-
Lono is a
|
13
|
+
Lono is a tool for managing CloudFormation templates.
|
16
14
|
|
17
|
-
|
15
|
+
* Lono generates CloudFormation templates based on ERB ruby templates in either `yaml` or `json` format.
|
16
|
+
* Lono takes simple env-like files to and generates the CloudFormation parameter files.
|
17
|
+
* Lono wraps the CloudFormation api calls in a simple interface using the generated files to launch the CloudFormation stacks.
|
18
|
+
|
19
|
+
These blog posts lono:
|
18
20
|
|
19
21
|
* [Why Generate CloudFormation Templates with Lono](https://medium.com/boltops/why-generate-cloudformation-templates-with-lono-65b8ea5eb87d)
|
20
22
|
* [Generating CloudFormation Templates with Lono](https://medium.com/boltops/generating-cloudformation-templates-with-lono-4709afa1299b)
|
21
23
|
* [AutoScaling CloudFormation Template with Lono](https://medium.com/boltops/autoscaling-cloudformation-template-with-lono-3dc520480c5f)
|
22
|
-
* [CloudFormation Tools: lono, lono-params and lono
|
23
|
-
](https://medium.com/boltops/cloudformation-
|
24
|
-
* [AWS CloudFormation dry-run with lono-cfn plan](https://medium.com/boltops/aws-cloudformation-dry-run-with-lono-cfn-plan-2a1e0f80d13c)
|
25
|
-
|
26
|
-
**UPDATE**: lono now supports yaml format for CloudFormation! The old json format is still supported. For current projects, you do not have to change anything as the format is autodetected as part of `lono generate`.
|
27
|
-
|
28
|
-
Newly generated projects with `lono new infra` will use the yaml format by default. If you prefer the json format use `lono new --format json infra`. You cannot mix and match json and yaml format in one project, it's either all json or yaml. If any one has questions feel free to ping me: tongueroo@gmail.com.
|
24
|
+
* [CloudFormation Tools: lono, lono-params and lono cfn Together](https://medium.com/boltops/cloudformation-tools-lono-lono-params-and-lono-cfn-play-together-620af51e616)
|
25
|
+
* [AWS CloudFormation dry-run with lono cfn preview](https://medium.com/boltops/aws-cloudformation-dry-run-with-lono-cfn-plan-2a1e0f80d13c)
|
29
26
|
|
30
27
|
## Usage
|
31
28
|
|
@@ -33,14 +30,18 @@ Newly generated projects with `lono new infra` will use the yaml format by defau
|
|
33
30
|
$ lono new infra
|
34
31
|
</pre>
|
35
32
|
|
36
|
-
This sets up a starter lono project called infra with example templates. Next you cd into the folder and generate the
|
33
|
+
This sets up a starter lono project called infra with example templates. Next you cd into the folder and generate the template and parameter files.
|
37
34
|
|
38
35
|
<pre>
|
39
36
|
$ cd infra
|
40
37
|
$ lono generate
|
41
38
|
</pre>
|
42
39
|
|
43
|
-
This
|
40
|
+
This CloudFormation template and parameter files are now available under `output` and `output/params`.
|
41
|
+
|
42
|
+
### Generate Template Files
|
43
|
+
|
44
|
+
The CloudFormation templates files that were generated from the `config` and `templates` folders and written to the `output` folder.
|
44
45
|
|
45
46
|
The starter lono template project config files looks like [this](lib/starter_project_yaml/config/lono.rb) and [this](lib/starter_project_yaml/config/lono/api.rb). Here's a snippet from one of the config files: [config/lono.rb](lib/starter_project_yaml/config/lono.rb).
|
46
47
|
|
@@ -171,6 +172,31 @@ You can use the generated CloudFormation templates in the `output` folder just a
|
|
171
172
|
|
172
173
|
![Lono flowchart](http://tongueroo.com/images/github-readmes/lono-flowchart.png "Lono flowchart")
|
173
174
|
|
175
|
+
### Generate Parameter Files
|
176
|
+
|
177
|
+
With lono you write simpler params file that is formatted with a simple `key=value` env-like file. The `params/mystack.txt` is shorter format versus the verbose standard CloudFormation parameters json file. Here is an example of a simple `params/mystack.txt` param file.
|
178
|
+
|
179
|
+
```bash
|
180
|
+
Param1=1
|
181
|
+
Param2=2
|
182
|
+
```
|
183
|
+
|
184
|
+
The `lono generate` command generates the CloudFormation parameter file in `output/params/mystack.json` which looks like this:
|
185
|
+
|
186
|
+
|
187
|
+
```json
|
188
|
+
[
|
189
|
+
{
|
190
|
+
"ParameterKey": "Param1",
|
191
|
+
"ParameterValue": "1"
|
192
|
+
},
|
193
|
+
{
|
194
|
+
"ParameterKey": "Param2",
|
195
|
+
"ParameterValue": "2"
|
196
|
+
}
|
197
|
+
]
|
198
|
+
```
|
199
|
+
|
174
200
|
## Template helper methods
|
175
201
|
|
176
202
|
There are helper methods that are available in templates.
|
@@ -189,7 +215,7 @@ If you have a lot of templates, the config/lono.rb file can get unwieldy long.
|
|
189
215
|
|
190
216
|
## Generate
|
191
217
|
|
192
|
-
You can generate the
|
218
|
+
You can generate the CloudFormation templates by running:
|
193
219
|
|
194
220
|
<pre>
|
195
221
|
$ lono generate
|
@@ -202,39 +228,124 @@ The lono init command also sets up guard-lono. Guard-lono continuously generate
|
|
202
228
|
$ guard
|
203
229
|
</pre>
|
204
230
|
|
205
|
-
|
231
|
+
# lono cfn
|
206
232
|
|
207
|
-
|
233
|
+
## Summary
|
234
|
+
Lono also provides a `lono cfn` wrapper command that allows you to launch stacks from the lono templates. The `lono cfn` tool automatically runs `lono generate` internally and then launches the CloudFormation stack all in one command. Provided that you are in a lono project and have a `my-stack` lono template definition. To create a stack you can simply run:
|
208
235
|
|
209
236
|
```
|
210
|
-
$ lono
|
211
|
-
$ lono-cfn create mystack-$(date +%Y%m%d%H%M%S) # shorthand if template and params file matches.
|
212
|
-
$ lono-cfn update mystack-1493859659
|
213
|
-
$ lono-cfn delete mystack-1493859659
|
237
|
+
$ lono cfn create my-stack
|
214
238
|
```
|
215
239
|
|
216
|
-
|
240
|
+
The above command will generate files to `output/my-stack.json` and `output/params/my-stack.txt` and use them to create a CloudFormation stack. Here are some more examples of cfn commands:
|
217
241
|
|
218
|
-
|
242
|
+
```
|
243
|
+
$ lono cfn create mystack-$(date +%Y%m%d%H%M%S) --template mystack --params mystack
|
244
|
+
$ lono cfn create mystack-$(date +%Y%m%d%H%M%S) # shorthand if template and params file matches.
|
245
|
+
$ lono cfn diff mystack-1493859659
|
246
|
+
$ lono cfn preview mystack-1493859659
|
247
|
+
$ lono cfn update mystack-1493859659
|
248
|
+
$ lono cfn delete mystack-1493859659
|
249
|
+
$ lono cfn create -h # getting help
|
250
|
+
```
|
219
251
|
|
220
|
-
|
221
|
-
|
222
|
-
|
252
|
+
### Conventions
|
253
|
+
|
254
|
+
The template by convention defaults to the name of the stack. In turn, the params by convention defaults to the name of the template.
|
255
|
+
|
256
|
+
* stack - This is a required parameter and is the CLI first parameter.
|
257
|
+
* template - By convention matches the stack name but can be overriden with `--template`.
|
258
|
+
* params - By convention matches the template name but can be overriden with `--params`.
|
259
|
+
|
260
|
+
The conventions allows the command to be a very nice short command that can be easily remembered. For example, these 2 commands are the same:
|
261
|
+
|
262
|
+
### lono cfn create
|
263
|
+
|
264
|
+
Long form:
|
265
|
+
|
266
|
+
```
|
267
|
+
$ lono cfn create my-stack --template my-stack --params --my-stack
|
223
268
|
```
|
224
269
|
|
225
|
-
|
270
|
+
Short form:
|
226
271
|
|
227
|
-
```json
|
228
|
-
[
|
229
|
-
{
|
230
|
-
"ParameterKey": "Param1",
|
231
|
-
"ParameterValue": "1"
|
232
|
-
},
|
233
|
-
{
|
234
|
-
"ParameterKey": "Param2",
|
235
|
-
"ParameterValue": "2"
|
236
|
-
}
|
237
|
-
]
|
238
272
|
```
|
273
|
+
$ lono cfn create my-stack
|
274
|
+
```
|
275
|
+
|
276
|
+
|
277
|
+
Both template and params conventions can be overridden. Here are examples of overriding the template and params name conventions.
|
278
|
+
|
279
|
+
```
|
280
|
+
$ lono cfn create my-stack --template different-name1
|
281
|
+
```
|
282
|
+
|
283
|
+
The template that will be use is output/different-name1.json and the parameters will use params/different-name1.json.
|
239
284
|
|
240
|
-
|
285
|
+
```
|
286
|
+
$ lono cfn create my-stack --params different-name2
|
287
|
+
```
|
288
|
+
|
289
|
+
The template that will be use is output/different-name2.json and the parameters will use params/different-name2.json.
|
290
|
+
|
291
|
+
```
|
292
|
+
$ lono cfn create my-stack --template different-name3 --params different-name4
|
293
|
+
```
|
294
|
+
|
295
|
+
The template that will be use is output/different-name3.json and the parameters will use params/different-name4.json.
|
296
|
+
|
297
|
+
### lono cfn update
|
298
|
+
|
299
|
+
To update stacks you can use `lono cfn update`:
|
300
|
+
|
301
|
+
```
|
302
|
+
$ lono cfn update my-stack --template template-name --params params-name
|
303
|
+
```
|
304
|
+
|
305
|
+
By default the update command will display a preview of the stack changes before applying the update and prompt to check if you are sure. If you want to bypass the are you sure prompt, use the `--sure` option.
|
306
|
+
|
307
|
+
```
|
308
|
+
$ lono cfn update my-stack --template template-name --params params-name --sure
|
309
|
+
```
|
310
|
+
|
311
|
+
### lono cfn delete
|
312
|
+
|
313
|
+
```
|
314
|
+
$ lono cfn delete my-stack --sure
|
315
|
+
```
|
316
|
+
|
317
|
+
### lono cfn preview
|
318
|
+
|
319
|
+
If you want to see the CloudFormation preview without updating the stack you can also use the `lono cfn preview` command. The preview command is also covered in this blog post: [AWS CloudFormation dry-run with lono cfn preview](https://medium.com/boltops/aws-cloudformation-dry-run-with-lono cfn-plan-2a1e0f80d13c)
|
320
|
+
|
321
|
+
```
|
322
|
+
$ lono cfn preview example --template single_instance --params single_instance
|
323
|
+
Using template: output/single_instance.yml
|
324
|
+
Using parameters: params/single_instance.txt
|
325
|
+
Generating CloudFormation templates:
|
326
|
+
./output/single_instance.yml
|
327
|
+
Params file generated for example at ./output/params/example.json
|
328
|
+
Generating CloudFormation Change Set for preview.....
|
329
|
+
CloudFormation preview for 'example' stack update. Changes:
|
330
|
+
Remove AWS::Route53::RecordSet: DnsRecord testsubdomain.sub.tongueroo.com
|
331
|
+
$
|
332
|
+
```
|
333
|
+
|
334
|
+
|
335
|
+
## Contributing
|
336
|
+
|
337
|
+
1. Fork it
|
338
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
339
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
340
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
341
|
+
5. Create new Pull Request
|
342
|
+
|
343
|
+
## Developing
|
344
|
+
|
345
|
+
There is a submodule in this project, so when you check out remember to sync the submodule.
|
346
|
+
|
347
|
+
```bash
|
348
|
+
$ git clone git@github.com:yourfork/lono.git
|
349
|
+
$ git submodule sync
|
350
|
+
$ git submodule update --init
|
351
|
+
```
|
data/bin/lono
CHANGED
data/circle.yml
ADDED
data/lib/lono.rb
CHANGED
@@ -4,10 +4,19 @@ require 'pp'
|
|
4
4
|
require 'colorize'
|
5
5
|
require 'fileutils'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
require
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
# vendor because need https://github.com/futurechimp/plissken/pull/6 to be merged
|
8
|
+
$:.unshift(File.expand_path("../../vendor/plissken/lib", __FILE__))
|
9
|
+
require "plissken"
|
10
|
+
|
11
|
+
$:.unshift(File.expand_path('../', __FILE__))
|
12
|
+
module Lono
|
13
|
+
autoload :VERSION, 'lono/version'
|
14
|
+
autoload :Help, 'lono/help'
|
15
|
+
autoload :ProjectChecker, 'lono/project_checker'
|
16
|
+
autoload :Command, 'lono/command'
|
17
|
+
autoload :CLI, 'lono/cli'
|
18
|
+
autoload :New, 'lono/new'
|
19
|
+
autoload :Template, 'lono/template'
|
20
|
+
autoload :Cfn, 'lono/cfn'
|
21
|
+
autoload :Param, 'lono/param'
|
22
|
+
end
|
data/lib/lono/cfn.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require "thor"
|
2
|
+
|
3
|
+
module Lono
|
4
|
+
class Cfn < Command
|
5
|
+
autoload :Help, 'lono/cfn/help'
|
6
|
+
autoload :AwsServices, 'lono/cfn/aws_services'
|
7
|
+
autoload :Util, 'lono/cfn/util'
|
8
|
+
autoload :CLI, 'lono/cfn/cli'
|
9
|
+
autoload :Base, 'lono/cfn/base'
|
10
|
+
autoload :Create, 'lono/cfn/create'
|
11
|
+
autoload :Update, 'lono/cfn/update'
|
12
|
+
autoload :Delete, 'lono/cfn/delete'
|
13
|
+
autoload :Preview, 'lono/cfn/preview'
|
14
|
+
autoload :Diff, 'lono/cfn/diff'
|
15
|
+
|
16
|
+
class_option :verbose, type: :boolean
|
17
|
+
class_option :noop, type: :boolean
|
18
|
+
class_option :project_root, desc: "Project folder. Defaults to current directory", default: "."
|
19
|
+
class_option :region, desc: "AWS region"
|
20
|
+
|
21
|
+
# common to create and update
|
22
|
+
class_option :template, desc: "override convention and specify the template file to use"
|
23
|
+
class_option :param, desc: "override convention and specify the param file to use"
|
24
|
+
class_option :lono, type: :boolean, desc: "invoke lono to generate CloudFormation templates", default: true
|
25
|
+
|
26
|
+
desc "create STACK", "create a CloudFormation stack"
|
27
|
+
long_desc Help.create
|
28
|
+
def create(name)
|
29
|
+
Create.new(name, options).run
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "update STACK", "update a CloudFormation stack"
|
33
|
+
long_desc Help.update
|
34
|
+
option :change_set, type: :boolean, default: true, desc: "Uses generated change set to update the stack. If false, will perform normal update-stack."
|
35
|
+
option :diff, type: :boolean, default: true, desc: "Show diff of the source code template changes before continuing."
|
36
|
+
option :preview, type: :boolean, default: true, desc: "Show preview of the stack changes before continuing."
|
37
|
+
option :sure, type: :boolean, desc: "Skips are you sure prompt"
|
38
|
+
def update(name)
|
39
|
+
Update.new(name, options).run
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "delete STACK", "delete a CloudFormation stack"
|
43
|
+
long_desc Help.delete
|
44
|
+
option :sure, type: :boolean, desc: "Skips are you sure prompt"
|
45
|
+
def delete(name)
|
46
|
+
Delete.new(name, options).run
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "preview STACK", "preview a CloudFormation stack update"
|
50
|
+
long_desc Help.preview
|
51
|
+
option :keep, type: :boolean, desc: "keep the changeset instead of deleting it afterwards"
|
52
|
+
option :diff, type: :boolean, default: true, desc: "Show diff of the source code template changes also."
|
53
|
+
def preview(name)
|
54
|
+
Diff.new(name, options).run if options[:diff]
|
55
|
+
Preview.new(name, options).run
|
56
|
+
end
|
57
|
+
|
58
|
+
desc "diff STACK", "diff of newly generated template vs existing template in AWS"
|
59
|
+
long_desc Help.diff
|
60
|
+
def diff(name)
|
61
|
+
Diff.new(name, options).run
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "aws-sdk"
|
2
|
+
|
3
|
+
module Lono::Cfn::AwsServices
|
4
|
+
def cfn
|
5
|
+
@cfn ||= Aws::CloudFormation::Client.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def stack_exists?(stack_name)
|
9
|
+
return true if testing_update?
|
10
|
+
return false if @options[:noop]
|
11
|
+
|
12
|
+
exist = nil
|
13
|
+
begin
|
14
|
+
# When the stack does not exist an exception is raised. Example:
|
15
|
+
# Aws::CloudFormation::Errors::ValidationError: Stack with id blah does not exist
|
16
|
+
resp = cfn.describe_stacks(stack_name: stack_name)
|
17
|
+
exist = true
|
18
|
+
rescue Aws::CloudFormation::Errors::ValidationError => e
|
19
|
+
if e.message =~ /does not exist/
|
20
|
+
exist = false
|
21
|
+
elsif e.message.include?("'stackName' failed to satisfy constraint")
|
22
|
+
# Example of e.message when describe_stack with invalid stack name
|
23
|
+
# "1 validation error detected: Value 'instance_and_route53' at 'stackName' failed to satisfy constraint: Member must satisfy regular expression pattern: [a-zA-Z][-a-zA-Z0-9]*|arn:[-a-zA-Z0-9:/._+]*"
|
24
|
+
puts "Invalid stack name: #{stack_name}"
|
25
|
+
puts "Full error message: #{e.message}"
|
26
|
+
exit 1
|
27
|
+
else
|
28
|
+
raise # re-raise exception because unsure what other errors can happen
|
29
|
+
end
|
30
|
+
end
|
31
|
+
exist
|
32
|
+
end
|
33
|
+
|
34
|
+
def testing_update?
|
35
|
+
ENV['TEST'] && self.class.name == "LonoCfn::Update"
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require "lono"
|
2
|
+
|
3
|
+
class Lono::Cfn::Base
|
4
|
+
include Lono::Cfn::AwsServices
|
5
|
+
include Lono::Cfn::Util
|
6
|
+
|
7
|
+
def initialize(stack_name, options={})
|
8
|
+
@stack_name = stack_name
|
9
|
+
@options = options
|
10
|
+
@project_root = options[:project_root] || '.'
|
11
|
+
ProjectChecker.check(@project_root) unless options[:lono] # already ran checker in lono generate
|
12
|
+
|
13
|
+
template_name = options[:template] || @stack_name
|
14
|
+
param_name = options[:param] || template_name
|
15
|
+
@template_path = get_source_path(template_name, :template)
|
16
|
+
@param_path = get_source_path(param_name, :param)
|
17
|
+
puts "Using template: #{@template_path}" unless @options[:mute_using]
|
18
|
+
puts "Using parameters: #{@param_path}" unless @options[:mute_using]
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
params = generate_all
|
23
|
+
save_stack(params) # defined in the sub class
|
24
|
+
end
|
25
|
+
|
26
|
+
def generate_all
|
27
|
+
generate_templates if @options[:lono]
|
28
|
+
check_for_errors
|
29
|
+
generate_params(mute: @options[:mute_params])
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate_templates
|
33
|
+
Lono::Template::DSL.new(
|
34
|
+
project_root: @project_root,
|
35
|
+
pretty: true
|
36
|
+
).run
|
37
|
+
end
|
38
|
+
|
39
|
+
def generate_params(options={})
|
40
|
+
generator_options = {
|
41
|
+
project_root: @project_root,
|
42
|
+
path: @param_path,
|
43
|
+
allow_no_file: true
|
44
|
+
}.merge(options)
|
45
|
+
generator = Lono::Param::Generator.new(@stack_name, generator_options)
|
46
|
+
generator.generate # Writes the json file in CamelCase keys format
|
47
|
+
generator.params # Returns Array in underscore keys format
|
48
|
+
end
|
49
|
+
|
50
|
+
def check_for_errors
|
51
|
+
errors, warns = check_files
|
52
|
+
unless errors.empty?
|
53
|
+
puts "Please double check the command you ran. There were some errors."
|
54
|
+
puts "ERROR: #{errors.join("\n")}".colorize(:red)
|
55
|
+
exit
|
56
|
+
end
|
57
|
+
unless warns.empty?
|
58
|
+
puts "Please double check the command you ran. There were some warnings."
|
59
|
+
puts "WARN: #{warns.join("\n")}".colorize(:yellow)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def check_files
|
64
|
+
errors, warns = [], []
|
65
|
+
unless File.exist?(@template_path)
|
66
|
+
warns << "Template file missing: could not find #{@template_path}"
|
67
|
+
end
|
68
|
+
if @options[:param] && !File.exist?(@param_path)
|
69
|
+
warns << "Parameters file missing: could not find #{@param_path}"
|
70
|
+
end
|
71
|
+
[errors, warns]
|
72
|
+
end
|
73
|
+
|
74
|
+
# if existing in params path then use that
|
75
|
+
# if it doesnt assume it is a full path and check that
|
76
|
+
# else fall back to convention, which also eventually gets checked in check_for_errors
|
77
|
+
#
|
78
|
+
# Type - :param or :template
|
79
|
+
def get_source_path(path, type)
|
80
|
+
if path.nil?
|
81
|
+
default_convention_path = convention_path(@stack_name, type)
|
82
|
+
else
|
83
|
+
# convention path based on the input from the user
|
84
|
+
convention_path(path, type)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def convention_path(name, type)
|
89
|
+
path = case type
|
90
|
+
when :template
|
91
|
+
format = detect_format
|
92
|
+
"#{@project_root}/output/#{name}.#{format}"
|
93
|
+
when :param
|
94
|
+
"#{@project_root}/params/#{name}.txt"
|
95
|
+
else
|
96
|
+
raise "hell: dont come here"
|
97
|
+
end
|
98
|
+
path.sub(/^\.\//, '')
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns String with value of "yml" or "json".
|
102
|
+
def detect_format
|
103
|
+
formats = Dir.glob("#{@project_root}/output/**/*").map { |path| path }.
|
104
|
+
reject { |s| s =~ %r{/params/} }. # reject output/params folder
|
105
|
+
map { |path| File.extname(path) }.
|
106
|
+
reject { |s| s.empty? }. # reject ""
|
107
|
+
uniq
|
108
|
+
if formats.size > 1
|
109
|
+
puts "ERROR: Detected multiple formats: #{formats.join(", ")}".colorize(:red)
|
110
|
+
puts "All the output files must use the same format. Either all json or all yml."
|
111
|
+
exit 1
|
112
|
+
elsif formats.size == 1
|
113
|
+
formats.first.sub(/^\./,'')
|
114
|
+
else
|
115
|
+
puts "WARN: Did not detect any template formats. Defaulting to yml. Please check the config and templates folders."
|
116
|
+
"yml" # default format
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# All CloudFormation states listed here:
|
121
|
+
# http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-describing-stacks.html
|
122
|
+
def stack_status(stack_name)
|
123
|
+
return true if testing_update?
|
124
|
+
return false if @options[:noop]
|
125
|
+
|
126
|
+
resp = cfn.describe_stacks(stack_name: stack_name)
|
127
|
+
status = resp.stacks[0].stack_status
|
128
|
+
end
|
129
|
+
|
130
|
+
def exist_unless_updatable(status)
|
131
|
+
return true if testing_update?
|
132
|
+
return false if @options[:noop]
|
133
|
+
|
134
|
+
unless status =~ /_COMPLETE$/
|
135
|
+
puts "Cannot create a change set for the stack because the #{@stack_name} is not in an updatable state. Stack status: #{status}"
|
136
|
+
quit(1)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# To allow mocking in specs
|
141
|
+
def quit(signal)
|
142
|
+
exit signal
|
143
|
+
end
|
144
|
+
end
|