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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d2df973e8c51854049665bee6f11cff19b8a7aba
4
- data.tar.gz: 2ce1a8f1de5d06e02a47aef292648d79c2c52d21
3
+ metadata.gz: a51b4fe56605619be180809d3e8b936beba108c0
4
+ data.tar.gz: 479573ec4534231f8cc2dad7a1d7396f240c3ed6
5
5
  SHA512:
6
- metadata.gz: 869faae3d938ae4cee9e9e666c25077a308220eaa7544fb8a9e78aeeb6df9870df541871102651a3c45efef0f1258490b50be49f48f6bf68d733e5a57001e85e
7
- data.tar.gz: b2958b04187ad83dea0e22909f07a66219214080ce097715d02a06775987dc0f86e86bd55482305e9cb8de59a86e4e02c371cab6834a6ff809cafcaec9280a16
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.10
4
+ - rvm: 2.1
5
5
  gemfile: spec/support/gemfiles/Gemfile.activesupport-4.0.0
6
- - rvm: 2.2.7
7
- - rvm: 2.3.4
8
- - rvm: 2.4.1
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
  ![StackMaster](/logo.png?raw=true)
2
2
 
3
+ [![License MIT](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://github.com/envato/stack_master/blob/master/LICENSE.md)
4
+ [![Gem Version](https://badge.fury.io/rb/stack_master.svg)](https://badge.fury.io/rb/stack_master)
5
+ [![Build Status](https://travis-ci.org/envato/stack_master.svg?branch=master)](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.
@@ -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 "Proposed change set:"
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}.yml")
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}.yml")
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}.yml")
96
+ Dir.glob(File.join(base_dir, 'parameters', "#{underscored_stack_name}.y*ml"))
97
97
  end
98
98
 
99
99
  def underscored_stack_name
@@ -1,3 +1,3 @@
1
1
  module StackMaster
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -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}.yml"
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}.yml"
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.1
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: 2017-12-15 00:00:00.000000000 Z
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