cumuliform 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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: