stack_master 1.0.1 → 1.1.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 +4 -4
- data/.travis.yml +5 -4
- data/README.md +17 -1
- data/features/apply.feature +2 -0
- data/features/apply_with_env_parameters.feature +49 -0
- data/lib/stack_master.rb +1 -0
- data/lib/stack_master/change_set.rb +6 -1
- data/lib/stack_master/parameter_resolvers/env.rb +18 -0
- data/lib/stack_master/stack_definition.rb +3 -3
- data/lib/stack_master/version.rb +1 -1
- data/spec/stack_master/parameter_loader_spec.rb +17 -0
- data/spec/stack_master/parameter_resolvers/env_spec.rb +35 -0
- data/spec/stack_master/stack_definition_spec.rb +35 -2
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a51b4fe56605619be180809d3e8b936beba108c0
|
4
|
+
data.tar.gz: 479573ec4534231f8cc2dad7a1d7396f240c3ed6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c7784db458ab74af7d4b7d1b18c4603c1227d73574d1624d013fded5bb6af8ec2f74239b7d30b50085fb6c5b781f62a46905b89f883fe00a77bc469621cdb8e
|
7
|
+
data.tar.gz: e5244c0803bd55d3462fb02f79d239a6b240fd3ca7dd88649021097bc0b20c9ac97fa5e9070667ef5a5d7e3bcc6f3a94cb2ec733a02329692f3fea66719da605
|
data/.travis.yml
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
language: ruby
|
2
2
|
matrix:
|
3
3
|
include:
|
4
|
-
- rvm: 2.1
|
4
|
+
- rvm: 2.1
|
5
5
|
gemfile: spec/support/gemfiles/Gemfile.activesupport-4.0.0
|
6
|
-
- rvm: 2.2
|
7
|
-
- rvm: 2.3
|
8
|
-
- rvm: 2.4
|
6
|
+
- rvm: 2.2
|
7
|
+
- rvm: 2.3
|
8
|
+
- rvm: 2.4
|
9
|
+
- rvm: 2.5
|
9
10
|
sudo: false
|
10
11
|
script:
|
11
12
|
- bundle exec rake spec features
|
data/README.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|

|
2
2
|
|
3
|
+
[](https://github.com/envato/stack_master/blob/master/LICENSE.md)
|
4
|
+
[](https://badge.fury.io/rb/stack_master)
|
5
|
+
[](https://travis-ci.org/envato/stack_master)
|
6
|
+
|
3
7
|
StackMaster is a CLI tool to manage CloudFormation stacks, with the following features:
|
4
8
|
|
5
9
|
- Synchronous visibility into stack updates. See exactly what is changing and
|
@@ -143,10 +147,13 @@ template_compilers:
|
|
143
147
|
|
144
148
|
## Parameters
|
145
149
|
|
146
|
-
Parameters are loaded from multiple YAML files, merged from the following lookup paths:
|
150
|
+
Parameters are loaded from multiple YAML files, merged from the following lookup paths from bottom to top:
|
147
151
|
|
152
|
+
- parameters/[stack_name].yaml
|
148
153
|
- parameters/[stack_name].yml
|
154
|
+
- parameters/[region]/[underscored_stack_name].yaml
|
149
155
|
- parameters/[region]/[underscored_stack_name].yml
|
156
|
+
- parameters/[region_alias]/[underscored_stack_name].yaml
|
150
157
|
- parameters/[region_alias]/[underscored_stack_name].yml
|
151
158
|
|
152
159
|
A simple parameter file could look like this:
|
@@ -290,6 +297,15 @@ A set of possible attributes is available in the [AWS documentation](https://doc
|
|
290
297
|
|
291
298
|
Any value can be an array of possible matches.
|
292
299
|
|
300
|
+
### Environment Variable
|
301
|
+
|
302
|
+
Lookup an environment variable:
|
303
|
+
|
304
|
+
```yaml
|
305
|
+
db_username:
|
306
|
+
env: DB_USERNAME
|
307
|
+
```
|
308
|
+
|
293
309
|
### Custom parameter resolvers
|
294
310
|
|
295
311
|
New parameter resolvers can be created in a separate gem.
|
data/features/apply.feature
CHANGED
@@ -207,8 +207,10 @@ Feature: Apply command
|
|
207
207
|
| Stack diff: |
|
208
208
|
| - "TestSg2": { |
|
209
209
|
| Parameters diff: No changes |
|
210
|
+
| ======================================== |
|
210
211
|
| Proposed change set: |
|
211
212
|
| Replace |
|
213
|
+
| ======================================== |
|
212
214
|
| Apply change set (y/n)? |
|
213
215
|
Then the exit status should be 0
|
214
216
|
|
@@ -0,0 +1,49 @@
|
|
1
|
+
Feature: Apply command with environment parameter
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given a file named "stack_master.yml" with:
|
5
|
+
"""
|
6
|
+
stacks:
|
7
|
+
us-east-2:
|
8
|
+
vpc:
|
9
|
+
template: vpc.rb
|
10
|
+
"""
|
11
|
+
And a directory named "parameters"
|
12
|
+
And a file named "parameters/vpc.yml" with:
|
13
|
+
"""
|
14
|
+
vpc_cidr:
|
15
|
+
env: VPC_CIDR
|
16
|
+
"""
|
17
|
+
And a directory named "templates"
|
18
|
+
And a file named "templates/vpc.rb" with:
|
19
|
+
"""
|
20
|
+
SparkleFormation.new(:vpc) do
|
21
|
+
|
22
|
+
parameters.vpc_cidr do
|
23
|
+
type 'String'
|
24
|
+
end
|
25
|
+
|
26
|
+
resources.vpc do
|
27
|
+
type 'AWS::EC2::VPC'
|
28
|
+
properties do
|
29
|
+
cidr_block ref!(:vpc_cidr)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
"""
|
35
|
+
|
36
|
+
Scenario: Run apply and create a new stack
|
37
|
+
Given I stub the following stack events:
|
38
|
+
| stack_id | event_id | stack_name | logical_resource_id | resource_status | resource_type | timestamp |
|
39
|
+
| 1 | 1 | vpc | Vpc | CREATE_COMPLETE | AWS::EC2::VPC | 2020-10-29 00:00:00 |
|
40
|
+
| 1 | 1 | vpc | vpc | CREATE_COMPLETE | AWS::CloudFormation::Stack | 2020-10-29 00:00:00 |
|
41
|
+
And I set the environment variables to:
|
42
|
+
| variable | value |
|
43
|
+
| VPC_CIDR | 10.0.0.0/16 |
|
44
|
+
When I run `stack_master apply us-east-2 vpc --trace`
|
45
|
+
And the output should contain all of these lines:
|
46
|
+
| +--- |
|
47
|
+
| +VpcCidr: 10.0.0.0/16 |
|
48
|
+
And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
|
49
|
+
Then the exit status should be 0
|
data/lib/stack_master.rb
CHANGED
@@ -60,6 +60,7 @@ module StackMaster
|
|
60
60
|
autoload :SecurityGroup, 'stack_master/parameter_resolvers/security_group'
|
61
61
|
autoload :LatestAmiByTags, 'stack_master/parameter_resolvers/latest_ami_by_tags'
|
62
62
|
autoload :LatestAmi, 'stack_master/parameter_resolvers/latest_ami'
|
63
|
+
autoload :Env, 'stack_master/parameter_resolvers/env'
|
63
64
|
end
|
64
65
|
|
65
66
|
module AwsDriver
|
@@ -42,10 +42,15 @@ module StackMaster
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def display(io)
|
45
|
-
io.puts
|
45
|
+
io.puts <<-EOL
|
46
|
+
|
47
|
+
========================================
|
48
|
+
Proposed change set:
|
49
|
+
EOL
|
46
50
|
@response.changes.each do |change|
|
47
51
|
display_resource_change(io, change.resource_change)
|
48
52
|
end
|
53
|
+
io.puts "========================================"
|
49
54
|
end
|
50
55
|
|
51
56
|
def failed?
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module StackMaster
|
2
|
+
module ParameterResolvers
|
3
|
+
class Env < Resolver
|
4
|
+
|
5
|
+
def initialize(config, stack_definition)
|
6
|
+
@config = config
|
7
|
+
@stack_definition = stack_definition
|
8
|
+
end
|
9
|
+
|
10
|
+
def resolve(value)
|
11
|
+
environment_variable = ENV[value]
|
12
|
+
raise ArgumentError, "The environment variable #{value} is not set" if environment_variable.nil?
|
13
|
+
environment_variable
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -84,16 +84,16 @@ module StackMaster
|
|
84
84
|
def additional_parameter_lookup_file_paths
|
85
85
|
return unless additional_parameter_lookup_dirs
|
86
86
|
additional_parameter_lookup_dirs.map do |a|
|
87
|
-
File.join(base_dir, 'parameters', a, "#{underscored_stack_name}.
|
87
|
+
Dir.glob(File.join(base_dir, 'parameters', a, "#{underscored_stack_name}.y*ml"))
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
91
|
def region_parameter_file_path
|
92
|
-
File.join(base_dir, 'parameters', "#{region}", "#{underscored_stack_name}.
|
92
|
+
Dir.glob(File.join(base_dir, 'parameters', "#{region}", "#{underscored_stack_name}.y*ml"))
|
93
93
|
end
|
94
94
|
|
95
95
|
def default_parameter_file_path
|
96
|
-
File.join(base_dir, 'parameters', "#{underscored_stack_name}.
|
96
|
+
Dir.glob(File.join(base_dir, 'parameters', "#{underscored_stack_name}.y*ml"))
|
97
97
|
end
|
98
98
|
|
99
99
|
def underscored_stack_name
|
data/lib/stack_master/version.rb
CHANGED
@@ -54,6 +54,23 @@ RSpec.describe StackMaster::ParameterLoader do
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
context 'yml and yaml region parameter files' do
|
58
|
+
let(:stack_file_returns) { {exists: false} }
|
59
|
+
let(:region_file_returns) { {exists: true, read: "Param2: value2"} }
|
60
|
+
let(:region_yaml_file_returns) { {exists: true, read: "Param1: value1\nParam2: valueX"} }
|
61
|
+
let(:region_yaml_file_name) { "/base_dir/parameters/us-east-1/stack_name.yaml" }
|
62
|
+
|
63
|
+
subject(:parameters) { StackMaster::ParameterLoader.load([stack_file_name, region_yaml_file_name, region_file_name]) }
|
64
|
+
|
65
|
+
before do
|
66
|
+
file_mock(region_yaml_file_name, region_yaml_file_returns)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'returns params from the region base stack_name.yml' do
|
70
|
+
expect(parameters).to eq(template_parameters: {'Param1' => 'value1', 'Param2' => 'value2'}, compile_time_parameters: {})
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
57
74
|
context 'compile time parameters' do
|
58
75
|
|
59
76
|
context 'stack parameter file' do
|
@@ -0,0 +1,35 @@
|
|
1
|
+
RSpec.describe StackMaster::ParameterResolvers::Env do
|
2
|
+
|
3
|
+
describe '#resolve' do
|
4
|
+
|
5
|
+
subject(:resolver) { described_class.new(nil, double(region: 'us-east-1')) }
|
6
|
+
let(:environment_variable_name) { 'TEST' }
|
7
|
+
let(:error) { "The environment variable #{environment_variable_name} is not set" }
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
ENV.delete(environment_variable_name)
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'the environment variable is defined' do
|
14
|
+
it 'should return the environment variable value' do
|
15
|
+
ENV[environment_variable_name] = 'a'
|
16
|
+
expect(resolver.resolve(environment_variable_name)).to eq 'a'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'the environment variable is undefined' do
|
21
|
+
it 'should raise and error' do
|
22
|
+
expect { resolver.resolve(environment_variable_name) }
|
23
|
+
.to raise_error(ArgumentError, error)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'the environment variable is defined but empty' do
|
28
|
+
it 'should return the empty string' do
|
29
|
+
ENV[environment_variable_name] = ''
|
30
|
+
expect(resolver.resolve(environment_variable_name)).to eq ''
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -14,23 +14,56 @@ RSpec.describe StackMaster::StackDefinition do
|
|
14
14
|
let(:tags) { {'environment' => 'production'} }
|
15
15
|
let(:base_dir) { '/base_dir' }
|
16
16
|
|
17
|
+
before do
|
18
|
+
allow(Dir).to receive(:glob).with(
|
19
|
+
File.join(base_dir, 'parameters', "#{stack_name}.y*ml")
|
20
|
+
).and_return(
|
21
|
+
[
|
22
|
+
"/base_dir/parameters/#{stack_name}.yaml",
|
23
|
+
"/base_dir/parameters/#{stack_name}.yml",
|
24
|
+
]
|
25
|
+
)
|
26
|
+
|
27
|
+
allow(Dir).to receive(:glob).with(
|
28
|
+
File.join(base_dir, 'parameters', "#{region}", "#{stack_name}.y*ml")
|
29
|
+
).and_return(
|
30
|
+
[
|
31
|
+
"/base_dir/parameters/#{region}/#{stack_name}.yaml",
|
32
|
+
"/base_dir/parameters/#{region}/#{stack_name}.yml",
|
33
|
+
]
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
17
37
|
it 'has default and region specific parameter file locations' do
|
18
38
|
expect(stack_definition.parameter_files).to eq([
|
39
|
+
"/base_dir/parameters/#{stack_name}.yaml",
|
19
40
|
"/base_dir/parameters/#{stack_name}.yml",
|
20
|
-
"/base_dir/parameters/#{region}/#{stack_name}.
|
41
|
+
"/base_dir/parameters/#{region}/#{stack_name}.yaml",
|
42
|
+
"/base_dir/parameters/#{region}/#{stack_name}.yml",
|
21
43
|
])
|
22
44
|
end
|
23
45
|
|
24
46
|
context 'with additional parameter lookup dirs' do
|
25
47
|
before do
|
26
48
|
stack_definition.send(:additional_parameter_lookup_dirs=, ['production'])
|
49
|
+
allow(Dir).to receive(:glob).with(
|
50
|
+
File.join(base_dir, 'parameters', "production", "#{stack_name}.y*ml")
|
51
|
+
).and_return(
|
52
|
+
[
|
53
|
+
"/base_dir/parameters/production/#{stack_name}.yaml",
|
54
|
+
"/base_dir/parameters/production/#{stack_name}.yml",
|
55
|
+
]
|
56
|
+
)
|
27
57
|
end
|
28
58
|
|
29
59
|
it 'includes a parameter lookup dir for it' do
|
30
60
|
expect(stack_definition.parameter_files).to eq([
|
61
|
+
"/base_dir/parameters/#{stack_name}.yaml",
|
31
62
|
"/base_dir/parameters/#{stack_name}.yml",
|
63
|
+
"/base_dir/parameters/#{region}/#{stack_name}.yaml",
|
32
64
|
"/base_dir/parameters/#{region}/#{stack_name}.yml",
|
33
|
-
"/base_dir/parameters/production/#{stack_name}.
|
65
|
+
"/base_dir/parameters/production/#{stack_name}.yaml",
|
66
|
+
"/base_dir/parameters/production/#{stack_name}.yml",
|
34
67
|
])
|
35
68
|
end
|
36
69
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stack_master
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Hodgkiss
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2018-02-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -303,6 +303,7 @@ files:
|
|
303
303
|
- example/simple/templates/myapp_web.rb
|
304
304
|
- features/apply.feature
|
305
305
|
- features/apply_with_compile_time_parameters.feature
|
306
|
+
- features/apply_with_env_parameters.feature
|
306
307
|
- features/apply_with_s3.feature
|
307
308
|
- features/delete.feature
|
308
309
|
- features/diff.feature
|
@@ -339,6 +340,7 @@ files:
|
|
339
340
|
- lib/stack_master/parameter_loader.rb
|
340
341
|
- lib/stack_master/parameter_resolver.rb
|
341
342
|
- lib/stack_master/parameter_resolvers/ami_finder.rb
|
343
|
+
- lib/stack_master/parameter_resolvers/env.rb
|
342
344
|
- lib/stack_master/parameter_resolvers/latest_ami.rb
|
343
345
|
- lib/stack_master/parameter_resolvers/latest_ami_by_tags.rb
|
344
346
|
- lib/stack_master/parameter_resolvers/secret.rb
|
@@ -412,6 +414,7 @@ files:
|
|
412
414
|
- spec/stack_master/parameter_loader_spec.rb
|
413
415
|
- spec/stack_master/parameter_resolver_spec.rb
|
414
416
|
- spec/stack_master/parameter_resolvers/ami_finder_spec.rb
|
417
|
+
- spec/stack_master/parameter_resolvers/env_spec.rb
|
415
418
|
- spec/stack_master/parameter_resolvers/latest_ami_by_tags_spec.rb
|
416
419
|
- spec/stack_master/parameter_resolvers/latest_ami_spec.rb
|
417
420
|
- spec/stack_master/parameter_resolvers/secret_spec.rb
|
@@ -490,6 +493,7 @@ summary: StackMaster is a sure-footed way of creating, updating and keeping trac
|
|
490
493
|
test_files:
|
491
494
|
- features/apply.feature
|
492
495
|
- features/apply_with_compile_time_parameters.feature
|
496
|
+
- features/apply_with_env_parameters.feature
|
493
497
|
- features/apply_with_s3.feature
|
494
498
|
- features/delete.feature
|
495
499
|
- features/diff.feature
|
@@ -526,6 +530,7 @@ test_files:
|
|
526
530
|
- spec/stack_master/parameter_loader_spec.rb
|
527
531
|
- spec/stack_master/parameter_resolver_spec.rb
|
528
532
|
- spec/stack_master/parameter_resolvers/ami_finder_spec.rb
|
533
|
+
- spec/stack_master/parameter_resolvers/env_spec.rb
|
529
534
|
- spec/stack_master/parameter_resolvers/latest_ami_by_tags_spec.rb
|
530
535
|
- spec/stack_master/parameter_resolvers/latest_ami_spec.rb
|
531
536
|
- spec/stack_master/parameter_resolvers/secret_spec.rb
|