stack_master 0.17.0 → 0.18.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +7 -5
  3. data/README.md +15 -0
  4. data/features/apply.feature +0 -1
  5. data/features/apply_with_compile_time_parameters.feature +93 -0
  6. data/lib/stack_master/parameter_loader.rb +41 -12
  7. data/lib/stack_master/sparkle_formation/compile_time/allowed_pattern_validator.rb +35 -0
  8. data/lib/stack_master/sparkle_formation/compile_time/allowed_values_validator.rb +37 -0
  9. data/lib/stack_master/sparkle_formation/compile_time/definitions_validator.rb +33 -0
  10. data/lib/stack_master/sparkle_formation/compile_time/empty_validator.rb +32 -0
  11. data/lib/stack_master/sparkle_formation/compile_time/max_length_validator.rb +36 -0
  12. data/lib/stack_master/sparkle_formation/compile_time/max_size_validator.rb +36 -0
  13. data/lib/stack_master/sparkle_formation/compile_time/min_length_validator.rb +36 -0
  14. data/lib/stack_master/sparkle_formation/compile_time/min_size_validator.rb +36 -0
  15. data/lib/stack_master/sparkle_formation/compile_time/number_validator.rb +35 -0
  16. data/lib/stack_master/sparkle_formation/compile_time/parameters_validator.rb +27 -0
  17. data/lib/stack_master/sparkle_formation/compile_time/state_builder.rb +32 -0
  18. data/lib/stack_master/sparkle_formation/compile_time/string_validator.rb +33 -0
  19. data/lib/stack_master/sparkle_formation/compile_time/value_builder.rb +40 -0
  20. data/lib/stack_master/sparkle_formation/compile_time/value_validator.rb +40 -0
  21. data/lib/stack_master/sparkle_formation/compile_time/value_validator_factory.rb +41 -0
  22. data/lib/stack_master/stack.rb +4 -3
  23. data/lib/stack_master/template_compiler.rb +2 -2
  24. data/lib/stack_master/template_compilers/cfndsl.rb +1 -1
  25. data/lib/stack_master/template_compilers/json.rb +1 -1
  26. data/lib/stack_master/template_compilers/sparkle_formation.rb +33 -4
  27. data/lib/stack_master/template_compilers/yaml.rb +1 -1
  28. data/lib/stack_master/validator.rb +4 -1
  29. data/lib/stack_master/version.rb +1 -1
  30. data/spec/spec_helper.rb +3 -0
  31. data/spec/stack_master/parameter_loader_spec.rb +65 -53
  32. data/spec/stack_master/sparkle_formation/compile_time/allowed_pattern_validator_spec.rb +47 -0
  33. data/spec/stack_master/sparkle_formation/compile_time/allowed_values_validator_spec.rb +47 -0
  34. data/spec/stack_master/sparkle_formation/compile_time/definitions_validator_spec.rb +36 -0
  35. data/spec/stack_master/sparkle_formation/compile_time/empty_validator_spec.rb +47 -0
  36. data/spec/stack_master/sparkle_formation/compile_time/max_length_validator_spec.rb +37 -0
  37. data/spec/stack_master/sparkle_formation/compile_time/max_size_validator_spec.rb +27 -0
  38. data/spec/stack_master/sparkle_formation/compile_time/min_length_validator_spec.rb +36 -0
  39. data/spec/stack_master/sparkle_formation/compile_time/min_size_validator_spec.rb +28 -0
  40. data/spec/stack_master/sparkle_formation/compile_time/number_validator_spec.rb +41 -0
  41. data/spec/stack_master/sparkle_formation/compile_time/parameters_validator_spec.rb +65 -0
  42. data/spec/stack_master/sparkle_formation/compile_time/state_builder_spec.rb +28 -0
  43. data/spec/stack_master/sparkle_formation/compile_time/string_validator_spec.rb +35 -0
  44. data/spec/stack_master/sparkle_formation/compile_time/value_build_spec.rb +52 -0
  45. data/spec/stack_master/sparkle_formation/compile_time/value_validator_factory_spec.rb +40 -0
  46. data/spec/stack_master/stack_spec.rb +15 -13
  47. data/spec/stack_master/template_compiler_spec.rb +7 -6
  48. data/spec/stack_master/template_compilers/cfndsl_spec.rb +4 -1
  49. data/spec/stack_master/template_compilers/json_spec.rb +4 -1
  50. data/spec/stack_master/template_compilers/sparkle_formation_spec.rb +53 -9
  51. data/spec/stack_master/template_compilers/yaml_spec.rb +4 -1
  52. data/spec/stack_master/validator_spec.rb +10 -6
  53. data/spec/support/gemfiles/Gemfile.activesupport-4.0.0 +5 -0
  54. data/spec/support/validator_spec.rb +23 -0
  55. data/stack_master.gemspec +1 -1
  56. metadata +55 -6
@@ -0,0 +1,41 @@
1
+ RSpec.describe StackMaster::SparkleFormation::CompileTime::NumberValidator do
2
+
3
+ describe '#validate' do
4
+ let(:name) { 'name' }
5
+ let(:error_message) { -> (error, _definition) { "#{name}:#{error} are not Numbers" } }
6
+
7
+ context 'numerical validation' do
8
+ let(:definition) { {type: :number} }
9
+ validate_valid_parameter(1)
10
+ validate_valid_parameter(['1'])
11
+ validate_invalid_parameter(['1.'], ['1.'])
12
+ validate_invalid_parameter(['.1'], ['.1'])
13
+ validate_invalid_parameter(['1.1.1'], ['1.1.1'])
14
+ validate_invalid_parameter(['1a1'], ['1a1'])
15
+ end
16
+
17
+ context 'numerical validation with default' do
18
+ let(:definition) { {type: :number, default: 1} }
19
+ validate_valid_parameter(nil)
20
+ end
21
+
22
+ context 'numerical validation with multiples' do
23
+ let(:definition) { {type: :number, multiple: true} }
24
+ validate_valid_parameter('1,2')
25
+ validate_valid_parameter([1, 2])
26
+ validate_invalid_parameter('1,1.', ['1.'])
27
+ validate_invalid_parameter({}, [{}])
28
+ end
29
+
30
+ context 'numerical validation with multiples and default' do
31
+ let(:definition) { {type: :number, multiple: true, default: '1,2'} }
32
+ validate_valid_parameter(nil)
33
+ end
34
+
35
+ context 'string validation' do
36
+ let(:definition) { {type: :string} }
37
+ validate_valid_parameter('a')
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,65 @@
1
+ RSpec.describe StackMaster::SparkleFormation::CompileTime::ParametersValidator do
2
+
3
+ let(:definitions) {{ip: {type: :string}}}
4
+ let(:parameters) {{'Ip' => '10.0.0.0'}}
5
+ let(:value_validator_factory) {instance_double(StackMaster::SparkleFormation::CompileTime::ValueValidatorFactory)}
6
+ let(:value_validator) {instance_double(StackMaster::SparkleFormation::CompileTime::ValueValidator)}
7
+
8
+ subject {described_class.new(definitions, parameters)}
9
+
10
+ before(:each) do
11
+ allow(StackMaster::SparkleFormation::CompileTime::ValueValidatorFactory)
12
+ .to receive(:new).and_return(value_validator_factory)
13
+ allow(value_validator_factory)
14
+ .to receive(:build).and_return([value_validator])
15
+ allow(value_validator).to receive(:validate)
16
+ allow(value_validator).to receive(:is_valid).and_return(true)
17
+ end
18
+
19
+ describe '#validate' do
20
+
21
+ it('should initialise the ValueValidatorFactory') do
22
+ expect(StackMaster::SparkleFormation::CompileTime::ValueValidatorFactory).to receive(:new).with(:ip, {type: :string}, '10.0.0.0')
23
+ subject.validate
24
+ end
25
+
26
+ it('should build validators') do
27
+ expect(value_validator_factory).to receive(:build)
28
+ subject.validate
29
+ end
30
+
31
+ it('should call validate on all validators') do
32
+ expect(value_validator).to receive(:validate)
33
+ subject.validate
34
+ end
35
+
36
+ context 'when the validators are valid' do
37
+
38
+ before(:each) do
39
+ allow(value_validator).to receive(:is_valid).and_return(true)
40
+ end
41
+
42
+ it('should not raise any error') do
43
+ expect{subject.validate}.to_not raise_error
44
+ end
45
+
46
+ end
47
+
48
+ context 'when the validators are invalid' do
49
+
50
+ let(:error){'error'}
51
+
52
+ before(:each) do
53
+ allow(value_validator).to receive(:is_valid).and_return(false)
54
+ allow(value_validator).to receive(:error).and_return(error)
55
+ end
56
+
57
+ it('should raise an error') do
58
+ expect {subject.validate}.to raise_error(ArgumentError, "Invalid compile time parameter: #{error}")
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,28 @@
1
+ RSpec.describe StackMaster::SparkleFormation::CompileTime::StateBuilder do
2
+
3
+ let(:definitions) {{ip: {type: :string}, size: {type: :number}}}
4
+ let(:ip) {'10.0.0.0'}
5
+ let(:size) {nil}
6
+ let(:parameters) {{'Ip' => ip}}
7
+ let(:ip_builder) {instance_double(StackMaster::SparkleFormation::CompileTime::ValueBuilder)}
8
+ let(:size_builder) {instance_double(StackMaster::SparkleFormation::CompileTime::ValueBuilder)}
9
+
10
+ subject {described_class.new(definitions, parameters)}
11
+
12
+ before(:each) do
13
+ allow(StackMaster::SparkleFormation::CompileTime::ValueBuilder).to receive(:new).with({type: :string}, ip).and_return(ip_builder)
14
+ allow(StackMaster::SparkleFormation::CompileTime::ValueBuilder).to receive(:new).with({type: :number}, size).and_return(size_builder)
15
+ allow(ip_builder).to receive(:build).and_return(ip)
16
+ allow(size_builder).to receive(:build).and_return(size)
17
+ end
18
+
19
+ describe '#build' do
20
+
21
+ it 'should create state' do
22
+ expected = {ip: '10.0.0.0', size: nil}
23
+ expect(subject.build).to eq(expected)
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,35 @@
1
+ RSpec.describe StackMaster::SparkleFormation::CompileTime::StringValidator do
2
+
3
+ describe '#validate' do
4
+ let(:name) { 'name' }
5
+ let(:error_message) { -> (error, _definition) { "#{name}:#{error} are not Strings" } }
6
+
7
+ context 'string validation' do
8
+ let(:definition) { {type: :string} }
9
+ validate_valid_parameter('a')
10
+ validate_valid_parameter([''])
11
+ validate_invalid_parameter({}, [{}])
12
+ end
13
+
14
+ context 'string validation default' do
15
+ let(:definition) { {type: :string, default: 'a'} }
16
+ validate_valid_parameter(nil)
17
+ end
18
+
19
+ context 'string validation with multiples' do
20
+ let(:definition) { {type: :string, multiple: true} }
21
+ validate_valid_parameter('a,b')
22
+ validate_invalid_parameter([{}], [{}])
23
+ end
24
+
25
+ context 'string validation with multiples and default' do
26
+ let(:definition) { {type: :string, multiple: true, default: 'a,a'} }
27
+ validate_valid_parameter(nil)
28
+ end
29
+
30
+ context 'numerical validation' do
31
+ let(:definition) { {type: :number} }
32
+ validate_valid_parameter(1)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,52 @@
1
+ RSpec.describe StackMaster::SparkleFormation::CompileTime::ValueBuilder do
2
+ scenarios= [
3
+ {definition: {type: :string}, parameter: nil, expected: nil},
4
+ {definition: {type: :string}, parameter: 'a', expected: 'a'},
5
+ {definition: {type: :string}, parameter: ['a'], expected: ['a']},
6
+
7
+ {definition: {type: :string, default: 'a'}, parameter: nil, expected: 'a'},
8
+
9
+ {definition: {type: :string, multiple: true}, parameter: 'a', expected: ['a']},
10
+ {definition: {type: :string, multiple: true}, parameter: 'a,b', expected: ['a', 'b']},
11
+ {definition: {type: :string, multiple: true}, parameter: 'a, b', expected: ['a', 'b']},
12
+
13
+ {definition: {type: :string, multiple: true, default: 'a'}, parameter: nil, expected: ['a']},
14
+
15
+ {definition: {type: :number}, parameter: nil, expected: nil},
16
+ {definition: {type: :number}, parameter: 1, expected: 1},
17
+ {definition: {type: :number}, parameter: '1', expected: 1},
18
+ {definition: {type: :number}, parameter: [1], expected: [1]},
19
+ {definition: {type: :number}, parameter: ['1'], expected: [1]},
20
+
21
+ {definition: {type: :number, default: '1'}, parameter: nil, expected: 1},
22
+
23
+ {definition: {type: :number, multiple: true}, parameter: 1, expected: 1},
24
+ {definition: {type: :number, multiple: true}, parameter: '1', expected: [1]},
25
+ {definition: {type: :number, multiple: true}, parameter: '1,2', expected: [1,2]},
26
+ {definition: {type: :number, multiple: true}, parameter: '1, 2', expected: [1,2]},
27
+
28
+ {definition: {type: :number, multiple: true, default: '1'}, parameter: nil, expected: [1]}
29
+ ]
30
+
31
+ describe '#build' do
32
+
33
+ scenarios.each do |scenario|
34
+
35
+ description = scenario.clone.tap {|clone| clone.delete(:expected)}
36
+ context "when #{description}" do
37
+
38
+ definition = scenario[:definition]
39
+ parameter = scenario[:parameter]
40
+ expected = scenario[:expected]
41
+
42
+ it("should have a value of #{expected}") do
43
+ expect(described_class.new(definition, parameter).build).to eq expected
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,40 @@
1
+ RSpec.describe StackMaster::SparkleFormation::CompileTime::ValueValidatorFactory do
2
+
3
+ let(:name) {:ip}
4
+ let(:definition) {{type: :string}}
5
+ let(:parameter) {{'Ip' => '10.0.0.0'}}
6
+
7
+ subject {described_class.new(name, definition, parameter)}
8
+
9
+ describe '#build' do
10
+
11
+ validators = [
12
+ StackMaster::SparkleFormation::CompileTime::EmptyValidator,
13
+ StackMaster::SparkleFormation::CompileTime::StringValidator,
14
+ StackMaster::SparkleFormation::CompileTime::NumberValidator,
15
+ StackMaster::SparkleFormation::CompileTime::AllowedValuesValidator,
16
+ StackMaster::SparkleFormation::CompileTime::AllowedPatternValidator,
17
+ StackMaster::SparkleFormation::CompileTime::MaxLengthValidator,
18
+ StackMaster::SparkleFormation::CompileTime::MinLengthValidator,
19
+ StackMaster::SparkleFormation::CompileTime::MaxSizeValidator,
20
+ StackMaster::SparkleFormation::CompileTime::MinSizeValidator]
21
+
22
+ after(:each){subject.build}
23
+
24
+ validators.each do |validator|
25
+
26
+ it "should build a #{validator} with correct parameters" do
27
+ expect(validator).to receive(:new).with(name, definition, parameter)
28
+ end
29
+
30
+ end
31
+
32
+ it 'should build in the correct order' do
33
+ validators.each do |validator|
34
+ expect(validator).to receive(:new).ordered
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -14,12 +14,12 @@ RSpec.describe StackMaster::Stack do
14
14
  context 'when the stack exists in AWS' do
15
15
  let(:parameters) {
16
16
  [
17
- {parameter_key: 'param1', parameter_value: 'value1'},
18
- {parameter_key: 'param2', parameter_value: 'value2'}
17
+ {parameter_key: 'param1', parameter_value: 'value1'},
18
+ {parameter_key: 'param2', parameter_value: 'value2'}
19
19
  ]
20
20
  }
21
21
  before do
22
- cf.stub_responses(:describe_stacks, stacks: [{ stack_id: stack_id, stack_name: stack_name, creation_time: Time.now, stack_status: 'UPDATE_COMPLETE', parameters: parameters, notification_arns: ['test_arn'], role_arn: 'test_service_role_arn'}])
22
+ cf.stub_responses(:describe_stacks, stacks: [{stack_id: stack_id, stack_name: stack_name, creation_time: Time.now, stack_status: 'UPDATE_COMPLETE', parameters: parameters, notification_arns: ['test_arn'], role_arn: 'test_service_role_arn'}])
23
23
  cf.stub_responses(:get_template, template_body: "{}")
24
24
  cf.stub_responses(:get_stack_policy, stack_policy_body: stack_policy_body)
25
25
  end
@@ -39,7 +39,7 @@ RSpec.describe StackMaster::Stack do
39
39
  it 'sets role_arn' do
40
40
  expect(stack.role_arn).to eq('test_service_role_arn')
41
41
  end
42
-
42
+
43
43
  it 'sets notification_arns' do
44
44
  expect(stack.notification_arns).to eq(['test_arn'])
45
45
  end
@@ -73,12 +73,13 @@ RSpec.describe StackMaster::Stack do
73
73
  end
74
74
 
75
75
  describe '.generate' do
76
- let(:tags) { { 'tag1' => 'value1' } }
76
+ let(:tags) { {'tag1' => 'value1'} }
77
77
  let(:stack_definition) { StackMaster::StackDefinition.new(region: region, stack_name: stack_name, tags: tags, base_dir: '/base_dir', template: template_file_name, notification_arns: ['test_arn'], role_arn: 'test_service_role_arn', stack_policy_file: 'no_replace_rds.json') }
78
78
  let(:config) { StackMaster::Config.new({'stacks' => {}}, '/base_dir') }
79
79
  subject(:stack) { StackMaster::Stack.generate(stack_definition, config) }
80
- let(:parameter_hash) { { 'DbPassword' => { 'secret' => 'db_password' } } }
81
- let(:resolved_parameters) { { 'DbPassword' => 'sdfgjkdhlfjkghdflkjghdflkjg', 'InstanceType' => 't2.medium' } }
80
+ let(:parameter_hash) { {template_parameters: {'DbPassword' => {'secret' => 'db_password'}}, compile_time_parameters: {}} }
81
+ let(:resolved_template_parameters) { {'DbPassword' => 'sdfgjkdhlfjkghdflkjghdflkjg', 'InstanceType' => 't2.medium'} }
82
+ let(:resolved_compile_time_parameters) { {} }
82
83
  let(:template_file_name) { 'template.rb' }
83
84
  let(:template_body) { '{"Parameters": { "VpcId": { "Description": "VPC ID" }, "InstanceType": { "Description": "Instance Type", "Default": "t2.micro" }} }' }
84
85
  let(:template_format) { :json }
@@ -86,8 +87,9 @@ RSpec.describe StackMaster::Stack do
86
87
 
87
88
  before do
88
89
  allow(StackMaster::ParameterLoader).to receive(:load).and_return(parameter_hash)
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, stack_definition.compiler_options).and_return(template_body)
90
+ allow(StackMaster::ParameterResolver).to receive(:resolve).with(config,stack_definition,parameter_hash[:template_parameters]).and_return(resolved_template_parameters)
91
+ allow(StackMaster::ParameterResolver).to receive(:resolve).with(config,stack_definition,parameter_hash[:compile_time_parameters]).and_return(resolved_compile_time_parameters)
92
+ allow(StackMaster::TemplateCompiler).to receive(:compile).with(config, stack_definition.template_file_path, resolved_compile_time_parameters, stack_definition.compiler_options).and_return(template_body)
91
93
  allow(File).to receive(:read).with(stack_definition.stack_policy_file_path).and_return(stack_policy_body)
92
94
  end
93
95
 
@@ -104,7 +106,7 @@ RSpec.describe StackMaster::Stack do
104
106
  end
105
107
 
106
108
  it 'resolves the parameters' do
107
- expect(stack.parameters).to eq resolved_parameters
109
+ expect(stack.parameters).to eq resolved_template_parameters
108
110
  end
109
111
 
110
112
  it 'compiles the template body' do
@@ -114,7 +116,7 @@ RSpec.describe StackMaster::Stack do
114
116
  it 'has role_arn' do
115
117
  expect(stack.role_arn).to eq 'test_service_role_arn'
116
118
  end
117
-
119
+
118
120
  it 'has notification_arns' do
119
121
  expect(stack.notification_arns).to eq ['test_arn']
120
122
  end
@@ -168,13 +170,13 @@ RSpec.describe StackMaster::Stack do
168
170
  let(:stack) { StackMaster::Stack.new(parameters: parameters, template_body: '{}', template_format: :json) }
169
171
 
170
172
  context 'when a parameter has a nil value' do
171
- let(:parameters) { { 'my_param' => nil } }
173
+ let(:parameters) { {'my_param' => nil} }
172
174
 
173
175
  it { should eq true }
174
176
  end
175
177
 
176
178
  context 'when no parameers have a nil value' do
177
- let(:parameters) { { 'my_param' => '1' } }
179
+ let(:parameters) { {'my_param' => '1'} }
178
180
 
179
181
  it { should eq false }
180
182
  end
@@ -2,10 +2,11 @@ RSpec.describe StackMaster::TemplateCompiler do
2
2
  describe '.compile' do
3
3
  let(:config) { double(template_compilers: { fab: :test_template_compiler }) }
4
4
  let(:template_file_path) { '/base_dir/templates/template.fab' }
5
+ let(:compile_time_parameters) { { 'InstanceType' => 't2.medium' } }
5
6
 
6
7
  class TestTemplateCompiler
7
8
  def self.require_dependencies; end
8
- def self.compile(template_file_path, compile_options); end
9
+ def self.compile(template_file_path, compile_time_parameters, compile_options); end
9
10
  end
10
11
 
11
12
  context 'when a template compiler is registered for the given file type' do
@@ -14,21 +15,21 @@ RSpec.describe StackMaster::TemplateCompiler do
14
15
  }
15
16
 
16
17
  it 'compiles the template using the relevant template compiler' do
17
- expect(TestTemplateCompiler).to receive(:compile).with(template_file_path, anything)
18
- StackMaster::TemplateCompiler.compile(config, template_file_path)
18
+ expect(TestTemplateCompiler).to receive(:compile).with(template_file_path, compile_time_parameters, anything)
19
+ StackMaster::TemplateCompiler.compile(config, template_file_path, compile_time_parameters, compile_time_parameters)
19
20
  end
20
21
 
21
22
  it 'passes compile_options to the template compiler' do
22
23
  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)
24
+ expect(TestTemplateCompiler).to receive(:compile).with(template_file_path, compile_time_parameters, opts)
25
+ StackMaster::TemplateCompiler.compile(config, template_file_path, compile_time_parameters,opts)
25
26
  end
26
27
 
27
28
  context 'when template compilation fails' do
28
29
  before { allow(TestTemplateCompiler).to receive(:compile).and_raise(RuntimeError) }
29
30
 
30
31
  it 'raise TemplateCompilationFailed exception' do
31
- expect{ StackMaster::TemplateCompiler.compile(config, template_file_path)
32
+ expect{ StackMaster::TemplateCompiler.compile(config, template_file_path, compile_time_parameters, compile_time_parameters)
32
33
  }.to raise_error(
33
34
  StackMaster::TemplateCompiler::TemplateCompilationFailed,"Failed to compile #{template_file_path}.")
34
35
  end
@@ -1,9 +1,12 @@
1
1
  RSpec.describe StackMaster::TemplateCompilers::Cfndsl do
2
+
3
+ let(:compile_time_parameters) { {'InstanceType' => 't2.medium'} }
4
+
2
5
  before(:all) { described_class.require_dependencies }
3
6
 
4
7
  describe '.compile' do
5
8
  def compile
6
- described_class.compile(template_file_path)
9
+ described_class.compile(template_file_path, compile_time_parameters)
7
10
  end
8
11
 
9
12
  context 'valid cfndsl template' do
@@ -1,7 +1,10 @@
1
1
  RSpec.describe StackMaster::TemplateCompilers::Json do
2
+
3
+ let(:compile_time_parameters) { { 'InstanceType' => 't2.medium' } }
4
+
2
5
  describe '.compile' do
3
6
  def compile
4
- described_class.compile(template_file_path)
7
+ described_class.compile(template_file_path, compile_time_parameters)
5
8
  end
6
9
 
7
10
  let(:template_file_path) { '/base_dir/templates/template.json' }
@@ -1,15 +1,34 @@
1
1
  RSpec.describe StackMaster::TemplateCompilers::SparkleFormation do
2
+
2
3
  describe '.compile' do
3
4
  def compile
4
- described_class.compile(template_file_path, compiler_options)
5
- end
6
-
7
- before do
8
- allow(SparkleFormation).to receive(:compile).with(template_file_path).and_return({})
5
+ described_class.compile(template_file_path, compile_time_parameters, compiler_options)
9
6
  end
10
7
 
11
8
  let(:template_file_path) { '/base_dir/templates/template.rb' }
9
+ let(:compile_time_parameters) { {'Ip' => '10.0.0.0', 'Name' => 'Something'} }
12
10
  let(:compiler_options) { {} }
11
+ let(:compile_time_parameter_definitions) { {} }
12
+
13
+ let(:sparkle_template) { instance_double(::SparkleFormation) }
14
+ let(:definitions_validator) { instance_double(StackMaster::SparkleFormation::CompileTime::DefinitionsValidator) }
15
+ let(:parameters_validator) { instance_double(StackMaster::SparkleFormation::CompileTime::ParametersValidator) }
16
+ let(:state_builder) { instance_double(StackMaster::SparkleFormation::CompileTime::StateBuilder) }
17
+
18
+ before do
19
+ allow(::SparkleFormation).to receive(:compile).with(template_file_path, :sparkle).and_return(sparkle_template)
20
+ allow(StackMaster::SparkleFormation::CompileTime::DefinitionsValidator).to receive(:new).and_return(definitions_validator)
21
+ allow(StackMaster::SparkleFormation::CompileTime::ParametersValidator).to receive(:new).and_return(parameters_validator)
22
+ allow(StackMaster::SparkleFormation::CompileTime::StateBuilder).to receive(:new).and_return(state_builder)
23
+
24
+ allow(sparkle_template).to receive(:parameters).and_return(compile_time_parameter_definitions)
25
+ allow(definitions_validator).to receive(:validate)
26
+ allow(parameters_validator).to receive(:validate)
27
+ allow(state_builder).to receive(:build).and_return({})
28
+ allow(sparkle_template).to receive(:compile_time_parameter_setter).and_yield
29
+ allow(sparkle_template).to receive(:compile_state=)
30
+ allow(sparkle_template).to receive(:to_json).and_return("{\n}")
31
+ end
13
32
 
14
33
  it 'compiles with sparkleformation' do
15
34
  expect(compile).to eq("{\n}")
@@ -17,21 +36,46 @@ RSpec.describe StackMaster::TemplateCompilers::SparkleFormation do
17
36
 
18
37
  it 'sets the appropriate sparkle_path' do
19
38
  compile
20
- expect(SparkleFormation.sparkle_path).to eq File.dirname(template_file_path)
39
+ expect(::SparkleFormation.sparkle_path).to eq File.dirname(template_file_path)
40
+ end
41
+
42
+ it 'should validate the compile time definitions' do
43
+ expect(StackMaster::SparkleFormation::CompileTime::DefinitionsValidator).to receive(:new).with(compile_time_parameter_definitions)
44
+ expect(definitions_validator).to receive(:validate)
45
+ compile
46
+ end
47
+
48
+ it 'should validate the parameters against any compile time definitions' do
49
+ expect(StackMaster::SparkleFormation::CompileTime::ParametersValidator).to receive(:new).with(compile_time_parameter_definitions, compile_time_parameters)
50
+ expect(parameters_validator).to receive(:validate)
51
+ compile
52
+ end
53
+
54
+ it 'should create the compile state' do
55
+ expect(StackMaster::SparkleFormation::CompileTime::StateBuilder).to receive(:new).with(compile_time_parameter_definitions, compile_time_parameters)
56
+ expect(state_builder).to receive(:build)
57
+ compile
58
+ end
59
+
60
+ it 'should set the compile state' do
61
+ expect(sparkle_template).to receive(:compile_state=).with({})
62
+ compile
21
63
  end
22
64
 
23
65
  context 'with a custom sparkle_path' do
24
- let(:compiler_options) { { "sparkle_path" => '../foo' } }
66
+ let(:compiler_options) { {'sparkle_path' => '../foo'} }
25
67
 
26
68
  it 'does not use the default path' do
27
69
  compile
28
- expect(SparkleFormation.sparkle_path).to_not eq File.dirname(template_file_path)
70
+ expect(::SparkleFormation.sparkle_path).to_not eq File.dirname(template_file_path)
29
71
  end
30
72
 
31
73
  it 'expands the given path' do
32
74
  compile
33
- expect(SparkleFormation.sparkle_path).to match %r{^/.+/foo}
75
+ expect(::SparkleFormation.sparkle_path).to match %r{^/.+/foo}
34
76
  end
35
77
  end
78
+
36
79
  end
80
+
37
81
  end