UNPKG

19.1 kBMarkdownView Raw
1# condensation
2
3Package, reuse and share particles for CloudFormation projects
4
5![condensation][condensation-image]
6
7[![NPM][npm-image]][npm-url]
8[![Gitter][gitter-image]][gitter-url]
9[![Build Status][travis-image]][travis-url]
10[![Code Climate][codeclimate-image]][codeclimate-url]
11[![Coverage Status][coveralls-image]][coveralls-url]
12[![Dependency Status][daviddm-image]][daviddm-url]
13
14
15## Summary
16
17Condensation uses [gulp](http://gulpjs.com) to generate tasks that
18compile, package and upload [AWS CloudFormation](http://aws.amazon.com/cloudformation/)
19templates and supporting assets as distributions.
20
21Any file with the extension `.hbs` will be compiled with
22[Handlebars.js](http://handlebarsjs.com/) to support
23partials, helpers and variable replacement.
24
25## Quick Start
26
27### With Docker
28
29The fastest way to get started with condensation: [condensation-docker][condensation-docker-url]
30
31```
32$ alias condensation="docker run -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN -v \"$HOME\"/.aws/credentials:/home/condensation/.aws/credentials -v \`pwd\`:/particles --rm -it sungardas/condensation"
33
34
35$ condensation create project particles-MYPROJECT
36$ cd particles-MYPROJECT
37$ condensation run build
38```
39
40### With a nodejs environment
41
42Use the Yeoman
43[generator](https://github.com/SungardAS/generator-condensation).
44
45```
46$ npm install -g yo
47$ npm install -g generator-condensation
48$ yo condensation:project particles-MYPROJECT
49$ cd particles-MYPROJECT
50$ npm run build
51```
52
53### Example Projects
54
55* [condensation-examples](https://github.com/SungardAS/condensation-examples)
56* [particles-vpc](https://github.com/SungardAS/particles-vpc)
57* [particles-cloudsploit-scans](https://github.com/SungardAS/particles-cloudsploit-scans)
58* [particles-enhanced-snapshots](https://github.com/SungardAS/particles-enhanced-snapshots)
59
60Check out the growing list of particles on
61[npm](https://www.npmjs.com/browse/keyword/condensation-particles)!
62
63
64## Features
65
66* Write reusable CloudFormation snippets, called `particles` that can be used
67 accross condensation projets
68* Package templates and assets then upload full distributions to multiple buckets across
69 regions with one command.
70* Reference another template within the distribution with
71 [AWS::CloudFormation::Stack](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stack.html)
72and the `templateS3Url` helper
73* Upload scripts, configuration files and other assets alongside
74 CloudFormation templates and reference them with asset helpers.
75
76## Why?
77
78CloudFormation templates are great for creating, updating and deleting
79AWS resources. Reusing parts of templates, referencing other
80templates with `AWS::CloudFormation::Stack` and deploying cloud-init
81scripts can be difficult to manage.
82
83* Sections such as AMI [mappings](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html)
84 are often re-used by many templates. Particles provide a way to
85 write the mapping once and reuse it in other templates by reference.
86* It is common to set up resources, such as a VPC, with nearly
87 identical attributes and structure for different applications and
88 services. Condensation allows that definition to become a independent
89 stack that can be referenced by other templates that are part of the
90 same distribution.
91* When bootstrapping ec2 instances it is beneficial to have versioned scripts and configuration
92 files deployed in the same bucket and path as the CloudFormation template
93 they are associated with.
94* When using `AWS::CloudFormation::Authentication` to download assets from
95 S3 buckets all resources must be in the same region. Condensation
96 makes it easy to deploy the same templates and assets to multiple
97 regions and ensure the referencing URLs are always pointing to the
98 right place.
99
100For example, templates in a distribution can reference one another based on the
101bucket they are deployed to.
102
103Example:
104
105 "TemplateURL": "{{templateS3Url 'vpc.template' }}"
106 ...
107 "TemplateURL": "{{templateS3Url 'subnet.template' }}"
108
109Output:
110
111 "TemplateURL": "https://s3-us-west-1.amazonaws.com/<BUCKET>/cftemplates/vpc.template"
112 ...
113 "TemplateURL": "https://s3-us-west-1.amazonaws.com/<BUCKET>/cftemplates/subnet.template"
114
115The Handlebars helper, `templateS3Url`, creates a URL that will always reference a template deployed within the same bucket.
116
117
118
119## Use
120
121### Project Structure
122
123 particles-my-project
124 |
125 -- guplfile.js
126 |
127 -- README.md
128 |
129 -- CHANGELOG.md
130 |
131 --particles
132 |
133 -- assets
134 |
135 -- conditions
136 |
137 -- cftemplates
138 |
139 -- helpers
140 |
141 -- mappings
142 |
143 -- metadata
144 |
145 -- outputs
146 |
147 -- parameters
148 |
149 -- resources
150 |
151 -- sets
152 |
153 -- partials
154
155Condensation builds templates with Handlebars helpers that
156are able to load particles from the local project
157or from any condensation compatible module added as a npm
158dependency.
159
160All helpers follow the same pattern:
161
162 {{<CONDENSATION-HELPER> [module:<MODULE>] '<PATH_TO_PARTICLE>' [OPTIONS...]}}
163
164When including the particles from another project *MODULE* is the name
165of the npm dependency.
166
167**New in 0.5.0**
168
169Use `m` instead of `module` if referencing a module that
170starts with `particles-` to minimize characters used. The `m` option
171will add `particles-` to the beginning of \<MODULE\> for you.
172
173 {{<CONDENSATION-HELPER> [m:<MODULE>] '<PATH_TO_PARTICLE>' [OPTIONS...]}}
174
175Example, load a particle from `particles-core`
176
177 {{parameter "m:core" "base" logicalId="Parameter1"}}
178
179#### Lazy Loading
180
181Particles will only be included in the final distribution if they are
182referenced in a `hbs` file.
183
184### layout support
185
186**New in 0.3.0**
187
188Instead of including particles within a traditional CloudFormation
189template the introduction of a layout supports capturing helper output
190and adding it to the correct section. Helpers within a layout do not
191have to to be in any specific order.
192
193 ---
194 things:
195 -
196 name: subnet1
197 cidr: "10.0.0.0/24"
198 -
199 name subnet2
200 cidr: "10.0.1.0/24"
201 ---
202
203 {{#layout templateDescription="condensation rocks!"}}
204 {{parameter 'my_parameter' logicalId="MyParameter"}}
205 {{condition 'my_condition' logicalId="MyCondition"}}
206
207 {{! helpers can occur in any order, allowing you to group related section parts together }}
208
209 {{#each things}}
210 {{parameter 'repeate_me' logicalId="RepeateMe" logicalIdSuffix=@index}}
211 {{condition 'repeate_me' logicalId="RepeateMeCond" logicalIdSuffix=@index}}
212 {{resource 'repeate_me' logicalId="RepeateMeResource" logicalIdSuffix=@index}}
213 {{output 'repeate_me' logicalId="RepeateMeOutput" logicalIdSuffix=@index}}
214 {{/each}}
215 {{/layout}}
216
217
218#### assets
219
220Files to be uploaded to S3 that are used to supplement CloudFormation
221templates. Files can include bootsrap scripts, packaged install files
222or configuration files.
223
224Any file with a `.hbs` extension will be
225compiled with handlebars and saved to S3. The `.hbs` extension will be
226removed from the filename.
227
228Asset URLs can be built with the `assetS3Url` helper:
229
230 {{assetS3Url 'my-asset' [protocol=https|s3]}}
231
232 {{assetS3Url 'module:<MODULE>' 'module-asset' [protocol=https|s3]}}
233
234
235Parameters:
236
237**protocol** *optional* https|s3 - Forces the protocol of the url to https:// or s3://
238
239Example Output:
240
241 "https://s3-us-west-1.amazonaws.com/BUCKET/assets/my-asset"
242
243 "https://s3-us-west-1.amazonaws.com/BUCKET/node_modules/MODULE/particles/assets/module-asset"
244
245Asset paths (the full key path as it will be in the s3 bucket) can be built with the `assetPath` helper:
246
247 {{assetPath 'my-asset'}}
248
249 {{assetPath 'module:<MODULE>' 'module-asset' }}
250
251Example Output:
252
253 "/assets/my-asset"
254
255 "/node_modules/MODULE/particles/assets/module-asset"
256
257For both assetS3Url and assetPath the particle path will match the name of the asset without the `.hbs` extension, if it exists.
258
259To include assets that are not directly referenced from a template
260use the `requireAssets` helper. It will ensure a glob of assets are
261included in the distribution.
262
263 {{requireAssets '/**'}}
264
265 {{requireAssets 'module:<MODULE>' '/**'}}
266
267`requireAssets` will not produce output, only ensure that the glob is
268uploaded to S3.
269
270#### conditions
271
272Contents of files will be loaded as conditions that can be used in
273in a traditional template or a `layout` (**recommended**)
274
275Directory: `conditions`
276Helper: `condition`
277
278 {{condition 'my-condition' logicalId="MyCond"}}
279
280 {{condition 'module:<MODULE>' 'condition-name' logicalId="TheirCond"}}
281
282The particle path can match the base name of the file or the base name
283plus any extensions.
284
285
286#### cftemplates
287
288CloudFormation templates that will be uploaded to S3.
289
290Any file with a `.hbs` extension will be compiled with
291handlebars and saved to S3 without the `.hbs` extension.
292
293Template URLs can be built with the `assetS3Url` helper:
294
295 {{templateS3Url 'my.template'}}
296
297 {{templateS3Url 'module:<MODULE>' 'module.template'}}
298
299The particle path should match the name of the template without the `.hbs` extension, if it exists.
300
301Example Output:
302
303 "https://s3-us-west-1.amazonaws.com/BUCKET/cftemplates/my.template"
304
305 "https://s3-us-west-1.amazonaws.com/BUCKET/node_modules/MODULE/particles/cftemplates/module.template"
306
307#### helpers
308
309Node modules that export a function that is built as a
310Handlebars [block helper](http://handlebarsjs.com/block_helpers.html).
311
312Helpers are called with the `helper` helper:
313
314 {{helper 'my-helper'}}
315
316 {{helper 'module:<MODULE>' 'module-helper'}}
317
318The particle path should match the name of the helper without the `.js` extension.
319
320#### mappings
321
322Contents of files will be loaded as mappings that can be used in
323in a traditional template or a `layout` (**recommended**)
324
325Directory: `mappings`
326Helper: `mapping`
327
328 {{mapping 'my-mapping' logicalId="MyMapping"}}
329
330 {{mapping 'module:<MODULE>' 'mapping-name' logicalId="TheirMapping"}}
331
332The particle path can match the base name of the file or the base name
333plus any extensions.
334
335#### metadata
336
337Contents of files will be loaded as metadata that can be used in
338in a traditional template or a `layout` (**recommended**)
339
340Directory: `metadata`
341Helper: `metadata`
342
343 {{metadata 'my-metadata' logicalId="MyMetadata"}}
344
345 {{metadata 'module:<MODULE>' 'metadata-name' logicalId="TheirMetadata"}}
346
347The particle path can match the base name of the file or the base name
348plus any extensions.
349
350#### outputs
351
352Contents of files will be loaded as outputs that can be used in
353in a traditional template or a `layout` (**recommended**)
354
355Directory: `outputs`
356Helper: `output`
357
358 {{output 'my-output' logicalId="MyOutput"}}
359
360 {{output 'module:<MODULE>' 'output-name' logicalId="TheirOutput"}}
361
362The particle path can match the base name of the file or the base name
363plus any extensions.
364
365#### parameters
366
367Contents of files will be loaded as parameters that can be used in
368in a traditional template or a `layout` (**recommended**)
369
370Directory: `parameters`
371Helper: `parameter`
372
373 {{parameter 'my-output' logicalId="MyParameter"}}
374
375 {{parameter 'module:<MODULE>' 'parameter-name' logicalId="TheirParameter"}}
376
377The particle path can match the base name of the file or the base name
378plus any extensions.
379
380#### partials
381
382Contents of files here will be loaded as partials that can be used in
383`assets` and `cftemplates`.
384
385These files will not be packaged or uploaded to S3.
386
387Partials can be loaded with the `partial` helper:
388
389 {{partial 'my-partial'}}
390
391 {{partial 'module:<MODULE>' 'module-partial'}}
392
393The particle path only needs to match the base name of the partial.
394
395A path of `some_partial` would match `some_partial.json` or `some_partial.json.hbs`.
396
397If the desired partial is not being loaded ensure precedence is given to an exact match.
398
399#### resources
400
401Contents of files will be loaded as resources that can be used in
402in a traditional template or a `layout` (**recommended**)
403
404Directory: `resources`
405Helper: `resource`
406
407 {{resource 'my-output' logicalId="MyResource"}}
408
409 {{resource 'module:<MODULE>' 'resource-name' logicalId="TheirResource"}}
410
411The particle path can match the base name of the file or the base name
412plus any extensions.
413
414#### sets
415
416Intended for use with `layout`
417
418A grouping of section definitions that will always be generated
419together. Most commonly used to generate parameters with corresponding
420conditions.
421
422Directory: `sets`
423Helper: `set`
424
425 {{set 'my-set' logicalId="MySet"}}
426
427 {{set 'module:<MODULE>' 'set-name' logicalId="TheirSet"}}
428
429The particle path can match the base name of the file or the base name
430plus any extensions.
431
432##### Scoping
433
434Sets can be repeated multiple times in a template. Sets can also be
435embedded within other sets. To help with namespacing a set can be
436scoped with a `logicalIdPrefix` and/or a 'logicalIdSuffix`. These
437values will be apporperiately added to and logicalIds within the set.
438
439To reference a logicalId within a scoped set use the `scopeId` and `ref`
440handlebars helpers provided by condensation.
441
442 {{!-- sets/my_set.hbs --}}
443 {{parameter "cidr" logicalId="Cidr"}}
444 {{resource "subnet" logicalId="Subnet" cidr=(ref "cidr")}}
445
446 ---
447
448 {{!-- cftemplates/my_template.template.json.hbs --}}
449
450 {{set "my_set" logicalIdSuffix="1"}}
451 {{set "my_set" logicalIdSuffix="2"}}
452
453The definition above would produce two parameters, `Cidr1` and `Cidr2`, and
454two resources, `Subnet1` and `Subnet2`. Each subnet will reference
455their respective Cidr parameter.
456
457### Tasks
458
459Get a full list of tasks by running `gulp -T`
460
461By default all tasks are prefixed with `condensation:`. This can be
462changed with the `taskPrefix` config option.
463
464#### Default
465
466The `default` task is an alias for `build`. It will prepare all files
467for deployment to s3. Templates and assets are written to the configured
468`dist` directory.
469
470 > gulp condensation:default
471
472
473#### condensation:s3:list
474Will list all the configured s3 buckets and module corresponding ID.
475
476 > gulp condensation:s3:list
477 [10:21:47] Using gulpfile ~/condensation-example/gulpfile.js
478 [10:21:47] Starting 'condensation:s3:list'...
479 0: a.bucket.in.us-east-1
480 1: a.bucket.in.us-west-2
481 [10:21:47] Finished 'condensation:s3:list' after 153 μs
482
483The IDs can be used to deploy to a single bucket instead of all buckets.
484
485#### condensation:deploy
486For the `deploy` task to run AWS credentials must be set as environment
487variables: `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID`
488
489 > AWS_SECRET_ACCESS_KEY=XXXX AWS_ACCESS_KEY_ID=XXXX gulp deploy
490
491This will upload templates to all cofigured S3 buckets.
492
493#### condensation:deploy:ID
494Deploy templates to a specific S3 bucket.
495
496#### condensation:deploy:LABEL
497Deploy templates to all S3 buckets that contain the label, LABEL.
498
499## Config Options
500
501 var config = {
502 // Array of S3 buckets to deploy to
503 s3: [
504 {
505 // AWS specific options
506 aws: {
507 region: 'us-east-1',
508 bucket: 'my.bucket.in.us-east-1',
509 },
510
511 // Run CloudFormation validation during the build task for this bucket
512 validate: true,
513
514 // Create this bucket if it does not already exist
515 create: true
516
517 // Prefix all objects (allows for multiple deployments to the same bucket
518 prefix: '',
519
520 labels: ['east']
521 },
522 ],
523 // The prefix to add to all generated gulp tasks (default: 'condensation')
524 // An empty string will remove the prefix
525 // - condensation:deploy will become deploy
526 taskPrefix: '',
527
528 // Directory that contains the `particles` directory.
529 // Used for test scripts, should not be changed if sharing templates
530 root: './',
531
532 // Where the build task will put the distribution
533 dist: 'dist'
534 };
535
536## Condensation Helpers
537
538### ref
539
540Build a reference to a logicalId. By default `ref` will return a
541logicalId in relation to it's scope adding any logicalIdPrefix and/or
542logicalIdSuffix as necessary. This can be turned off by setting `scope`
543to `false`.
544
545 {{ref 'MyParameter'}}
546 {{ref 'MyParameter' scope=false}}
547
548### scopeId
549
550Return a logicalId based on it's current scope. Will add any
551logicalIdPrefix and/or logicalIdSuffix that is defined.
552
553 {{scopeId 'MyParameter'}}
554
555## Handlebars Helpers
556
557Aside from the helpers to load particles, condensation provides the
558following generic handlebars helpers.
559
560### concat
561
562Concatenate strings
563
564 {{concat 'one' 'two'}}
565 {{#parameter logicalId=(concat 'myPrefix' myStrVar)}}
566
567## Front Matter
568
569All `cftemplates` and `partials` are first processed with
570[gray-matter](https://github.com/jonschlinkert/gray-matter) to load any
571default data definitions.
572
573## Errors
574
575Errors due to badly formed JSON or failed CF validations will stop the
576process and the offending files will be dumped to `condensation_errors`
577
578## Experimental
579
580### condensation.js
581
582If a project contains `condensation.js` the file will be loaded as a
583module and will attement to run the `initialize` function providing a
584callback as the only parameter.
585
586This can be used by particle project to bootstrap any necessary assets
587before any template compiling begins.
588
589Example:
590[particles-cloudsploit-scans](https://github.com/SungardAS/particles-cloudsploit-scans)
591
592## Acknowledgements
593
594Big thank-you to [Brent Stees](https://github.com/bstees) for creating
595the condensation logo!
596
597## Sungard Availability Services | Labs
598[![Sungard Availability Services | Labs][labs-logo]][labs-github-url]
599
600This project is maintained by the Labs team at [Sungard Availability
601Services](http://sungardas.com)
602
603GitHub: [https://sungardas.github.io](https://sungardas.github.io)
604
605Blog:
606[http://blog.sungardas.com/CTOLabs/](http://blog.sungardas.com/CTOLabs/)
607
608
609[codeclimate-image]: https://codeclimate.com/github/SungardAS/condensation/badges/gpa.svg
610[codeclimate-url]: https://codeclimate.com/github/SungardAS/condensation
611[condensation-image]: ./docs/images/condensation_logo.png?raw=true
612[coveralls-image]: https://coveralls.io/repos/SungardAS/condensation/badge.svg
613[coveralls-url]: https://coveralls.io/r/SungardAS/condensation
614[condensation-docker-url]: https://github.com/SungardAS/condensation-docker
615[daviddm-image]: https://david-dm.org/SungardAS/condensation.svg?theme=shields.io
616[daviddm-url]: https://david-dm.org/SungardAS/condensation
617[gitter-image]: https://badges.gitter.im/Join%20Chat.svg
618[gitter-url]: https://gitter.im/SungardAS/condensation?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
619[labs-github-url]: https://sungardas.github.io
620[labs-logo]: https://raw.githubusercontent.com/SungardAS/repo-assets/master/images/logos/sungardas-labs-logo-small.png
621[npm-image]: https://badge.fury.io/js/condensation.svg
622[npm-url]: https://npmjs.org/package/condensation
623[travis-image]: https://travis-ci.org/SungardAS/condensation.svg?branch=master
624[travis-url]: https://travis-ci.org/SungardAS/condensation