stack_master 1.6.0-x64-mingw32
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 +7 -0
- data/README.md +548 -0
- data/bin/stack_master +17 -0
- data/lib/stack_master.rb +159 -0
- data/lib/stack_master/aws_driver/cloud_formation.rb +41 -0
- data/lib/stack_master/aws_driver/s3.rb +68 -0
- data/lib/stack_master/change_set.rb +109 -0
- data/lib/stack_master/cli.rb +208 -0
- data/lib/stack_master/command.rb +57 -0
- data/lib/stack_master/commands/apply.rb +221 -0
- data/lib/stack_master/commands/delete.rb +53 -0
- data/lib/stack_master/commands/diff.rb +31 -0
- data/lib/stack_master/commands/events.rb +39 -0
- data/lib/stack_master/commands/init.rb +111 -0
- data/lib/stack_master/commands/list_stacks.rb +20 -0
- data/lib/stack_master/commands/outputs.rb +31 -0
- data/lib/stack_master/commands/resources.rb +33 -0
- data/lib/stack_master/commands/status.rb +46 -0
- data/lib/stack_master/commands/terminal_helper.rb +28 -0
- data/lib/stack_master/commands/validate.rb +17 -0
- data/lib/stack_master/config.rb +133 -0
- data/lib/stack_master/ctrl_c.rb +4 -0
- data/lib/stack_master/paged_response_accumulator.rb +29 -0
- data/lib/stack_master/parameter_loader.rb +49 -0
- data/lib/stack_master/parameter_resolver.rb +98 -0
- data/lib/stack_master/parameter_resolvers/ami_finder.rb +36 -0
- data/lib/stack_master/parameter_resolvers/env.rb +18 -0
- data/lib/stack_master/parameter_resolvers/latest_ami.rb +19 -0
- data/lib/stack_master/parameter_resolvers/latest_ami_by_tags.rb +18 -0
- data/lib/stack_master/parameter_resolvers/parameter_store.rb +31 -0
- data/lib/stack_master/parameter_resolvers/secret.rb +52 -0
- data/lib/stack_master/parameter_resolvers/security_group.rb +22 -0
- data/lib/stack_master/parameter_resolvers/sns_topic_name.rb +31 -0
- data/lib/stack_master/parameter_resolvers/stack_output.rb +76 -0
- data/lib/stack_master/prompter.rb +21 -0
- data/lib/stack_master/resolver_array.rb +35 -0
- data/lib/stack_master/security_group_finder.rb +28 -0
- data/lib/stack_master/sns_topic_finder.rb +26 -0
- 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/sparkle_formation/template_file.rb +115 -0
- data/lib/stack_master/stack.rb +105 -0
- data/lib/stack_master/stack_definition.rb +103 -0
- data/lib/stack_master/stack_differ.rb +111 -0
- data/lib/stack_master/stack_events/fetcher.rb +38 -0
- data/lib/stack_master/stack_events/presenter.rb +27 -0
- data/lib/stack_master/stack_events/streamer.rb +68 -0
- data/lib/stack_master/stack_states.rb +34 -0
- data/lib/stack_master/stack_status.rb +61 -0
- data/lib/stack_master/template_compiler.rb +30 -0
- data/lib/stack_master/template_compilers/cfndsl.rb +13 -0
- data/lib/stack_master/template_compilers/json.rb +22 -0
- data/lib/stack_master/template_compilers/sparkle_formation.rb +71 -0
- data/lib/stack_master/template_compilers/yaml.rb +14 -0
- data/lib/stack_master/template_utils.rb +31 -0
- data/lib/stack_master/test_driver/cloud_formation.rb +193 -0
- data/lib/stack_master/test_driver/s3.rb +34 -0
- data/lib/stack_master/testing.rb +9 -0
- data/lib/stack_master/utils.rb +50 -0
- data/lib/stack_master/validator.rb +33 -0
- data/lib/stack_master/version.rb +3 -0
- metadata +457 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'table_print'
|
2
|
+
|
3
|
+
module StackMaster
|
4
|
+
module Commands
|
5
|
+
class ListStacks
|
6
|
+
include Command
|
7
|
+
include Commander::UI
|
8
|
+
include StackMaster::Commands::TerminalHelper
|
9
|
+
|
10
|
+
def initialize(config)
|
11
|
+
@config = config
|
12
|
+
end
|
13
|
+
|
14
|
+
def perform
|
15
|
+
tp.set :max_width, self.window_size
|
16
|
+
tp @config.stacks, :region, :stack_name
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'table_print'
|
2
|
+
|
3
|
+
module StackMaster
|
4
|
+
module Commands
|
5
|
+
class Outputs
|
6
|
+
include Command
|
7
|
+
include Commander::UI
|
8
|
+
include StackMaster::Commands::TerminalHelper
|
9
|
+
|
10
|
+
def initialize(config, stack_definition, options = {})
|
11
|
+
@config = config
|
12
|
+
@stack_definition = stack_definition
|
13
|
+
end
|
14
|
+
|
15
|
+
def perform
|
16
|
+
if stack
|
17
|
+
tp.set :max_width, self.window_size
|
18
|
+
tp stack.outputs, :output_key, :output_value, :description
|
19
|
+
else
|
20
|
+
StackMaster.stdout.puts "Stack doesn't exist"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def stack
|
27
|
+
@stack ||= Stack.find(@stack_definition.region, @stack_definition.stack_name)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module StackMaster
|
2
|
+
module Commands
|
3
|
+
class Resources
|
4
|
+
include Command
|
5
|
+
include Commander::UI
|
6
|
+
|
7
|
+
def initialize(config, stack_definition, options = {})
|
8
|
+
@config = config
|
9
|
+
@stack_definition = stack_definition
|
10
|
+
end
|
11
|
+
|
12
|
+
def perform
|
13
|
+
if stack_resources
|
14
|
+
tp stack_resources, :logical_resource_id, :resource_type, :timestamp, :resource_status, :resource_status_reason, :description
|
15
|
+
else
|
16
|
+
StackMaster.stdout.puts "Stack doesn't exist"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def stack_resources
|
23
|
+
@stack_resources = cf.describe_stack_resources(stack_name: @stack_definition.stack_name).stack_resources
|
24
|
+
rescue Aws::CloudFormation::Errors::ValidationError
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def cf
|
29
|
+
@cf ||= StackMaster.cloud_formation_driver
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'table_print'
|
2
|
+
require 'ruby-progressbar'
|
3
|
+
|
4
|
+
module StackMaster
|
5
|
+
module Commands
|
6
|
+
class Status
|
7
|
+
include Command
|
8
|
+
include StackMaster::Commands::TerminalHelper
|
9
|
+
|
10
|
+
def initialize(config, show_progress = true)
|
11
|
+
@config = config
|
12
|
+
@show_progress = show_progress
|
13
|
+
end
|
14
|
+
|
15
|
+
def perform
|
16
|
+
progress if @show_progress
|
17
|
+
status = @config.stacks.map do |stack_definition|
|
18
|
+
stack_status = StackStatus.new(@config, stack_definition)
|
19
|
+
progress.increment if @show_progress
|
20
|
+
{
|
21
|
+
region: stack_definition.region,
|
22
|
+
stack_name: stack_definition.stack_name,
|
23
|
+
stack_status: stack_status.status,
|
24
|
+
different: stack_status.changed_message,
|
25
|
+
}
|
26
|
+
end
|
27
|
+
tp.set :max_width, self.window_size
|
28
|
+
tp.set :io, StackMaster.stdout
|
29
|
+
tp status
|
30
|
+
StackMaster.stdout.puts " * No echo parameters can't be diffed"
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def progress
|
36
|
+
@progress ||= ProgressBar.create(title: "Fetching stack information",
|
37
|
+
total: @config.stacks.size,
|
38
|
+
output: StackMaster.stdout)
|
39
|
+
end
|
40
|
+
|
41
|
+
def sort_params(hash)
|
42
|
+
hash.sort.to_h
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'os'
|
2
|
+
|
3
|
+
module StackMaster
|
4
|
+
module Commands
|
5
|
+
module TerminalHelper
|
6
|
+
def window_size
|
7
|
+
size = ENV.fetch("COLUMNS") { OS.windows? ? windows_window_size : unix_window_size }
|
8
|
+
|
9
|
+
if size.nil? || size == ""
|
10
|
+
80
|
11
|
+
else
|
12
|
+
size.to_i
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def unix_window_size
|
17
|
+
`tput cols`.chomp
|
18
|
+
end
|
19
|
+
|
20
|
+
def windows_window_size
|
21
|
+
columns_regex = %r{^\s+Columns:\s+([0-9]+)$}
|
22
|
+
output = `mode con`
|
23
|
+
columns_line = output.split("\n").select { |line| line.match(columns_regex) }.last
|
24
|
+
columns_line.match(columns_regex)[1]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module StackMaster
|
2
|
+
module Commands
|
3
|
+
class Validate
|
4
|
+
include Command
|
5
|
+
include Commander::UI
|
6
|
+
|
7
|
+
def initialize(config, stack_definition, options = {})
|
8
|
+
@config = config
|
9
|
+
@stack_definition = stack_definition
|
10
|
+
end
|
11
|
+
|
12
|
+
def perform
|
13
|
+
failed unless Validator.valid?(@stack_definition, @config)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'deep_merge/rails_compat'
|
2
|
+
require 'active_support/core_ext/object/deep_dup'
|
3
|
+
|
4
|
+
module StackMaster
|
5
|
+
class Config
|
6
|
+
def self.load!(config_file = 'stack_master.yml')
|
7
|
+
resolved_config_file = search_up_and_chdir(config_file)
|
8
|
+
config = YAML.load(File.read(resolved_config_file))
|
9
|
+
base_dir = File.dirname(File.expand_path(resolved_config_file))
|
10
|
+
new(config, base_dir)
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :stacks,
|
14
|
+
:base_dir,
|
15
|
+
:template_dir,
|
16
|
+
:stack_defaults,
|
17
|
+
:region_defaults,
|
18
|
+
:region_aliases,
|
19
|
+
:template_compilers,
|
20
|
+
|
21
|
+
def self.search_up_and_chdir(config_file)
|
22
|
+
return config_file unless File.dirname(config_file) == "."
|
23
|
+
|
24
|
+
dir = Dir.pwd
|
25
|
+
parent_dir = File.expand_path("..", Dir.pwd)
|
26
|
+
while parent_dir != dir && !File.exists?(File.join(dir, config_file))
|
27
|
+
dir = parent_dir
|
28
|
+
parent_dir = File.expand_path("..", dir)
|
29
|
+
end
|
30
|
+
|
31
|
+
File.join(dir, config_file)
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(config, base_dir)
|
35
|
+
@config = config
|
36
|
+
@base_dir = base_dir
|
37
|
+
@template_dir = config.fetch('template_dir', nil)
|
38
|
+
@stack_defaults = config.fetch('stack_defaults', {})
|
39
|
+
@region_aliases = Utils.underscore_keys_to_hyphen(config.fetch('region_aliases', {}))
|
40
|
+
@region_to_aliases = @region_aliases.inject({}) do |hash, (key, value)|
|
41
|
+
hash[value] ||= []
|
42
|
+
hash[value] << key
|
43
|
+
hash
|
44
|
+
end
|
45
|
+
@region_defaults = normalise_region_defaults(config.fetch('region_defaults', {}))
|
46
|
+
@stacks = []
|
47
|
+
load_template_compilers(config)
|
48
|
+
load_config
|
49
|
+
end
|
50
|
+
|
51
|
+
def filter(region = nil, stack_name = nil)
|
52
|
+
@stacks.select do |s|
|
53
|
+
(region.blank? || s.region == region || s.region == region.gsub('_', '-')) &&
|
54
|
+
(stack_name.blank? || s.stack_name == stack_name || s.stack_name == stack_name.gsub('_', '-'))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def find_stack(region, stack_name)
|
59
|
+
filter(region, stack_name).first
|
60
|
+
end
|
61
|
+
|
62
|
+
def unalias_region(region)
|
63
|
+
@region_aliases.fetch(region) { region }
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
def load_template_compilers(config)
|
68
|
+
@template_compilers = {}
|
69
|
+
populate_template_compilers(config.fetch('template_compilers', {}))
|
70
|
+
merge_defaults_to_user_defined_compilers
|
71
|
+
end
|
72
|
+
|
73
|
+
def merge_defaults_to_user_defined_compilers
|
74
|
+
@template_compilers = default_template_compilers.merge(@template_compilers)
|
75
|
+
end
|
76
|
+
|
77
|
+
def populate_template_compilers user_defined_compilers
|
78
|
+
user_defined_compilers.each do |key, val|
|
79
|
+
@template_compilers[key.to_sym] = val.to_sym
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def default_template_compilers
|
84
|
+
{
|
85
|
+
rb: :sparkle_formation,
|
86
|
+
json: :json,
|
87
|
+
yml: :yaml,
|
88
|
+
yaml: :yaml,
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
def load_config
|
93
|
+
unaliased_stacks = resolve_region_aliases(@config.fetch('stacks'))
|
94
|
+
load_stacks(unaliased_stacks)
|
95
|
+
end
|
96
|
+
|
97
|
+
def resolve_region_aliases(stacks)
|
98
|
+
stacks.inject({}) do |hash, (region, attributes)|
|
99
|
+
hash[unalias_region(region)] = attributes
|
100
|
+
hash
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def load_stacks(stacks)
|
105
|
+
stacks.each do |region, stacks_for_region|
|
106
|
+
region = Utils.underscore_to_hyphen(region)
|
107
|
+
stacks_for_region.each do |stack_name, attributes|
|
108
|
+
stack_name = Utils.underscore_to_hyphen(stack_name)
|
109
|
+
stack_attributes = build_stack_defaults(region).deeper_merge!(attributes).merge(
|
110
|
+
'region' => region,
|
111
|
+
'stack_name' => stack_name,
|
112
|
+
'base_dir' => @base_dir,
|
113
|
+
'template_dir' => @template_dir,
|
114
|
+
'additional_parameter_lookup_dirs' => @region_to_aliases[region])
|
115
|
+
@stacks << StackDefinition.new(stack_attributes)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def build_stack_defaults(region)
|
121
|
+
region_defaults = @region_defaults.fetch(region, {}).deep_dup
|
122
|
+
@stack_defaults.deep_dup.deeper_merge(region_defaults)
|
123
|
+
end
|
124
|
+
|
125
|
+
def normalise_region_defaults(region_defaults)
|
126
|
+
region_defaults.inject({}) do |normalised_aliases, (region_or_alias, value)|
|
127
|
+
region = unalias_region(region_or_alias)
|
128
|
+
normalised_aliases[Utils.underscore_to_hyphen(region)] = value
|
129
|
+
normalised_aliases
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module StackMaster
|
2
|
+
class PagedResponseAccumulator
|
3
|
+
def self.call(*args)
|
4
|
+
new(*args).call
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(cf, method, arguments, accumulator_method)
|
8
|
+
@cf = cf
|
9
|
+
@method = method
|
10
|
+
@arguments = arguments
|
11
|
+
@accumulator_method = accumulator_method
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
book = []
|
16
|
+
next_token = nil
|
17
|
+
first_response = nil
|
18
|
+
begin
|
19
|
+
response = @cf.public_send(@method, @arguments.merge(next_token: next_token))
|
20
|
+
first_response = response if first_response.nil?
|
21
|
+
next_token = response.next_token
|
22
|
+
book += response.public_send(@accumulator_method)
|
23
|
+
end while !next_token.nil?
|
24
|
+
first_response.send("#{@accumulator_method}=", book.reverse)
|
25
|
+
first_response.send(:next_token=, book.reverse)
|
26
|
+
first_response
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'active_support/core_ext/object/deep_dup'
|
2
|
+
|
3
|
+
module StackMaster
|
4
|
+
class ParameterLoader
|
5
|
+
|
6
|
+
COMPILE_TIME_PARAMETERS_KEY = 'compile_time_parameters'
|
7
|
+
|
8
|
+
def self.load(parameter_files)
|
9
|
+
StackMaster.debug 'Searching for parameter files...'
|
10
|
+
parameter_files.reduce({template_parameters: {}, compile_time_parameters: {}}) do |hash, file_name|
|
11
|
+
parameters = load_parameters(file_name)
|
12
|
+
template_parameters = create_template_parameters(parameters)
|
13
|
+
compile_time_parameters = create_compile_time_parameters(parameters)
|
14
|
+
|
15
|
+
merge_and_camelize(hash[:template_parameters], template_parameters)
|
16
|
+
merge_and_camelize(hash[:compile_time_parameters], compile_time_parameters)
|
17
|
+
hash
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def self.load_parameters(file_name)
|
25
|
+
file_exists = File.exists?(file_name)
|
26
|
+
StackMaster.debug file_exists ? " #{file_name} found" : " #{file_name} not found"
|
27
|
+
file_exists ? load_file(file_name) : {}
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.load_file(file_name)
|
31
|
+
YAML.load(File.read(file_name)) || {}
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.create_template_parameters(parameters)
|
35
|
+
parameters.deep_dup.tap do |parameters_clone|
|
36
|
+
parameters_clone.delete(COMPILE_TIME_PARAMETERS_KEY) || parameters_clone.delete(COMPILE_TIME_PARAMETERS_KEY.camelize)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.create_compile_time_parameters(parameters)
|
41
|
+
(parameters[COMPILE_TIME_PARAMETERS_KEY] || parameters[COMPILE_TIME_PARAMETERS_KEY.camelize] || {}).deep_dup
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.merge_and_camelize(hash, parameters)
|
45
|
+
parameters.each { |key, value| hash[key.camelize] = value }
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module StackMaster
|
2
|
+
class ParameterResolver
|
3
|
+
ResolverNotFound = Class.new(StandardError)
|
4
|
+
InvalidParameter = Class.new(StandardError)
|
5
|
+
|
6
|
+
def self.resolve(config, stack_definition, parameters)
|
7
|
+
new(config, stack_definition, parameters).resolve
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(config, stack_definition, parameters)
|
11
|
+
@config = config
|
12
|
+
@stack_definition = stack_definition
|
13
|
+
@parameters = parameters
|
14
|
+
@resolvers = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def resolve
|
18
|
+
@parameters.reduce({}) do |parameters, (key, value)|
|
19
|
+
begin
|
20
|
+
parameters[key] = resolve_parameter_value(key, value)
|
21
|
+
rescue InvalidParameter
|
22
|
+
raise InvalidParameter, "Unable to resolve parameter #{key.inspect} value causing error: #{$!.message}"
|
23
|
+
end
|
24
|
+
parameters
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def require_parameter_resolver(file_name)
|
31
|
+
require "stack_master/parameter_resolvers/#{file_name}"
|
32
|
+
rescue LoadError
|
33
|
+
if file_name == file_name.singularize
|
34
|
+
raise ResolverNotFound.new(file_name)
|
35
|
+
else
|
36
|
+
require_parameter_resolver(file_name.singularize)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def load_parameter_resolver(class_name)
|
41
|
+
# Check if the class name already exists
|
42
|
+
resolver_class_const(class_name)
|
43
|
+
rescue NameError
|
44
|
+
# If it doesn't, try to load it
|
45
|
+
require_parameter_resolver(class_name.underscore)
|
46
|
+
end
|
47
|
+
|
48
|
+
def resolve_parameter_value(key, parameter_value)
|
49
|
+
return parameter_value.to_s if Numeric === parameter_value || parameter_value == true || parameter_value == false
|
50
|
+
return resolve_array_parameter_values(key, parameter_value).join(',') if Array === parameter_value
|
51
|
+
return parameter_value unless Hash === parameter_value
|
52
|
+
validate_parameter_value!(key, parameter_value)
|
53
|
+
|
54
|
+
resolver_name = parameter_value.keys.first.to_s
|
55
|
+
load_parameter_resolver(resolver_name)
|
56
|
+
|
57
|
+
value = parameter_value.values.first
|
58
|
+
resolver_class_name = resolver_name.camelize
|
59
|
+
call_resolver(resolver_class_name, value)
|
60
|
+
rescue Aws::CloudFormation::Errors::ValidationError
|
61
|
+
raise InvalidParameter, $!.message
|
62
|
+
end
|
63
|
+
|
64
|
+
def resolve_array_parameter_values(key, parameter_values)
|
65
|
+
parameter_values.reduce([]) do |values, parameter_value|
|
66
|
+
values << resolve_parameter_value(key, parameter_value)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def call_resolver(class_name, value)
|
71
|
+
resolver_class(class_name).resolve(value)
|
72
|
+
end
|
73
|
+
|
74
|
+
def resolver_class_name(class_name)
|
75
|
+
"StackMaster::ParameterResolvers::#{class_name.camelize}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def resolver_class_const(class_name)
|
79
|
+
Kernel.const_get(resolver_class_name(class_name))
|
80
|
+
end
|
81
|
+
|
82
|
+
def resolver_class(class_name)
|
83
|
+
@resolvers.fetch(class_name) do
|
84
|
+
begin
|
85
|
+
@resolvers[class_name] = resolver_class_const(class_name).new(@config, @stack_definition)
|
86
|
+
rescue NameError
|
87
|
+
raise ResolverNotFound, "Could not find parameter resolver called #{class_name}, please double check your configuration"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def validate_parameter_value!(key, parameter_value)
|
93
|
+
if parameter_value.keys.size != 1
|
94
|
+
raise InvalidParameter, "#{key} hash contained more than one key: #{parameter_value.inspect}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|