kumo_keisei 3.0.4 → 3.0.5.pre.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +160 -4
- data/VERSION +1 -1
- data/lib/kumo_keisei/stack.rb +10 -1
- data/spec/lib/kumo_keisei/stack_spec.rb +63 -6
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d3c673fda643f764f36cdf9e17d130deb9004ae
|
4
|
+
data.tar.gz: b861c435acc83e7eb5e875f262d003dce20cc5fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 293edcc0a2b44381720c8e08c7f13a0e57aa34c321fc4eb94e31e93142ccc9b149bdb72c754cab442f75b47d1754394de9bc3b39bb6629ea4c8c9195b40bef81
|
7
|
+
data.tar.gz: 986d62661c2bb354562ee024492606d905a9931d1cb99627906d6232f5517c92c22b41640a05d2a51b999dc5a9ff68931f60e3d705f2a9c02e79cc3dd376a3e4
|
data/README.md
CHANGED
@@ -22,14 +22,170 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
+
### Basic Usage
|
26
|
+
|
27
|
+
The basic usage will give you a CloudFormation stack named `{application}-{type}-{environment}`. The default type is `nodes`
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
application_name = "myapp"
|
31
|
+
environment_name = "production"
|
32
|
+
my_stack = KumoKeisei::Stack.new(stack_name, environment_name)
|
33
|
+
|
34
|
+
stack_config = {
|
35
|
+
config_path: File.join('/app', 'env', 'config'),
|
36
|
+
template_path: File.join('/app', 'env', 'cloudformation', 'myapp.json'),
|
37
|
+
}
|
38
|
+
|
39
|
+
my_stack.apply! stack_config
|
40
|
+
```
|
41
|
+
|
42
|
+
### Changing the stack type
|
43
|
+
|
44
|
+
Specify the `type` in an options object passed to the `KumoKeisei::Stack` constructor. For example the following will give you a `myapp-vpc-production` stack e.g:
|
45
|
+
```ruby
|
46
|
+
vpc_stack_options = {
|
47
|
+
type: 'vpc'
|
48
|
+
}
|
49
|
+
vpc_stack = KumoKeisei::Stack.new('myapp', 'production', vpc_stack_options)
|
50
|
+
```
|
51
|
+
|
52
|
+
### Timeouts
|
53
|
+
|
54
|
+
You can tune each of the timeouts by passing options to the Stack constructor:
|
55
|
+
```ruby
|
56
|
+
stack_options = {
|
57
|
+
confirmation_timeout: 0.5,
|
58
|
+
waiter_delay: 20,
|
59
|
+
waiter_attempts: 90,
|
60
|
+
}
|
61
|
+
|
62
|
+
KumoKeisei::Stack.new(stack_name, environment_name, stack_options)
|
63
|
+
```
|
64
|
+
|
65
|
+
*confirmation_timeout*: how long to wait for a user to confirm delete actions
|
66
|
+
*waiter_delay*: how long to wait between checking Cfn for completion of delete and update actions
|
67
|
+
*waiter_attempts*: how many times to retry checking that a Cfn delete or update was successful
|
68
|
+
|
69
|
+
### CloudFormation Templates, Parameter Templates and Configuration Files
|
70
|
+
|
71
|
+
The **CloudFormation Template** is a json file (e.g. app.json) describing a related set of Amazon resources using the [CloudFormation DSL](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/gettingstarted.templatebasics.html). You pass the location by specifying the `template_path` in the object passed to `apply!`,
|
72
|
+
|
73
|
+
The **Parameter Template** is a file prescribing the Cfn parameters [Embedded Ruby](http://www.stuartellis.eu/articles/erb/) form. It must be in the same folder holding the CloudFormation Template, named `{app_name}.yml.erb`.
|
74
|
+
|
75
|
+
The **Configuration Files** are a set of files in `yml` format prescribing configuration values for a given environment. They must be in the folder given by `config_path`, in the form of `{environment}.yml` and `{environment}_secrets.yml`
|
76
|
+
|
77
|
+
[KumoKi](https://github.com/redbubble/kumo_ki_gem) will be used to decrypt the _secrets_ files.
|
78
|
+
|
79
|
+
### Configuration Hierarchy
|
80
|
+
|
81
|
+
Configuration will be loaded from the following sources:
|
82
|
+
|
83
|
+
1. `common.yml` and `common_secrets.yml` if they exist.
|
84
|
+
2. `{environment}.yml` and `{environment}_secrets.yml` or `development.yml` and `development_secrets.yml` if environment specific config does not exist.
|
85
|
+
|
86
|
+
### Injecting Configuration
|
87
|
+
|
88
|
+
You can also inject configuration at run time by adding it to the object provided to the `apply!` call:
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
stack_config = {
|
92
|
+
config_path: File.join('/app', 'env', 'config'),
|
93
|
+
template_path: File.join('/app', 'env', 'cloudformation', 'myapp.json'),
|
94
|
+
injected_config: {
|
95
|
+
'Seed' => random_seed,
|
96
|
+
}
|
97
|
+
}
|
98
|
+
stack.apply!(stack_config)
|
99
|
+
```
|
100
|
+
|
101
|
+
### Getting the configuration without an `apply!`
|
102
|
+
|
103
|
+
If you need to inspect the configuration without applying a stack, call `config`:
|
104
|
+
```ruby
|
105
|
+
stack_config = {
|
106
|
+
config_path: File.join('/app', 'env', 'config'),
|
107
|
+
template_path: File.join('/app', 'env', 'cloudformation', 'myapp.json'),
|
108
|
+
injected_config: {
|
109
|
+
'Seed' => random_seed,
|
110
|
+
}
|
111
|
+
}
|
112
|
+
marshalled_config = stack.config(stack_config)
|
113
|
+
if marshalled_config('DB_HOST').start_with? '192.' then
|
114
|
+
...
|
115
|
+
```
|
116
|
+
|
117
|
+
## Upgrading from `KumoKeisei::CloudFormationStack` to `KumoKeisei::Stack`
|
118
|
+
|
119
|
+
`KumoKeisei::CloudFormationStack` is deprecated and should be replaced with a `KumoKeisei::Stack` which encompasses an environment object (`KumoKeisei::EnvironmentConfig`).
|
120
|
+
|
121
|
+
Previously you would have to construct your own `EnvironmentConfig` which would marshal it's configuration, then instantiate a `CloudFormationStack` and conduct operations on it.
|
122
|
+
|
123
|
+
E.g. `apply-env`:
|
124
|
+
```ruby
|
125
|
+
require_relative '../env/cloudformation_stack'
|
126
|
+
|
127
|
+
environment_name = ARGV.fetch(0) rescue raise("Error! No environment name given!")
|
128
|
+
|
129
|
+
stack = CloudFormationStack.new(environment_name)
|
130
|
+
stack.apply
|
131
|
+
```
|
132
|
+
and `environment_config.rb`:
|
133
|
+
```ruby
|
134
|
+
require 'kumo_keisei'
|
135
|
+
|
136
|
+
class CloudFormationStack
|
137
|
+
|
138
|
+
APP_NAME = "fooapp"
|
139
|
+
|
140
|
+
attr_reader :env_name
|
141
|
+
|
142
|
+
def initialize(env_name)
|
143
|
+
@stacks = {}
|
144
|
+
@env_name = env_name
|
145
|
+
end
|
146
|
+
|
147
|
+
def env_vars
|
148
|
+
{}
|
149
|
+
end
|
150
|
+
|
151
|
+
def apply
|
152
|
+
# Inject the VPC and Subnets into the application's environment config
|
153
|
+
foo_config = KumoKeisei::EnvironmentConfig.new(
|
154
|
+
env_name: env_name,
|
155
|
+
config_dir_path: File.expand_path(File.join("..", "..", "env", "config"), __FILE__)
|
156
|
+
)
|
157
|
+
|
158
|
+
foo_stack = create_stack(:foo, foo_config)
|
159
|
+
foo_stack.apply!
|
160
|
+
end
|
161
|
+
...
|
162
|
+
def create_stack(stack_name, environment_config)
|
163
|
+
raise "Stack '#{ stack_name }' already exists!" if @stacks[stack_name]
|
164
|
+
params_template_erb = params_template(stack_name)
|
165
|
+
stack_values = cf_params_json(get_stack_params(params_template_erb, environment_config))
|
166
|
+
write_stack_params_file(stack_values, stack_name)
|
167
|
+
@stacks[stack_name] = KumoKeisei::CloudFormationStack.new(stack_names[stack_name], "./env/cloudformation/#{stack_name}.json", stack_file_params_file_path(stack_name))
|
168
|
+
end
|
169
|
+
...
|
170
|
+
```
|
171
|
+
|
172
|
+
With the new `Stack` object, all you need to do is pass in the location of the template and config as in the above section. New `apply-env`:
|
25
173
|
```ruby
|
26
|
-
|
27
|
-
|
28
|
-
|
174
|
+
require 'kumo_keisei'
|
175
|
+
|
176
|
+
environment_name = ARGV.fetch(0) rescue raise("Error! No environment name given!")
|
29
177
|
|
30
|
-
|
178
|
+
stack_config = {
|
179
|
+
config_path: File.join('/app', 'env', 'config'),
|
180
|
+
template_path: File.join('/app', 'env', 'cloudformation', 'fooapp.json'),
|
181
|
+
}
|
182
|
+
|
183
|
+
stack = KumoKeisei::Stack.new('fooapp', environment_name)
|
184
|
+
stack.apply!(stack_config)
|
31
185
|
```
|
32
186
|
|
187
|
+
|
188
|
+
|
33
189
|
## Dependencies
|
34
190
|
|
35
191
|
#### Ruby Versions
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.0.
|
1
|
+
3.0.5-alpha1
|
data/lib/kumo_keisei/stack.rb
CHANGED
@@ -4,6 +4,7 @@ module KumoKeisei
|
|
4
4
|
class Stack
|
5
5
|
class CreateError < StandardError; end
|
6
6
|
class UpdateError < StandardError; end
|
7
|
+
class UsageError < StandardError; end
|
7
8
|
|
8
9
|
UPDATEABLE_STATUSES = [
|
9
10
|
'UPDATE_ROLLBACK_COMPLETE',
|
@@ -39,6 +40,9 @@ module KumoKeisei
|
|
39
40
|
|
40
41
|
def apply!(stack_config)
|
41
42
|
stack_config.merge!(env_name: @env_name)
|
43
|
+
|
44
|
+
raise UsageError.new('You must provide a :template_path in the stack config hash for an apply! operation') unless stack_config.has_key?(:template_path)
|
45
|
+
|
42
46
|
if updatable?
|
43
47
|
update!(stack_config)
|
44
48
|
else
|
@@ -76,6 +80,11 @@ module KumoKeisei
|
|
76
80
|
!get_stack.nil?
|
77
81
|
end
|
78
82
|
|
83
|
+
def config(stack_config)
|
84
|
+
raise UsageError.new('You must provide a :config_path in the stack config hash to retrieve the stack\'s config') unless stack_config.has_key?(:config_path)
|
85
|
+
environment_config(stack_config).config
|
86
|
+
end
|
87
|
+
|
79
88
|
private
|
80
89
|
|
81
90
|
def transform_logical_resource_id(id)
|
@@ -153,7 +162,7 @@ module KumoKeisei
|
|
153
162
|
end
|
154
163
|
|
155
164
|
def environment_config(stack_config)
|
156
|
-
params_template_path = File.absolute_path(File.join(File.dirname(stack_config[:template_path]), "#{@app_name}.yml.erb"))
|
165
|
+
params_template_path = stack_config.has_key?(:template_path) ? File.absolute_path(File.join(File.dirname(stack_config[:template_path]), "#{@app_name}.yml.erb")) : nil
|
157
166
|
EnvironmentConfig.new(stack_config.merge(params_template_file_path: params_template_path))
|
158
167
|
end
|
159
168
|
|
@@ -40,6 +40,8 @@ describe KumoKeisei::Stack do
|
|
40
40
|
}
|
41
41
|
}
|
42
42
|
|
43
|
+
context "unit tests" do
|
44
|
+
|
43
45
|
before do
|
44
46
|
allow(KumoKeisei::ConsoleJockey).to receive(:flash_message)
|
45
47
|
allow(KumoKeisei::ConsoleJockey).to receive(:write_line).and_return(nil)
|
@@ -73,6 +75,20 @@ describe KumoKeisei::Stack do
|
|
73
75
|
end
|
74
76
|
|
75
77
|
describe "#apply!" do
|
78
|
+
context "when you don't specify the location of the Cfn template" do
|
79
|
+
let(:stack_config) {
|
80
|
+
{
|
81
|
+
config_path: 'config-path',
|
82
|
+
injected_config: { 'VpcId' => 'vpc-id' },
|
83
|
+
env_name: 'non-production'
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
it "complains" do
|
88
|
+
expect { subject.apply!(stack_config) }.to raise_error(KumoKeisei::Stack::UsageError)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
76
92
|
context "when the stack is updatable" do
|
77
93
|
UPDATEABLE_STATUSES = ['UPDATE_ROLLBACK_COMPLETE', 'CREATE_COMPLETE', 'UPDATE_COMPLETE']
|
78
94
|
|
@@ -254,15 +270,56 @@ describe KumoKeisei::Stack do
|
|
254
270
|
end
|
255
271
|
end
|
256
272
|
|
257
|
-
|
258
|
-
|
259
|
-
|
273
|
+
describe "#type" do
|
274
|
+
it "presumes stacks are of type node if the type is not set" do
|
275
|
+
expect(subject.stack_name).to eq("#{app_name}-nodes-#{environment_name}")
|
276
|
+
end
|
277
|
+
|
278
|
+
it "embeds the type into the name of the stack if set" do
|
279
|
+
subject = KumoKeisei::Stack.new(app_name, environment_name, { type: "vpc" } )
|
280
|
+
expect(subject.stack_name).to eq("#{app_name}-vpc-#{environment_name}")
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
describe "#config" do
|
285
|
+
context "when passed a config_path and params_template_file_path" do
|
286
|
+
before do
|
287
|
+
allow(KumoKeisei::EnvironmentConfig).to receive(:new).with(stack_config.merge(params_template_file_path: "#{app_name}.yml.erb")).and_return(double(:environment_config, cf_params: {}, config: { :foo=> 'bar', :baz=> 'qux' }))
|
260
288
|
end
|
261
289
|
|
262
|
-
it "
|
263
|
-
subject
|
264
|
-
expect(subject.stack_name).to eq("#{app_name}-vpc-#{environment_name}")
|
290
|
+
it "will return the results of the nested KumoKeisei::EnvironmentConfig.config" do
|
291
|
+
expect(subject.config(stack_config)).to eq({:foo=> 'bar', :baz=>'qux'})
|
265
292
|
end
|
266
293
|
end
|
267
294
|
|
295
|
+
context "when a config_path and nil for params_template_file_path" do
|
296
|
+
let(:stack_config) {
|
297
|
+
{
|
298
|
+
config_path: 'config-path',
|
299
|
+
env_name: 'non-production'
|
300
|
+
}
|
301
|
+
}
|
302
|
+
|
303
|
+
before do
|
304
|
+
allow(KumoKeisei::EnvironmentConfig).to receive(:new).with(stack_config.merge(params_template_file_path: nil)).and_return(double(:environment_config, cf_params: {}, config: { :foo=> 'bar', :baz=> 'qux' }))
|
305
|
+
end
|
306
|
+
|
307
|
+
it "will return the results of the nested KumoKeisei::EnvironmentConfig.config" do
|
308
|
+
expect(subject.config(stack_config)).to eq({:foo=> 'bar', :baz=>'qux'})
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
context "if not given a stack_config containing a `config_path`" do
|
313
|
+
let(:stack_config) {
|
314
|
+
{
|
315
|
+
}
|
316
|
+
}
|
317
|
+
it "will raise an error" do
|
318
|
+
expect { described_class.new(app_name, environment_name).config(stack_config)}.to raise_error(KumoKeisei::Stack::UsageError)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
268
325
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kumo_keisei
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.5.pre.alpha1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Redbubble
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-07-
|
11
|
+
date: 2016-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk
|
@@ -130,12 +130,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
130
130
|
version: '0'
|
131
131
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
132
|
requirements:
|
133
|
-
- - "
|
133
|
+
- - ">"
|
134
134
|
- !ruby/object:Gem::Version
|
135
|
-
version:
|
135
|
+
version: 1.3.1
|
136
136
|
requirements: []
|
137
137
|
rubyforge_project:
|
138
|
-
rubygems_version: 2.
|
138
|
+
rubygems_version: 2.2.2
|
139
139
|
signing_key:
|
140
140
|
specification_version: 4
|
141
141
|
summary: A collection of utilities for dealing with AWS Cloud Formation.
|