stack_master 0.14.0 → 0.15.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: 8693e4d791f64b4704d3e5b068d0e3a77fa8c6a6
4
- data.tar.gz: 69c0fcb456e40b8dc933ea73697bc194b65e20ea
3
+ metadata.gz: 44ae5dfa519051496de9c2707df2441f8a0a9115
4
+ data.tar.gz: 8f2065b8c59a2a2399f0398a0dc6a8541d864287
5
5
  SHA512:
6
- metadata.gz: 6805b7c93f992d0d83f6728732bf58001e5ebdda5bc2cb59d4438ede7e8ef725feb29f77512b5e3d673210405f7e869d197443b77545c602564f0704efe515ed
7
- data.tar.gz: 42bc841676942028c0f8cc59206e5d7ca3dfb8c38301aa52e543c921eff25bd3afd97f0ba2e1a02bbf386e4d81d34684aa3c71e9e32390e69fa8cc35abb00bbd
6
+ metadata.gz: 50f3472de66c642581c80398f5430c9fcb596f5b973582834a65bfbca589265be7e2951a584e2459f42f2aa9fcdf1fd2c9fd9bfd07dca1397e8007d67641c6f4
7
+ data.tar.gz: 2a2e5221add3e4aa4c3910de36f73d26eb551d63b3272526e5329124d386feccc8566bcbe593a4e49833e8996c7835ab1d577b4e72d70326176fbc5242f45c1e
data/README.md CHANGED
@@ -390,6 +390,37 @@ container_definitions array!(
390
390
  )
391
391
  ```
392
392
 
393
+ ## Compiler Options & Alternate Template Directories
394
+
395
+ StackMaster allows you to separate your stack definitions and parameters from your templates by way of a `template_dir` key in your stack_master.yml.
396
+ You can also pass compiler-specific options to the template compiler to further customize SparkleFormation or CfnDsl's behavior. Combining the 2 lets you move your SFN templates away from your stack definitions. For example, if your project is laid out as:
397
+
398
+ ```
399
+ project-root
400
+ |-- envs
401
+ |-- env-1
402
+ |-- stack_master.yml
403
+ |-- env-2
404
+ |-- stack_master.yml
405
+ |-- sparkle
406
+ |-- templates
407
+ |-- my-stack.rb
408
+ ```
409
+
410
+ Your env-1/stack_master.yml files can reference common templates by setting:
411
+
412
+ ```
413
+ template_dir: ../../sparkle/templates
414
+ stack_defaults:
415
+ compiler_options:
416
+ sparkle_path: ../../sparkle
417
+
418
+ stacks:
419
+ us-east-1:
420
+ my-stack:
421
+ template: my-stack.rb
422
+ ```
423
+
393
424
  ## Commands
394
425
 
395
426
  ```bash
@@ -78,7 +78,7 @@ Feature: Apply command
78
78
  | + "Vpc": { |
79
79
  | Parameters diff: |
80
80
  | KeyName: my-key |
81
- And the output should match /2020-10-29 00:00:00 \+[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
81
+ And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
82
82
  Then the exit status should be 0
83
83
 
84
84
  Scenario: Run apply and don't create the stack
@@ -90,7 +90,7 @@ Feature: Apply command
90
90
  | Parameters diff: |
91
91
  | KeyName: my-key |
92
92
  | aborted |
93
- And the output should not match /2020-10-29 00:00:00 \+[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
93
+ And the output should not match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
94
94
  Then the exit status should be 0
95
95
 
96
96
  Scenario: Run apply with region only and create 2 stacks
@@ -120,11 +120,11 @@ Feature: Apply command
120
120
  | + "Vpc": { |
121
121
  | Parameters diff: |
122
122
  | KeyName: my-key |
123
- And the output should match /2020-10-29 00:00:00 \+[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
124
- And the output should match /2020-10-29 00:00:00 \+[0-9]{4} myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE/
123
+ And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
124
+ And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE/
125
125
  Then the exit status should be 0
126
- And the output should match /2020-10-29 00:00:00 \+[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
127
- And the output should match /2020-10-29 00:00:00 \+[0-9]{4} myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE/
126
+ And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
127
+ And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE/
128
128
  Then the exit status should be 0
129
129
 
130
130
  Scenario: Create stack with --changed
@@ -154,11 +154,11 @@ Feature: Apply command
154
154
  | + "Vpc": { |
155
155
  | Parameters diff: |
156
156
  | KeyName: my-key |
157
- And the output should match /2020-10-29 00:00:00 \+[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
158
- And the output should match /2020-10-29 00:00:00 \+[0-9]{4} myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE/
157
+ And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
158
+ And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE/
159
159
  Then the exit status should be 0
160
- And the output should match /2020-10-29 00:00:00 \+[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
161
- And the output should match /2020-10-29 00:00:00 \+[0-9]{4} myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE/
160
+ And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
161
+ And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE/
162
162
  Then the exit status should be 0
163
163
 
164
164
  Scenario: Update a stack
@@ -324,7 +324,7 @@ Feature: Apply command
324
324
  | + "TestSg": { |
325
325
  | Parameters diff: |
326
326
  | VpcId: vpc-xxxxxx |
327
- And the output should match /2020-10-29 00:00:00 \+[0-9]{4} myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE/
327
+ And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE/
328
328
  Then the exit status should be 0
329
329
 
330
330
  Scenario: Create a stack with a notification ARN and a stack update policy
@@ -68,7 +68,7 @@ Feature: Apply command
68
68
  | + "Vpc": { |
69
69
  | Parameters diff: |
70
70
  | KeyName: my-key |
71
- And the output should match /2020-10-29 00:00:00 \+[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
71
+ And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
72
72
  And an S3 file in bucket "my-bucket" with key "cfn_templates/my-app/myapp_vpc.json" exists with content:
73
73
  """
74
74
  {
@@ -8,7 +8,7 @@ Feature: Delete command
8
8
  | stack_id | event_id | stack_name | logical_resource_id | resource_status | resource_type | timestamp |
9
9
  | 1 | 1 | myapp-vpc | myapp-vpc | DELETE_COMPLETE | AWS::CloudFormation::Stack | 2020-10-29 00:00:00 |
10
10
  When I run `stack_master delete us-east-1 myapp-vpc --trace`
11
- And the output should match /2020-10-29 00:00:00 \+[0-9]{4} myapp-vpc AWS::CloudFormation::Stack DELETE_COMPLETE/
11
+ And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack DELETE_COMPLETE/
12
12
  Then the exit status should be 0
13
13
 
14
14
  Scenario: Run a delete command on a stack that does not exists
@@ -30,4 +30,4 @@ Feature: Events command
30
30
  | 1 | 1 | myapp-vpc | TestSg | CREATE_COMPLETE | AWS::EC2::SecurityGroup | 2020-10-29 00:00:00 |
31
31
  | 1 | 1 | myapp-vpc | myapp-vpc | CREATE_COMPLETE | AWS::CloudFormation::Stack | 2020-10-29 00:00:00 |
32
32
  When I run `stack_master events us-east-1 myapp-vpc --trace`
33
- And the output should match /2020-10-29 00:00:00 \+[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
33
+ And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
@@ -58,5 +58,5 @@ Feature: Region aliases
58
58
  | + "Vpc": { |
59
59
  | Parameters diff: |
60
60
  | KeyName: my-key |
61
- And the output should match /2020-10-29 00:00:00 \+[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
61
+ And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
62
62
  Then the exit status should be 0
@@ -12,6 +12,7 @@ module StackMaster
12
12
 
13
13
  attr_accessor :stacks,
14
14
  :base_dir,
15
+ :template_dir,
15
16
  :stack_defaults,
16
17
  :region_defaults,
17
18
  :region_aliases,
@@ -33,6 +34,7 @@ module StackMaster
33
34
  def initialize(config, base_dir)
34
35
  @config = config
35
36
  @base_dir = base_dir
37
+ @template_dir = config.fetch('template_dir', nil)
36
38
  @stack_defaults = config.fetch('stack_defaults', {})
37
39
  @region_aliases = Utils.underscore_keys_to_hyphen(config.fetch('region_aliases', {}))
38
40
  @region_to_aliases = @region_aliases.inject({}) do |hash, (key, value)|
@@ -108,6 +110,7 @@ module StackMaster
108
110
  'region' => region,
109
111
  'stack_name' => stack_name,
110
112
  'base_dir' => @base_dir,
113
+ 'template_dir' => @template_dir,
111
114
  'additional_parameter_lookup_dirs' => @region_to_aliases[region])
112
115
  @stacks << StackDefinition.new(stack_attributes)
113
116
  end
@@ -63,7 +63,7 @@ module StackMaster
63
63
 
64
64
  def self.generate(stack_definition, config)
65
65
  parameter_hash = ParameterLoader.load(stack_definition.parameter_files)
66
- template_body = TemplateCompiler.compile(config, stack_definition.template_file_path)
66
+ template_body = TemplateCompiler.compile(config, stack_definition.template_file_path, stack_definition.compiler_options)
67
67
  template_format = TemplateUtils.identify_template_format(template_body)
68
68
  parameters = ParameterResolver.resolve(config, stack_definition, parameter_hash)
69
69
  stack_policy_body = if stack_definition.stack_policy_file_path
@@ -7,20 +7,24 @@ module StackMaster
7
7
  :role_arn,
8
8
  :notification_arns,
9
9
  :base_dir,
10
+ :template_dir,
10
11
  :secret_file,
11
12
  :stack_policy_file,
12
13
  :additional_parameter_lookup_dirs,
13
14
  :s3,
14
- :files
15
+ :files,
16
+ :compiler_options
15
17
 
16
18
  include Utils::Initializable
17
19
 
18
20
  def initialize(attributes = {})
19
21
  @additional_parameter_lookup_dirs = []
22
+ @compiler_options = {}
20
23
  @notification_arns = []
21
24
  @s3 = {}
22
25
  @files = []
23
26
  super
27
+ @template_dir ||= File.join(@base_dir, 'templates')
24
28
  end
25
29
 
26
30
  def ==(other)
@@ -35,15 +39,12 @@ module StackMaster
35
39
  @secret_file == other.secret_file &&
36
40
  @stack_policy_file == other.stack_policy_file &&
37
41
  @additional_parameter_lookup_dirs == other.additional_parameter_lookup_dirs &&
38
- @s3 == other.s3
39
- end
40
-
41
- def template_dir
42
- File.join(base_dir, 'templates')
42
+ @s3 == other.s3 &&
43
+ @compiler_options == other.compiler_options
43
44
  end
44
45
 
45
46
  def template_file_path
46
- File.join(template_dir, template)
47
+ File.expand_path(File.join(template_dir, template))
47
48
  end
48
49
 
49
50
  def files_dir
@@ -2,10 +2,10 @@ module StackMaster
2
2
  class TemplateCompiler
3
3
  TemplateCompilationFailed = Class.new(RuntimeError)
4
4
 
5
- def self.compile(config, template_file_path)
5
+ def self.compile(config, template_file_path, compiler_options = {})
6
6
  compiler = template_compiler_for_file(template_file_path, config)
7
7
  compiler.require_dependencies
8
- compiler.compile(template_file_path)
8
+ compiler.compile(template_file_path, compiler_options)
9
9
  rescue
10
10
  raise TemplateCompilationFailed.new("Failed to compile #{template_file_path}.")
11
11
  end
@@ -4,10 +4,10 @@ module StackMaster::TemplateCompilers
4
4
  require 'cfndsl'
5
5
  end
6
6
 
7
- def self.compile(template_file_path)
7
+ def self.compile(template_file_path, compiler_options = {})
8
8
  ::CfnDsl.eval_file_with_extras(template_file_path).to_json
9
9
  end
10
10
 
11
11
  StackMaster::TemplateCompiler.register(:cfndsl, self)
12
12
  end
13
- end
13
+ end
@@ -7,7 +7,7 @@ module StackMaster::TemplateCompilers
7
7
  require 'json'
8
8
  end
9
9
 
10
- def self.compile(template_file_path)
10
+ def self.compile(template_file_path, compiler_options = {})
11
11
  template_body = File.read(template_file_path)
12
12
  if template_body.size > MAX_TEMPLATE_SIZE
13
13
  # Parse the json and rewrite compressed
@@ -19,4 +19,4 @@ module StackMaster::TemplateCompilers
19
19
 
20
20
  StackMaster::TemplateCompiler.register(:json, self)
21
21
  end
22
- end
22
+ end
@@ -5,11 +5,16 @@ module StackMaster::TemplateCompilers
5
5
  require 'stack_master/sparkle_formation/template_file'
6
6
  end
7
7
 
8
- def self.compile(template_file_path)
9
- ::SparkleFormation.sparkle_path = File.dirname(template_file_path)
8
+ def self.compile(template_file_path, compiler_options = {})
9
+ if compiler_options["sparkle_path"]
10
+ ::SparkleFormation.sparkle_path = File.expand_path(compiler_options["sparkle_path"])
11
+ else
12
+ ::SparkleFormation.sparkle_path = File.dirname(template_file_path)
13
+ end
14
+
10
15
  JSON.pretty_generate(::SparkleFormation.compile(template_file_path))
11
16
  end
12
17
 
13
18
  StackMaster::TemplateCompiler.register(:sparkle_formation, self)
14
19
  end
15
- end
20
+ end
@@ -5,7 +5,7 @@ module StackMaster::TemplateCompilers
5
5
  require 'json'
6
6
  end
7
7
 
8
- def self.compile(template_file_path)
8
+ def self.compile(template_file_path, compiler_options = {})
9
9
  File.read(template_file_path)
10
10
  end
11
11
 
@@ -11,7 +11,7 @@ module StackMaster
11
11
 
12
12
  def perform
13
13
  StackMaster.stdout.print "#{@stack_definition.stack_name}: "
14
- template_body = TemplateCompiler.compile(@config, @stack_definition.template_file_path)
14
+ template_body = TemplateCompiler.compile(@config, @stack_definition.template_file_path, @stack_definition.compiler_options)
15
15
  cf.validate_template(template_body: TemplateUtils.maybe_compressed_template_body(template_body))
16
16
  StackMaster.stdout.puts "valid"
17
17
  true
@@ -1,3 +1,3 @@
1
1
  module StackMaster
2
- VERSION = "0.14.0"
2
+ VERSION = "0.15.0"
3
3
  end
@@ -87,7 +87,7 @@ RSpec.describe StackMaster::Stack do
87
87
  before do
88
88
  allow(StackMaster::ParameterLoader).to receive(:load).and_return(parameter_hash)
89
89
  allow(StackMaster::ParameterResolver).to receive(:resolve).and_return(resolved_parameters)
90
- allow(StackMaster::TemplateCompiler).to receive(:compile).with(config, stack_definition.template_file_path).and_return(template_body)
90
+ allow(StackMaster::TemplateCompiler).to receive(:compile).with(config, stack_definition.template_file_path, stack_definition.compiler_options).and_return(template_body)
91
91
  allow(File).to receive(:read).with(stack_definition.stack_policy_file_path).and_return(stack_policy_body)
92
92
  end
93
93
 
@@ -5,7 +5,7 @@ RSpec.describe StackMaster::TemplateCompiler do
5
5
 
6
6
  class TestTemplateCompiler
7
7
  def self.require_dependencies; end
8
- def self.compile(template_file_path); end
8
+ def self.compile(template_file_path, compile_options); end
9
9
  end
10
10
 
11
11
  context 'when a template compiler is registered for the given file type' do
@@ -14,10 +14,16 @@ RSpec.describe StackMaster::TemplateCompiler do
14
14
  }
15
15
 
16
16
  it 'compiles the template using the relevant template compiler' do
17
- expect(TestTemplateCompiler).to receive(:compile).with(template_file_path)
17
+ expect(TestTemplateCompiler).to receive(:compile).with(template_file_path, anything)
18
18
  StackMaster::TemplateCompiler.compile(config, template_file_path)
19
19
  end
20
20
 
21
+ it 'passes compile_options to the template compiler' do
22
+ opts = {foo: 1, bar: true, baz: "meh"}
23
+ expect(TestTemplateCompiler).to receive(:compile).with(template_file_path, opts)
24
+ StackMaster::TemplateCompiler.compile(config, template_file_path, opts)
25
+ end
26
+
21
27
  context 'when template compilation fails' do
22
28
  before { allow(TestTemplateCompiler).to receive(:compile).and_raise(RuntimeError) }
23
29
 
@@ -1,7 +1,7 @@
1
1
  RSpec.describe StackMaster::TemplateCompilers::SparkleFormation do
2
2
  describe '.compile' do
3
3
  def compile
4
- described_class.compile(template_file_path)
4
+ described_class.compile(template_file_path, compiler_options)
5
5
  end
6
6
 
7
7
  before do
@@ -9,6 +9,7 @@ RSpec.describe StackMaster::TemplateCompilers::SparkleFormation do
9
9
  end
10
10
 
11
11
  let(:template_file_path) { '/base_dir/templates/template.rb' }
12
+ let(:compiler_options) { {} }
12
13
 
13
14
  it 'compiles with sparkleformation' do
14
15
  expect(compile).to eq("{\n}")
@@ -18,5 +19,19 @@ RSpec.describe StackMaster::TemplateCompilers::SparkleFormation do
18
19
  compile
19
20
  expect(SparkleFormation.sparkle_path).to eq File.dirname(template_file_path)
20
21
  end
22
+
23
+ context 'with a custom sparkle_path' do
24
+ let(:compiler_options) { { "sparkle_path" => '../foo' } }
25
+
26
+ it 'does not use the default path' do
27
+ compile
28
+ expect(SparkleFormation.sparkle_path).to_not eq File.dirname(template_file_path)
29
+ end
30
+
31
+ it 'expands the given path' do
32
+ compile
33
+ expect(SparkleFormation.sparkle_path).to match %r{^/.+/foo}
34
+ end
35
+ end
21
36
  end
22
- end
37
+ end
data/stack_master.gemspec CHANGED
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
33
33
  spec.add_dependency "erubis"
34
34
  spec.add_dependency "colorize"
35
35
  spec.add_dependency "activesupport", "~> 4.2"
36
- spec.add_dependency "sparkle_formation", "~> 1.1"
36
+ spec.add_dependency "sparkle_formation"
37
37
  spec.add_dependency "table_print"
38
38
  spec.add_dependency "dotgpg"
39
39
  spec.add_dependency "deep_merge"
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: 0.14.0
4
+ version: 0.15.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-03-28 00:00:00.000000000 Z
12
+ date: 2017-04-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -211,16 +211,16 @@ dependencies:
211
211
  name: sparkle_formation
212
212
  requirement: !ruby/object:Gem::Requirement
213
213
  requirements:
214
- - - "~>"
214
+ - - ">="
215
215
  - !ruby/object:Gem::Version
216
- version: '1.1'
216
+ version: '0'
217
217
  type: :runtime
218
218
  prerelease: false
219
219
  version_requirements: !ruby/object:Gem::Requirement
220
220
  requirements:
221
- - - "~>"
221
+ - - ">="
222
222
  - !ruby/object:Gem::Version
223
- version: '1.1'
223
+ version: '0'
224
224
  - !ruby/object:Gem::Dependency
225
225
  name: table_print
226
226
  requirement: !ruby/object:Gem::Requirement
@@ -450,7 +450,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
450
450
  version: '0'
451
451
  requirements: []
452
452
  rubyforge_project:
453
- rubygems_version: 2.6.8
453
+ rubygems_version: 2.6.11
454
454
  signing_key:
455
455
  specification_version: 4
456
456
  summary: StackMaster is a sure-footed way of creating, updating and keeping track