Skip to content

Commit 022e27a

Browse files
author
Alireza
authored
Merge pull request #56 from developmentseed/nested_templates
add support for nested CF templates
2 parents e9af42b + 741c227 commit 022e27a

19 files changed

Lines changed: 916 additions & 123 deletions

.circleci/config.yml

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,29 @@ jobs:
1818
name: Install
1919
command: |
2020
npm install
21-
sudo npm install -g .
21+
22+
# save cahce
23+
- save_cache:
24+
key: deploy-{{ .Branch }}-{{ checksum "package.json" }}
25+
paths:
26+
- ~/kes/node_modules
2227

2328
- run:
2429
name: Test Examples
2530
command: |
2631
mkdir ~/example1
2732
cp -r examples/lambdas ~/example1/.kes
2833
cd ~/example1/
29-
kes cf compile
30-
kes cf validate
34+
~/kes/bin/cli.js cf compile
35+
~/kes/bin/cli.js cf validate
3136
3237
cd ~/kes
33-
kes cf compile --kes-folder examples/full
34-
kes cf validate --kes-folder examples/full
38+
./bin/cli.js cf compile --kes-folder examples/full
39+
./bin/cli.js cf validate --kes-folder examples/full
40+
./bin/cli.js cf validate --kes-folder examples/nested
41+
42+
./bin/cli.js cf validate --kes-folder examples/app_using_template --template examples/template
3543
36-
kes cf validate --kes-folder examples/app_using_template --template examples/template
3744
3845
npm run test
3946
@@ -65,8 +72,4 @@ jobs:
6572
npm publish || echo 'npm publishing failed'
6673
fi
6774
68-
# save cahce
69-
- save_cache:
70-
key: deploy-{{ .Branch }}-{{ checksum "package.json" }}
71-
paths:
72-
- ~/kes/node_modules
75+

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ _docs
44
build
55
dist
66
cloudformation.yml
7+
myNestedTemplate.yml
8+

CHANGELOG

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## v2.1.0
2+
3+
- add support for nested cloudformation templates
4+
15
## v2.0.3
26

37
- support symlink for lambda zipping

bin/cli.js

Lines changed: 13 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -3,75 +3,30 @@
33
'use strict';
44

55
require('./readme');
6-
const get = require('lodash.get');
76
const fs = require('fs');
87
const path = require('path');
98
const colors = require('colors/safe');
109
const yaml = require('js-yaml');
1110
const prompt = require('prompt');
1211
const program = require('commander');
13-
const deprecate = require('deprecate');
12+
const kes = require('../index');
1413
const pckg = require('../package.json');
15-
const Config = require('../src/config');
1614

1715
const baseDir = process.cwd();
1816
const kesFolder = path.join(baseDir, '.kes');
1917
const distFolder = path.join(baseDir, 'dist');
2018

21-
const success = (r) => process.exit(0);
22-
2319
program.version(pckg.version);
2420

25-
/**
26-
* @name failure
27-
* @private
28-
*/
29-
const failure = (e) => {
30-
if (e.message) {
31-
console.log(e.message);
32-
}
33-
else {
34-
console.log(e);
35-
}
36-
process.exit(1);
37-
};
38-
39-
const determineKesClass = function () {
40-
let Kes;
41-
42-
// if there is a kes class specified use that
43-
const kesClass = get(program, 'kesClass');
44-
if (kesClass) {
45-
Kes = require(path.join(process.cwd(), kesClass));
46-
}
47-
else {
48-
// check if there is kes.js in the kes-folder
49-
try {
50-
let kesFolder;
51-
if (program.kesFolder) {
52-
kesFolder = program.kesFolder;
53-
}
54-
else {
55-
kesFolder = path.join(process.cwd(), '.kes');
56-
}
57-
Kes = require(path.join(process.cwd(), kesFolder, 'kes.js'));
21+
function extractCommanderOptions(program) {
22+
const options = {};
23+
Object.keys(program).forEach(property => {
24+
if (typeof program[property] === 'string') {
25+
options[property] = program[property];
5826
}
59-
catch (e) {
60-
// check if there is a template and the template has kes class
61-
const template = get(program, 'template', '/path/to/nowhere');
62-
try {
63-
const kesPath = path.join(process.cwd(), template, 'kes.js');
64-
fs.lstatSync(kesPath);
65-
Kes = require(kesPath);
66-
}
67-
catch (e) {
68-
Kes = require('../index').Kes;
69-
}
70-
}
71-
}
72-
73-
return Kes;
74-
};
27+
});
28+
return options;
29+
}
7530

7631
const init = function () {
7732
if (fs.existsSync(kesFolder)) {
@@ -161,50 +116,16 @@ program
161116
deploy Creates the CF stack and Update if already exists
162117
validate Validates the CF stack
163118
compile Compiles the CF stack`)
164-
.action((cmd) => {
165-
const Kes = determineKesClass(program);
166-
const config = new Config(program);
167-
const kes = new Kes(config);
168-
switch (cmd) {
169-
case 'create':
170-
deprecate('"kes cf create" command is deprecated. Use "kes cf deploy" instead');
171-
kes.createStack().then(r => success(r)).catch(e => failure(e));
172-
break;
173-
case 'update':
174-
deprecate('"kes cf update" command is deprecated. Use "kes cf deploy" instead');
175-
kes.updateStack().then(r => success(r)).catch(e => failure(e));
176-
break;
177-
case 'upsert':
178-
deprecate('"kes cf upsert" command is deprecated. Use "kes cf deploy" instead');
179-
kes.upsertStack().then(r => success(r)).catch(e => failure(e));
180-
break;
181-
case 'deploy':
182-
kes.deployStack().then(r => success(r)).catch(e => failure(e));
183-
break;
184-
case 'validate':
185-
kes.validateTemplate().then(r => success(r)).catch(e => failure(e));
186-
break;
187-
case 'compile':
188-
kes.compileCF().then(r => success(r)).catch(e => failure(e));
189-
break;
190-
default:
191-
console.log('Wrong choice. Accepted arguments: [create|update|upsert|deploy|validate|compile]');
192-
}
119+
.action((cmd, o) => {
120+
const options = extractCommanderOptions(program);
121+
kes.buildCf(options ,cmd);
193122
});
194123

195124
program
196125
.command('lambda <lambdaName>')
197126
.description('uploads a given lambda function to Lambda service')
198127
.action((cmd, options) => {
199-
if (cmd) {
200-
const Kes = require('../index').Kes;
201-
const config = new Config(program);
202-
const kes = new Kes(config);
203-
kes.updateSingleLambda(cmd).then(r => success(r)).catch(e => failure(e));
204-
}
205-
else {
206-
console.log('Lambda name is missing');
207-
}
128+
kes.buildLambda(program, cmd);
208129
});
209130

210131
program

bin/readme.js

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@
244244
*
245245
* To create a CF stack or update and existing one run
246246
* ```bash
247-
* kes cf deploy
247+
* kes cf deploy
248248
* ```
249249
*
250250
* ### Differenet deployment configurations
@@ -300,4 +300,48 @@
300300
*
301301
* This setup gives users of the templates a great degree of flexibility and ownership.
302302
*
303+
* ## Nested Templates
304+
* Kes supports use of [Cloudformation Nested Templates](https://aws.amazon.com/blogs/devops/use-nested-stacks-to-create-reusable-templates-and-support-role-specialization/).
305+
* To use nested templates, create a separate `template.yml` and `config.yml` files for each nested template using the same rules explained above.
306+
* Then include references in your main `config.yml`.
307+
*
308+
* All nested templates will receive the parent configuration under the `parent` key.
309+
*
310+
* ### Example
311+
* ```yaml
312+
* # config.yml
313+
* default:
314+
* stackName: myStack-test
315+
* myArray:
316+
* - DEBUG: true
317+
* nested_templates:
318+
* myNestedTemplate:
319+
* cfFile: /path/to/myNestedTemplate.template.yml
320+
* configFile: /path/to/myNestedConfig.yml
321+
*
322+
* staging:
323+
* stackName: myStack-staging
324+
* myArray:
325+
* - DEBUG: false
326+
* ```
327+
*
328+
* ```yaml
329+
* # myNestedConfig.yml
330+
* default:
331+
* timeout: 300
332+
* ```
333+
*
334+
* ```yaml
335+
* # myNestedTemplate.template.yml
336+
* Resources:
337+
*
338+
* {{# each parent.myArray}}
339+
* Lambda:
340+
* Type: SomeAWSResource
341+
* Properties:
342+
* Timeout: {{../timeout}}
343+
* Environments:
344+
* - {{@key}}: {{this}}
345+
* {{/each}}
346+
* ```
303347
*/

docs/API.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- [Config](#config)
66
- [parse](#parse)
7+
- [flatten](#flatten)
78
- [Kes](#kes)
89
- [updateSingleLambda](#updatesinglelambda)
910
- [compileCF](#compilecf)
@@ -31,6 +32,8 @@
3132
- [configureAws](#configureaws)
3233
- [fileToString](#filetostring)
3334
- [mergeYamls](#mergeyamls)
35+
- [determineKesClass](#determinekesclass)
36+
- [failure](#failure)
3437

3538
## Config
3639

@@ -73,6 +76,13 @@ config = configInstance.parse();
7376

7477
Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the configuration object
7578

79+
### flatten
80+
81+
Return a javascript object (not a class instance) of the
82+
config class
83+
84+
Returns **[object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** a javascript object version of the class
85+
7686
## Kes
7787

7888
The main Kes class. This class is used in the command module to create
@@ -367,3 +377,23 @@ replace values of file 1 if they have the same key.
367377
- `file2` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** Yaml path to file 2 or file 2 string
368378

369379
Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** Merged Yaml file in string format
380+
381+
## determineKesClass
382+
383+
Based on the information passed from the CLI by the commander
384+
module this function determines whether to use the default Kes class
385+
or use the override class provided by the user
386+
387+
**Parameters**
388+
389+
- `options` **[object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** The options passed by the commander library
390+
391+
Returns **Class** Kes class
392+
393+
## failure
394+
395+
In case of error logs the error and exit with error 1
396+
397+
**Parameters**
398+
399+
- `e` **[Error](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error)** error object

docs/README.md

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
- [Deployment Using IAM Role](#deployment-using-iam-role)
1717
- [Updating One Lambda Function](#updating-one-lambda-function)
1818
- [Use Templates](#use-templates)
19+
- [Nested Templates](#nested-templates)
20+
- [Example](#example)
1921

2022
##
2123

@@ -67,7 +69,7 @@ It makes it much easier to deploy lambda functions and create API gateway resour
6769
Go to your project directory and run the following command.
6870
6971
```bash
70-
$ kes init
72+
$ npm init
7173
```
7274
7375
This will create a `.kes` folder on your project folder. It will include the following files:
@@ -268,7 +270,7 @@ Resources:
268270
To create a CF stack or update and existing one run
269271
270272
```bash
271-
kes cf deploy
273+
kes cf deploy
272274
```
273275
274276
### Differenet deployment configurations
@@ -324,3 +326,50 @@ The user still has the option of creating her own `config.yml` and `cloudformati
324326
in the template or append it if it doesn't exist.
325327
326328
This setup gives users of the templates a great degree of flexibility and ownership.
329+
330+
## Nested Templates
331+
332+
Kes supports use of [Cloudformation Nested Templates](https://aws.amazon.com/blogs/devops/use-nested-stacks-to-create-reusable-templates-and-support-role-specialization/).
333+
To use nested templates, create a separate `template.yml` and `config.yml` files for each nested template using the same rules explained above.
334+
Then include references in your main `config.yml`.
335+
336+
All nested templates will receive the parent configuration under the `parent` key.
337+
338+
### Example
339+
340+
```yaml
341+
# config.yml
342+
default:
343+
stackName: myStack-test
344+
myArray:
345+
- DEBUG: true
346+
nested_templates:
347+
myNestedTemplate:
348+
cfFile: /path/to/myNestedTemplate.template.yml
349+
configFile: /path/to/myNestedConfig.yml
350+
351+
staging:
352+
stackName: myStack-staging
353+
myArray:
354+
- DEBUG: false
355+
```
356+
357+
```yaml
358+
# myNestedConfig.yml
359+
default:
360+
timeout: 300
361+
```
362+
363+
```yaml
364+
# myNestedTemplate.template.yml
365+
Resources:
366+
367+
{{# each parent.myArray}}
368+
Lambda:
369+
Type: SomeAWSResource
370+
Properties:
371+
Timeout: {{../timeout}}
372+
Environments:
373+
- {{@key}}: {{this}}
374+
{{/each}}
375+
```

examples/full/kes.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
const { Kes } = require('../../index');
3+
const Kes = require('../../index').Kes;
44

55
class BetterKes extends Kes {
66
opsStack(ops) {

0 commit comments

Comments
 (0)