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.
- checksums.yaml +4 -4
- data/.travis.yml +7 -5
- data/README.md +15 -0
- data/features/apply.feature +0 -1
- data/features/apply_with_compile_time_parameters.feature +93 -0
- data/lib/stack_master/parameter_loader.rb +41 -12
- data/lib/stack_master/sparkle_formation/compile_time/allowed_pattern_validator.rb +35 -0
- data/lib/stack_master/sparkle_formation/compile_time/allowed_values_validator.rb +37 -0
- data/lib/stack_master/sparkle_formation/compile_time/definitions_validator.rb +33 -0
- data/lib/stack_master/sparkle_formation/compile_time/empty_validator.rb +32 -0
- data/lib/stack_master/sparkle_formation/compile_time/max_length_validator.rb +36 -0
- data/lib/stack_master/sparkle_formation/compile_time/max_size_validator.rb +36 -0
- data/lib/stack_master/sparkle_formation/compile_time/min_length_validator.rb +36 -0
- data/lib/stack_master/sparkle_formation/compile_time/min_size_validator.rb +36 -0
- data/lib/stack_master/sparkle_formation/compile_time/number_validator.rb +35 -0
- data/lib/stack_master/sparkle_formation/compile_time/parameters_validator.rb +27 -0
- data/lib/stack_master/sparkle_formation/compile_time/state_builder.rb +32 -0
- data/lib/stack_master/sparkle_formation/compile_time/string_validator.rb +33 -0
- data/lib/stack_master/sparkle_formation/compile_time/value_builder.rb +40 -0
- data/lib/stack_master/sparkle_formation/compile_time/value_validator.rb +40 -0
- data/lib/stack_master/sparkle_formation/compile_time/value_validator_factory.rb +41 -0
- data/lib/stack_master/stack.rb +4 -3
- data/lib/stack_master/template_compiler.rb +2 -2
- data/lib/stack_master/template_compilers/cfndsl.rb +1 -1
- data/lib/stack_master/template_compilers/json.rb +1 -1
- data/lib/stack_master/template_compilers/sparkle_formation.rb +33 -4
- data/lib/stack_master/template_compilers/yaml.rb +1 -1
- data/lib/stack_master/validator.rb +4 -1
- data/lib/stack_master/version.rb +1 -1
- data/spec/spec_helper.rb +3 -0
- data/spec/stack_master/parameter_loader_spec.rb +65 -53
- data/spec/stack_master/sparkle_formation/compile_time/allowed_pattern_validator_spec.rb +47 -0
- data/spec/stack_master/sparkle_formation/compile_time/allowed_values_validator_spec.rb +47 -0
- data/spec/stack_master/sparkle_formation/compile_time/definitions_validator_spec.rb +36 -0
- data/spec/stack_master/sparkle_formation/compile_time/empty_validator_spec.rb +47 -0
- data/spec/stack_master/sparkle_formation/compile_time/max_length_validator_spec.rb +37 -0
- data/spec/stack_master/sparkle_formation/compile_time/max_size_validator_spec.rb +27 -0
- data/spec/stack_master/sparkle_formation/compile_time/min_length_validator_spec.rb +36 -0
- data/spec/stack_master/sparkle_formation/compile_time/min_size_validator_spec.rb +28 -0
- data/spec/stack_master/sparkle_formation/compile_time/number_validator_spec.rb +41 -0
- data/spec/stack_master/sparkle_formation/compile_time/parameters_validator_spec.rb +65 -0
- data/spec/stack_master/sparkle_formation/compile_time/state_builder_spec.rb +28 -0
- data/spec/stack_master/sparkle_formation/compile_time/string_validator_spec.rb +35 -0
- data/spec/stack_master/sparkle_formation/compile_time/value_build_spec.rb +52 -0
- data/spec/stack_master/sparkle_formation/compile_time/value_validator_factory_spec.rb +40 -0
- data/spec/stack_master/stack_spec.rb +15 -13
- data/spec/stack_master/template_compiler_spec.rb +7 -6
- data/spec/stack_master/template_compilers/cfndsl_spec.rb +4 -1
- data/spec/stack_master/template_compilers/json_spec.rb +4 -1
- data/spec/stack_master/template_compilers/sparkle_formation_spec.rb +53 -9
- data/spec/stack_master/template_compilers/yaml_spec.rb +4 -1
- data/spec/stack_master/validator_spec.rb +10 -6
- data/spec/support/gemfiles/Gemfile.activesupport-4.0.0 +5 -0
- data/spec/support/validator_spec.rb +23 -0
- data/stack_master.gemspec +1 -1
- metadata +55 -6
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative 'value_validator'
|
2
|
+
|
3
|
+
module StackMaster
|
4
|
+
module SparkleFormation
|
5
|
+
module CompileTime
|
6
|
+
class MinSizeValidator < ValueValidator
|
7
|
+
|
8
|
+
KEY = :min_size
|
9
|
+
|
10
|
+
def initialize(name, definition, parameter)
|
11
|
+
@name = name
|
12
|
+
@definition = definition
|
13
|
+
@parameter = parameter
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def check_is_valid
|
19
|
+
return true unless @definition[:type] == :number
|
20
|
+
return true unless @definition.key?(KEY)
|
21
|
+
invalid_values.empty?
|
22
|
+
end
|
23
|
+
|
24
|
+
def invalid_values
|
25
|
+
values = build_values(@definition, @parameter)
|
26
|
+
values.select { |value| value.to_f < @definition[KEY].to_f}
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_error
|
30
|
+
"#{@name}:#{invalid_values} must not be lesser than #{KEY}:#{@definition[KEY]}"
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'value_validator'
|
2
|
+
|
3
|
+
module StackMaster
|
4
|
+
module SparkleFormation
|
5
|
+
module CompileTime
|
6
|
+
class NumberValidator < ValueValidator
|
7
|
+
|
8
|
+
def initialize(name, definition, parameter)
|
9
|
+
@name = name
|
10
|
+
@definition = definition
|
11
|
+
@parameter = parameter
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def check_is_valid
|
17
|
+
return true unless @definition[:type] == :number
|
18
|
+
invalid_values.empty?
|
19
|
+
end
|
20
|
+
|
21
|
+
def invalid_values
|
22
|
+
values = build_values(@definition, @parameter)
|
23
|
+
values.reject do |value|
|
24
|
+
value.is_a?(Numeric) || value.is_a?(String) && value.to_s =~ /^(\d+)(\.?(\d+))?$/
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_error
|
29
|
+
"#{@name}:#{invalid_values} are not Numbers"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative 'value_validator_factory'
|
2
|
+
|
3
|
+
module StackMaster
|
4
|
+
module SparkleFormation
|
5
|
+
module CompileTime
|
6
|
+
class ParametersValidator
|
7
|
+
|
8
|
+
def initialize(definitions, parameters)
|
9
|
+
@definitions = definitions
|
10
|
+
@parameters = parameters
|
11
|
+
end
|
12
|
+
|
13
|
+
def validate
|
14
|
+
@definitions.each do |name, definition|
|
15
|
+
parameter = @parameters[name.to_s.camelize]
|
16
|
+
factory = ValueValidatorFactory.new(name, definition, parameter)
|
17
|
+
value_validators = factory.build
|
18
|
+
value_validators.each do |validator|
|
19
|
+
validator.validate
|
20
|
+
raise ArgumentError.new "Invalid compile time parameter: #{validator.error}" unless validator.is_valid
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative 'value_builder'
|
2
|
+
|
3
|
+
module StackMaster
|
4
|
+
module SparkleFormation
|
5
|
+
module CompileTime
|
6
|
+
class StateBuilder
|
7
|
+
|
8
|
+
def initialize(definitions, parameters)
|
9
|
+
@definitions = definitions
|
10
|
+
@parameters = parameters
|
11
|
+
end
|
12
|
+
|
13
|
+
def build
|
14
|
+
state = {}
|
15
|
+
@definitions.each do |name, definition|
|
16
|
+
parameter_key = name.to_s.camelize
|
17
|
+
parameter = @parameters[parameter_key]
|
18
|
+
state[name] = create_value(definition, parameter)
|
19
|
+
end
|
20
|
+
state
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def create_value(definition, parameter)
|
26
|
+
ValueBuilder.new(definition, parameter).build
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative 'value_validator'
|
2
|
+
|
3
|
+
module StackMaster
|
4
|
+
module SparkleFormation
|
5
|
+
module CompileTime
|
6
|
+
class StringValidator < ValueValidator
|
7
|
+
|
8
|
+
def initialize(name, definition, parameter)
|
9
|
+
@name = name
|
10
|
+
@definition = definition
|
11
|
+
@parameter = parameter
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def check_is_valid
|
17
|
+
return true unless @definition[:type] == :string
|
18
|
+
invalid_values.empty?
|
19
|
+
end
|
20
|
+
|
21
|
+
def invalid_values
|
22
|
+
values = build_values(@definition, @parameter)
|
23
|
+
values.reject { |value| value.is_a?(String)}
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_error
|
27
|
+
"#{@name}:#{invalid_values} are not Strings"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module StackMaster
|
2
|
+
module SparkleFormation
|
3
|
+
module CompileTime
|
4
|
+
class ValueBuilder
|
5
|
+
|
6
|
+
def initialize(definition, parameter)
|
7
|
+
@definition = definition
|
8
|
+
@parameter = parameter
|
9
|
+
end
|
10
|
+
|
11
|
+
def build
|
12
|
+
parameter_or_default
|
13
|
+
convert_strings_to_array
|
14
|
+
convert_strings_to_numbers
|
15
|
+
@value
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def parameter_or_default
|
21
|
+
@value = @parameter.nil? ? @definition[:default] : @parameter
|
22
|
+
end
|
23
|
+
|
24
|
+
def convert_strings_to_array
|
25
|
+
if @definition[:multiple] && @value.is_a?(String)
|
26
|
+
@value = @value.split(',').map(&:strip)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def convert_strings_to_numbers
|
31
|
+
if @definition[:type] == :number
|
32
|
+
@value = @value.to_f if @value.is_a?(String)
|
33
|
+
@value = @value.map { |item| item.is_a?(String) ? item.to_f : item } if @value.is_a?(Array)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module StackMaster
|
2
|
+
module SparkleFormation
|
3
|
+
module CompileTime
|
4
|
+
class ValueValidator
|
5
|
+
|
6
|
+
attr_reader :is_valid, :error
|
7
|
+
|
8
|
+
def validate
|
9
|
+
@is_valid = check_is_valid
|
10
|
+
@error = create_error unless @is_valid
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def check_is_valid
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_error
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
|
23
|
+
def build_values(definition, parameter)
|
24
|
+
parameter_or_default = parameter.nil? ? definition[:default] : parameter
|
25
|
+
convert_to_array(definition, parameter_or_default)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def convert_to_array(definition, parameter)
|
31
|
+
if definition[:multiple] && parameter.is_a?(String)
|
32
|
+
return parameter.split(',').map(&:strip)
|
33
|
+
end
|
34
|
+
parameter.is_a?(Array) ? parameter : [parameter]
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative 'empty_validator'
|
2
|
+
require_relative 'string_validator'
|
3
|
+
require_relative 'number_validator'
|
4
|
+
require_relative 'allowed_values_validator'
|
5
|
+
require_relative 'allowed_pattern_validator'
|
6
|
+
require_relative 'max_length_validator'
|
7
|
+
require_relative 'min_length_validator'
|
8
|
+
require_relative 'max_size_validator'
|
9
|
+
require_relative 'min_size_validator'
|
10
|
+
|
11
|
+
module StackMaster
|
12
|
+
module SparkleFormation
|
13
|
+
module CompileTime
|
14
|
+
class ValueValidatorFactory
|
15
|
+
|
16
|
+
VALIDATORS_TYPES = [
|
17
|
+
EmptyValidator,
|
18
|
+
StringValidator,
|
19
|
+
NumberValidator,
|
20
|
+
AllowedValuesValidator,
|
21
|
+
AllowedPatternValidator,
|
22
|
+
MaxLengthValidator,
|
23
|
+
MinLengthValidator,
|
24
|
+
MaxSizeValidator,
|
25
|
+
MinSizeValidator
|
26
|
+
]
|
27
|
+
|
28
|
+
def initialize(name, definition, parameter)
|
29
|
+
@name = name
|
30
|
+
@definition = definition
|
31
|
+
@parameter = parameter
|
32
|
+
end
|
33
|
+
|
34
|
+
def build
|
35
|
+
VALIDATORS_TYPES.map { |validator| validator.new(@name, @definition, @parameter)}
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/stack_master/stack.rb
CHANGED
@@ -63,16 +63,17 @@ module StackMaster
|
|
63
63
|
|
64
64
|
def self.generate(stack_definition, config)
|
65
65
|
parameter_hash = ParameterLoader.load(stack_definition.parameter_files)
|
66
|
-
|
66
|
+
template_parameters = ParameterResolver.resolve(config, stack_definition, parameter_hash[:template_parameters])
|
67
|
+
compile_time_parameters = ParameterResolver.resolve(config, stack_definition, parameter_hash[:compile_time_parameters])
|
68
|
+
template_body = TemplateCompiler.compile(config, stack_definition.template_file_path, compile_time_parameters,stack_definition.compiler_options)
|
67
69
|
template_format = TemplateUtils.identify_template_format(template_body)
|
68
|
-
parameters = ParameterResolver.resolve(config, stack_definition, parameter_hash)
|
69
70
|
stack_policy_body = if stack_definition.stack_policy_file_path
|
70
71
|
File.read(stack_definition.stack_policy_file_path)
|
71
72
|
end
|
72
73
|
new(region: stack_definition.region,
|
73
74
|
stack_name: stack_definition.stack_name,
|
74
75
|
tags: stack_definition.tags,
|
75
|
-
parameters:
|
76
|
+
parameters: template_parameters,
|
76
77
|
template_body: template_body,
|
77
78
|
template_format: template_format,
|
78
79
|
role_arn: stack_definition.role_arn,
|
@@ -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, compiler_options = {})
|
5
|
+
def self.compile(config, template_file_path, compile_time_parameters, compiler_options = {})
|
6
6
|
compiler = template_compiler_for_file(template_file_path, config)
|
7
7
|
compiler.require_dependencies
|
8
|
-
compiler.compile(template_file_path, compiler_options)
|
8
|
+
compiler.compile(template_file_path, compile_time_parameters, compiler_options)
|
9
9
|
rescue
|
10
10
|
raise TemplateCompilationFailed.new("Failed to compile #{template_file_path}.")
|
11
11
|
end
|
@@ -4,7 +4,7 @@ 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, _compile_time_parameters, _compiler_options = {})
|
8
8
|
::CfnDsl.eval_file_with_extras(template_file_path).to_json
|
9
9
|
end
|
10
10
|
|
@@ -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, _compile_time_parameters, _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
|
@@ -1,18 +1,47 @@
|
|
1
|
+
require 'stack_master/sparkle_formation/compile_time/parameters_validator'
|
2
|
+
require 'stack_master/sparkle_formation/compile_time/definitions_validator'
|
3
|
+
require 'stack_master/sparkle_formation/compile_time/state_builder'
|
4
|
+
|
1
5
|
module StackMaster::TemplateCompilers
|
2
6
|
class SparkleFormation
|
7
|
+
|
8
|
+
CompileTime = StackMaster::SparkleFormation::CompileTime
|
9
|
+
|
3
10
|
def self.require_dependencies
|
4
11
|
require 'sparkle_formation'
|
5
12
|
require 'stack_master/sparkle_formation/template_file'
|
6
13
|
end
|
7
14
|
|
8
|
-
def self.compile(template_file_path, compiler_options = {})
|
9
|
-
if compiler_options[
|
10
|
-
::SparkleFormation.sparkle_path = File.expand_path(compiler_options[
|
15
|
+
def self.compile(template_file_path, compile_time_parameters, compiler_options = {})
|
16
|
+
if compiler_options['sparkle_path']
|
17
|
+
::SparkleFormation.sparkle_path = File.expand_path(compiler_options['sparkle_path'])
|
11
18
|
else
|
12
19
|
::SparkleFormation.sparkle_path = File.dirname(template_file_path)
|
13
20
|
end
|
21
|
+
sparkle_template = ::SparkleFormation.compile(template_file_path, :sparkle)
|
22
|
+
definitions = sparkle_template.parameters
|
23
|
+
validate_definitions(definitions)
|
24
|
+
validate_parameters(definitions, compile_time_parameters)
|
25
|
+
|
26
|
+
sparkle_template.compile_time_parameter_setter do
|
27
|
+
sparkle_template.compile_state = create_state(definitions, compile_time_parameters)
|
28
|
+
end
|
29
|
+
|
30
|
+
JSON.pretty_generate(sparkle_template)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def self.validate_definitions(definitions)
|
36
|
+
CompileTime::DefinitionsValidator.new(definitions).validate
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.validate_parameters(definitions, compile_time_parameters)
|
40
|
+
CompileTime::ParametersValidator.new(definitions, compile_time_parameters).validate
|
41
|
+
end
|
14
42
|
|
15
|
-
|
43
|
+
def self.create_state(definitions, compile_time_parameters)
|
44
|
+
CompileTime::StateBuilder.new(definitions, compile_time_parameters).build
|
16
45
|
end
|
17
46
|
|
18
47
|
StackMaster::TemplateCompiler.register(:sparkle_formation, self)
|
@@ -10,8 +10,11 @@ module StackMaster
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def perform
|
13
|
+
parameter_hash = ParameterLoader.load(@stack_definition.parameter_files)
|
14
|
+
compile_time_parameters = ParameterResolver.resolve(@config, @stack_definition, parameter_hash[:compile_time_parameters])
|
15
|
+
|
13
16
|
StackMaster.stdout.print "#{@stack_definition.stack_name}: "
|
14
|
-
template_body = TemplateCompiler.compile(@config, @stack_definition.template_file_path, @stack_definition.compiler_options)
|
17
|
+
template_body = TemplateCompiler.compile(@config, @stack_definition.template_file_path, compile_time_parameters, @stack_definition.compiler_options)
|
15
18
|
cf.validate_template(template_body: TemplateUtils.maybe_compressed_template_body(template_body))
|
16
19
|
StackMaster.stdout.puts "valid"
|
17
20
|
true
|
data/lib/stack_master/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'stack_master'
|
2
2
|
require 'timecop'
|
3
3
|
require 'pry'
|
4
|
+
|
5
|
+
Dir["./spec/support/**/*.rb"].sort.each { |f| require f }
|
6
|
+
|
4
7
|
Aws.config[:stub_responses] = true
|
5
8
|
# This file was generated by the `rspec --init` command. Conventionally, all
|
6
9
|
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|