stack_master 0.17.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
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