cumuliform 0.3.0 → 0.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e4589cd0a6f35898e49b81876b266f3a9822a111
4
- data.tar.gz: 7ddd217959b61d317a0ddc0f2def640d2fa51d07
3
+ metadata.gz: dc898679239945b8548cd8b35fac0135ca1c07d4
4
+ data.tar.gz: 5e5996b0de7f64ba2deb495dcf306374af28947c
5
5
  SHA512:
6
- metadata.gz: d1c8a3767dac321236b599bffb8a4c05d3111eeb7acac048a8da941d061dc3b3bfe12fa61150dad15bb590596a7414aa9a04a765c09b2f24d4e8673c36ccc0a0
7
- data.tar.gz: 20524b85307eb0fe35233ccb6c3453dbc6d09a4920af248fa0d22c9df8abfc62e37b316a7b1149306153546d3d0f71387f5328087b39efa063c8cbe60e3920f3
6
+ metadata.gz: a1de59e26464fb7370af9cdac344ba606ababdc27ec608d0324cf976352c4eded31b1e78731d4ed40c4282029deb0f3b15b3e42a96e70d9c06bb782c310100a9
7
+ data.tar.gz: 5511163114e278987878e18844961a03fd8223fb6e20d328bc1653a194c87f3955ec9b5f74257b49f4fbfcb0561a91adecc0fddebe7fac956d07176bc92c0f3a
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ /examples/*.cform
data/README.md CHANGED
@@ -2,7 +2,24 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/tape-tv/cumuliform.svg?branch=master)](https://travis-ci.org/tape-tv/cumuliform) [![Code Climate](https://codeclimate.com/github/tape-tv/cumuliform/badges/gpa.svg)](https://codeclimate.com/github/tape-tv/cumuliform) [![Test Coverage](https://codeclimate.com/github/tape-tv/cumuliform/badges/coverage.svg)](https://codeclimate.com/github/tape-tv/cumuliform/coverage)
4
4
 
5
- A DSL and library for the generation and reuse of Amazon's AWS CloudFormation templates, extracted from ops and deployment code at tape.tv
5
+ Amazons [CloudFormation AWS service][cf] provides a way to describe
6
+ infrastructure stacks using a JSON template. We love CloudFormation, and use it
7
+ a lot, but the JSON templates are hard to write and read, it's very hard to
8
+ reuse things shared between stacks, and it's very easy to make simple typos
9
+ which are not discovered until minutes into stack creation when things fail for
10
+ seemingly crazy reasons.
11
+
12
+ [cf]: http://aws.amazon.com/cloudformation/
13
+
14
+ Cumuliform is a tool to help eliminate as many sources of reference errors as
15
+ possible, and to allow easier reuse of template parts between stacks. It
16
+ provides a simple DSL that generates reliably valid JSON and enforces
17
+ referential integrity through convenience wrappers around the common points
18
+ where CloudFormation expects references between resources. provides.
19
+
20
+ Cumuliform has been extracted from ops and deployment code at [tape.tv][tape]
21
+
22
+ [tape]: https://www.tape.tv/
6
23
 
7
24
  ## Installation
8
25
 
@@ -20,15 +37,144 @@ Or install it yourself as:
20
37
 
21
38
  $ gem install cumuliform
22
39
 
23
- ## Usage
40
+ # Getting started
41
+
42
+ You’ll probably want to familiarise yourself with the [CloudFormation getting
43
+ started guide][cf-get-started] if you haven’t already.
44
+
45
+ [cf-get-started]: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/GettingStarted.html
46
+
47
+ To quickly recap the key points for template authors:
48
+
49
+ 1. A template is a JSON file containing a single Object (`{}`)
50
+ 2. The template object is split into specific sections through top-level
51
+ properties (resources, parameters, mappings, and outputs).
52
+ 3. The things we’re actually interested in are object children of those
53
+ top-level objects, and the keys (‘logical IDs’ in CloudFormation terms) must
54
+ be unique across each of the four sections.
55
+ 4. Resources, parameters, and the like are just JSON Objects.
56
+ 5. CloudFormation provides what it calls ‘Intrinsic Functions’, e.g. `Fn::Ref`
57
+ to define links and dependencies between your resources.
58
+ 6. Because a template is just a JSON object, it’s very easy to accidentally
59
+ define a resource or parameter with the same logical id more than once, which
60
+ results in a last-one-wins situation where the object defined latest in the
61
+ file will obliterate the previously defined one.
62
+
63
+ Cumuliform provides DSL methods to define objects in each of the four sections,
64
+ helps catch any duplicate logical IDs and provides wrappers for CloudFormation’s
65
+ Intrinsic Functions that enforce referential integrity *before* you upload your
66
+ template and start creating a stack with it.
67
+
68
+ ## The simplest possible template
69
+
70
+ Let’s define a very simple template consisting of one resource and one parameter
71
+
72
+ ```ruby
73
+ Cumuliform.template do
74
+ parameter 'AMI' do
75
+ {
76
+ Description: 'The AMI id for our template (defaults to the stock Ubuntu 14.04 image in eu-central-1)',
77
+ Type: 'String',
78
+ Default: 'ami-accff2b1'
79
+ }
80
+ end
81
+
82
+ resource 'MyInstance' do
83
+ {
84
+ Type: 'AWS::EC2::Instance',
85
+ Properties: {
86
+ ImageId: ref('AMI'),
87
+ InstanceType: 'm3.medium'
88
+ }
89
+ }
90
+ end
91
+ end
92
+ ```
93
+
94
+ Processing the ruby source with cumuliform's command line runner gives us this JSON template:
95
+
96
+ ```sh
97
+ $ cumuliform simplest.rb simplest.cform
98
+ ```
99
+
100
+ ```json
101
+ {
102
+ "Parameters": {
103
+ "AMI": {
104
+ "Description": "The AMI id for our template (defaults to the stock Ubuntu 14.04 image in eu-central-1)",
105
+ "Type": "String",
106
+ "Default": "ami-accff2b1"
107
+ }
108
+ },
109
+ "Resources": {
110
+ "MyInstance": {
111
+ "Type": "AWS::EC2::Instance",
112
+ "Properties": {
113
+ "ImageId": {
114
+ "Ref": "AMI"
115
+ },
116
+ "InstanceType": "m3.medium"
117
+ }
118
+ }
119
+ }
120
+ }
121
+ ```
122
+
123
+ # Rake tasks and the Command Line runner
24
124
 
25
- TODO: Write usage instructions here
125
+ Cumuliform provides a very simple command-line runner to turn a `.rb` template
126
+ into JSON:
127
+
128
+ ```sh
129
+ $ cumuliform /path/to/input_template.rb /path/to/output_template.json
130
+ ```
131
+
132
+ It also provides a Rake task generator to create a Rake `rule` task to turn
133
+ `x.rb` into `x.cform`:
134
+
135
+ ```ruby
136
+ require 'cumuliform/rake_task'
137
+
138
+ Cumuliform::RakeTask.rule '.cform' => '.rb'
139
+ ```
140
+
141
+ To transform `filename.rb` into `filename.cform`:
142
+
143
+ ```sh
144
+ $ rake filename.cform
145
+ ```
146
+
147
+ If you haven't used Rake's `rule` tasks before, this [Rake rules article from
148
+ Avdi Grimm][rules] is a good place to start.
149
+
150
+ [rules]: http://devblog.avdi.org/2014/04/23/rake-part-3-rules/
151
+
152
+ You'll almost certainly want something more sophisticated than that. Here's an
153
+ example that declares the standard rule and adds a `FileList` to list the
154
+ targets (CloudFormation templates you want to generate) based on your sources
155
+ (Ruby Cumuliform template files). `rake cform` will transform all `.rb` files
156
+ in the same dir as your `Rakefile` into the corresponding `.cform` files:
157
+
158
+ ```ruby
159
+ require 'cumuliform/rake_task'
160
+
161
+ Cumuliform::RakeTask.rule '.cform' => '.rb'
162
+
163
+ TARGETS = Rake::FileList['*.rb'].ext('.cform')
164
+
165
+ task :cform => TARGETS
166
+ ```
26
167
 
27
- ## Development
168
+ # Development
28
169
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
170
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
171
+ `bin/console` for an interactive prompt that will allow you to experiment.
30
172
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
173
+ To install this gem onto your local machine, run `bundle exec rake install`. To
174
+ release a new version, update the version number in `version.rb`, and then run
175
+ `bundle exec rake release` to create a git tag for the version, push git
176
+ commits and tags, and push the `.gem` file to
177
+ [rubygems.org](https://rubygems.org).
32
178
 
33
179
  ## Contributing
34
180
 
data/Rakefile CHANGED
@@ -6,3 +6,12 @@ begin
6
6
  rescue LoadError
7
7
  end
8
8
 
9
+ EXAMPLES = Rake::FileList.new('examples/**/*.rb')
10
+ EXAMPLE_TARGETS = EXAMPLES.ext('.cform')
11
+
12
+ $:.unshift(File.expand_path('../lib', __FILE__))
13
+ require 'cumuliform/rake_task'
14
+
15
+ Cumuliform::RakeTask.rule(".cform" => ".rb")
16
+
17
+ task :examples => EXAMPLE_TARGETS
@@ -0,0 +1,6 @@
1
+ require 'cumuliform'
2
+
3
+ rule ".cform" => ".rb" do |t|
4
+ template = eval(File.read(t.source), binding, t.source)
5
+ File.open(t.name, 'w:utf-8') { |f| f.write(template.to_json) }
6
+ end
@@ -0,0 +1,19 @@
1
+ Cumuliform.template do
2
+ parameter 'AMI' do
3
+ {
4
+ Description: 'The AMI id for our template (defaults to the stock Ubuntu 14.04 image in eu-central-1)',
5
+ Type: 'String',
6
+ Default: 'ami-accff2b1'
7
+ }
8
+ end
9
+
10
+ resource 'MyInstance' do
11
+ {
12
+ Type: 'AWS::EC2::Instance',
13
+ Properties: {
14
+ ImageId: ref('AMI'),
15
+ InstanceType: 'm3.medium'
16
+ }
17
+ }
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'cumuliform/runner'
4
+
5
+ Cumuliform::Runner.process(ARGV[0], ARGV[1])
@@ -0,0 +1,23 @@
1
+ require 'cumuliform/runner'
2
+
3
+ module Cumuliform
4
+ module RakeTask
5
+ extend self
6
+
7
+ class TaskLib < Rake::TaskLib
8
+ include ::Rake::DSL if defined?(::Rake::DSL)
9
+
10
+ def define_rule(rule_args)
11
+ task_body = ->(t, args) {
12
+ Cumuliform::Runner.process(t.source, t.name)
13
+ }
14
+
15
+ rule(*rule_args, &task_body)
16
+ end
17
+ end
18
+
19
+ def rule(*args)
20
+ TaskLib.new.define_rule(args)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ require 'cumuliform'
2
+ require 'pathname'
3
+
4
+ module Cumuliform
5
+ class Runner
6
+ def self.process_io(io)
7
+ mod = Module.new
8
+ path = io.respond_to?(:path) ? io.path : nil
9
+ args = [io.read, path].compact
10
+ template = mod.class_eval(*args)
11
+ end
12
+
13
+ def self.process(input_path, output_path)
14
+ input_path = Pathname.new(input_path)
15
+ output_path = Pathname.new(output_path)
16
+
17
+ template = process_io(input_path.open)
18
+ output_path.open('w:utf-8') { |f| f.write(template.to_json) }
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,3 @@
1
1
  module Cumuliform
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cumuliform
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Patterson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-05-27 00:00:00.000000000 Z
11
+ date: 2015-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -58,7 +58,8 @@ description: |
58
58
  non-existent resources because you have a typo.
59
59
  email:
60
60
  - matt@reprocessed.org
61
- executables: []
61
+ executables:
62
+ - cumuliform
62
63
  extensions: []
63
64
  extra_rdoc_files: []
64
65
  files:
@@ -73,12 +74,17 @@ files:
73
74
  - bin/console
74
75
  - bin/setup
75
76
  - cumuliform.gemspec
77
+ - examples/Rakefile
78
+ - examples/simplest.rb
79
+ - exe/cumuliform
76
80
  - lib/cumuliform.rb
77
81
  - lib/cumuliform/error.rb
78
82
  - lib/cumuliform/fragments.rb
79
83
  - lib/cumuliform/functions.rb
80
84
  - lib/cumuliform/import.rb
81
85
  - lib/cumuliform/output.rb
86
+ - lib/cumuliform/rake_task.rb
87
+ - lib/cumuliform/runner.rb
82
88
  - lib/cumuliform/version.rb
83
89
  homepage: https://www.github.com/tape-tv/cumuliform
84
90
  licenses: