stack_master 0.14.0 → 0.15.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: 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