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