stack_master 2.17.1 → 2.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/README.md +1 -1
- data/bin/stack_master +3 -5
- data/lib/stack_master/aws_driver/cloud_formation.rb +4 -4
- data/lib/stack_master/aws_driver/s3.rb +7 -7
- data/lib/stack_master/change_set.rb +7 -11
- data/lib/stack_master/cli.rb +32 -26
- data/lib/stack_master/command.rb +1 -5
- data/lib/stack_master/commands/apply.rb +34 -19
- data/lib/stack_master/commands/delete.rb +4 -4
- data/lib/stack_master/commands/drift.rb +5 -9
- data/lib/stack_master/commands/events.rb +4 -6
- data/lib/stack_master/commands/init.rb +14 -14
- data/lib/stack_master/commands/lint.rb +1 -1
- data/lib/stack_master/commands/list_stacks.rb +1 -1
- data/lib/stack_master/commands/outputs.rb +1 -1
- data/lib/stack_master/commands/status.rb +4 -4
- data/lib/stack_master/commands/terminal_helper.rb +3 -3
- data/lib/stack_master/commands/tidy.rb +14 -16
- data/lib/stack_master/config.rb +8 -11
- data/lib/stack_master/diff.rb +2 -2
- data/lib/stack_master/parameter_loader.rb +1 -2
- data/lib/stack_master/parameter_resolver.rb +14 -17
- data/lib/stack_master/parameter_resolvers/ami_finder.rb +1 -2
- data/lib/stack_master/parameter_resolvers/ejson.rb +4 -4
- data/lib/stack_master/parameter_resolvers/latest_ami_by_tags.rb +1 -1
- data/lib/stack_master/parameter_resolvers/latest_container.rb +3 -3
- data/lib/stack_master/parameter_resolvers/one_password.rb +5 -5
- data/lib/stack_master/parameter_resolvers/sso_group_id.rb +1 -1
- data/lib/stack_master/parameter_resolvers/stack_output.rb +7 -11
- data/lib/stack_master/parameter_validator.rb +1 -5
- data/lib/stack_master/prompter.rb +1 -1
- data/lib/stack_master/resolver_array.rb +2 -2
- data/lib/stack_master/role_assumer.rb +1 -1
- data/lib/stack_master/security_group_finder.rb +4 -4
- data/lib/stack_master/sns_topic_finder.rb +1 -1
- data/lib/stack_master/sparkle_formation/compile_time/allowed_pattern_validator.rb +1 -1
- data/lib/stack_master/sparkle_formation/compile_time/definitions_validator.rb +1 -1
- data/lib/stack_master/sparkle_formation/compile_time/value_builder.rb +7 -7
- data/lib/stack_master/sparkle_formation/compile_time/value_validator.rb +1 -3
- data/lib/stack_master/sparkle_formation/template_file.rb +2 -2
- data/lib/stack_master/sso_group_id_finder.rb +3 -3
- data/lib/stack_master/stack.rb +6 -4
- data/lib/stack_master/stack_definition.rb +3 -4
- data/lib/stack_master/stack_differ.rb +32 -9
- data/lib/stack_master/template_compilers/json.rb +1 -1
- data/lib/stack_master/template_compilers/sparkle_formation.rb +2 -2
- data/lib/stack_master/template_utils.rb +2 -2
- data/lib/stack_master/test_driver/cloud_formation.rb +11 -3
- data/lib/stack_master/test_driver/s3.rb +2 -3
- data/lib/stack_master/utils.rb +3 -6
- data/lib/stack_master/validator.rb +1 -1
- data/lib/stack_master/version.rb +1 -1
- data/lib/stack_master.rb +1 -1
- metadata +6 -5
|
@@ -4,9 +4,9 @@ module StackMaster
|
|
|
4
4
|
module Commands
|
|
5
5
|
module TerminalHelper
|
|
6
6
|
def window_size
|
|
7
|
-
size = ENV.fetch(
|
|
7
|
+
size = ENV.fetch('COLUMNS') { OS.windows? ? windows_window_size : unix_window_size }
|
|
8
8
|
|
|
9
|
-
if size.nil? || size ==
|
|
9
|
+
if size.nil? || size == ''
|
|
10
10
|
80
|
|
11
11
|
else
|
|
12
12
|
size.to_i
|
|
@@ -18,7 +18,7 @@ module StackMaster
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def windows_window_size
|
|
21
|
-
columns_regex =
|
|
21
|
+
columns_regex = /^\s+Columns:\s+([0-9]+)$/
|
|
22
22
|
output = `mode con`
|
|
23
23
|
columns_line = output.split("\n").select { |line| line.match(columns_regex) }.last
|
|
24
24
|
columns_line.match(columns_regex)[1]
|
|
@@ -8,23 +8,23 @@ module StackMaster
|
|
|
8
8
|
used_templates = []
|
|
9
9
|
used_parameter_files = []
|
|
10
10
|
|
|
11
|
-
templates = Set.new(find_templates
|
|
12
|
-
parameter_files = Set.new(find_parameter_files
|
|
11
|
+
templates = Set.new(find_templates)
|
|
12
|
+
parameter_files = Set.new(find_parameter_files)
|
|
13
13
|
|
|
14
14
|
status = @config.stacks.each do |stack_definition|
|
|
15
15
|
parameter_files.subtract(stack_definition.parameter_files_from_globs)
|
|
16
16
|
template = File.absolute_path(stack_definition.template_file_path)
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
templates.delete(template)
|
|
18
|
+
next unless template
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
templates.delete(template)
|
|
21
|
+
|
|
22
|
+
next if File.exist?(template)
|
|
23
|
+
|
|
24
|
+
StackMaster.stdout.puts(
|
|
25
|
+
"Stack \"#{stack_definition.stack_name}\" in \"#{stack_definition.region}\" " \
|
|
26
|
+
"missing template \"#{rel_path(template)}\""
|
|
27
|
+
)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
templates.each do |path|
|
|
@@ -46,21 +46,19 @@ module StackMaster
|
|
|
46
46
|
# template directories) this won't find the right directory.
|
|
47
47
|
template_dir = @config.template_dir || File.join(@config.base_dir, 'templates')
|
|
48
48
|
|
|
49
|
-
templates = Dir.glob(File.absolute_path(File.join(template_dir, '**',
|
|
49
|
+
templates = Dir.glob(File.absolute_path(File.join(template_dir, '**', '*.{rb,yaml,yml,json}')))
|
|
50
50
|
dynamics_dir = File.join(template_dir, 'dynamics')
|
|
51
51
|
|
|
52
52
|
# Exclude sparkleformation dynamics
|
|
53
53
|
# TODO: Should this filter out anything with 'dynamics', not just the first
|
|
54
54
|
# subdirectory?
|
|
55
|
-
templates
|
|
55
|
+
templates.select do |path|
|
|
56
56
|
!path.start_with?(dynamics_dir)
|
|
57
57
|
end
|
|
58
|
-
|
|
59
|
-
templates
|
|
60
58
|
end
|
|
61
59
|
|
|
62
60
|
def find_parameter_files
|
|
63
|
-
Dir.glob(File.absolute_path(File.join(@config.base_dir,
|
|
61
|
+
Dir.glob(File.absolute_path(File.join(@config.base_dir, 'parameters', '*.{yml,yaml}')))
|
|
64
62
|
end
|
|
65
63
|
end
|
|
66
64
|
end
|
data/lib/stack_master/config.rb
CHANGED
|
@@ -26,13 +26,13 @@ module StackMaster
|
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
def self.search_up_and_chdir(config_file)
|
|
29
|
-
return config_file unless File.dirname(config_file) ==
|
|
29
|
+
return config_file unless File.dirname(config_file) == '.'
|
|
30
30
|
|
|
31
31
|
dir = Dir.pwd
|
|
32
|
-
parent_dir = File.expand_path(
|
|
32
|
+
parent_dir = File.expand_path('..', Dir.pwd)
|
|
33
33
|
while parent_dir != dir && !File.exist?(File.join(dir, config_file))
|
|
34
34
|
dir = parent_dir
|
|
35
|
-
parent_dir = File.expand_path(
|
|
35
|
+
parent_dir = File.expand_path('..', dir)
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
File.join(dir, config_file)
|
|
@@ -45,10 +45,9 @@ module StackMaster
|
|
|
45
45
|
@parameters_dir = config.fetch('parameters_dir', nil)
|
|
46
46
|
@stack_defaults = config.fetch('stack_defaults', {})
|
|
47
47
|
@region_aliases = Utils.underscore_keys_to_hyphen(config.fetch('region_aliases', {}))
|
|
48
|
-
@region_to_aliases = @region_aliases.
|
|
48
|
+
@region_to_aliases = @region_aliases.each_with_object({}) do |(key, value), hash|
|
|
49
49
|
hash[value] ||= []
|
|
50
50
|
hash[value] << key
|
|
51
|
-
hash
|
|
52
51
|
end
|
|
53
52
|
@region_defaults = normalise_region_defaults(config.fetch('region_defaults', {}))
|
|
54
53
|
@stacks = []
|
|
@@ -86,7 +85,7 @@ module StackMaster
|
|
|
86
85
|
@template_compilers = default_template_compilers.merge(@template_compilers)
|
|
87
86
|
end
|
|
88
87
|
|
|
89
|
-
def populate_template_compilers
|
|
88
|
+
def populate_template_compilers(user_defined_compilers)
|
|
90
89
|
user_defined_compilers.each do |key, val|
|
|
91
90
|
@template_compilers[key.to_sym] = val.to_sym
|
|
92
91
|
end
|
|
@@ -98,7 +97,7 @@ module StackMaster
|
|
|
98
97
|
json: :json,
|
|
99
98
|
yml: :yaml,
|
|
100
99
|
yaml: :yaml,
|
|
101
|
-
erb: :yaml_erb
|
|
100
|
+
erb: :yaml_erb
|
|
102
101
|
}
|
|
103
102
|
end
|
|
104
103
|
|
|
@@ -108,9 +107,8 @@ module StackMaster
|
|
|
108
107
|
end
|
|
109
108
|
|
|
110
109
|
def resolve_region_aliases(stacks)
|
|
111
|
-
stacks.
|
|
110
|
+
stacks.each_with_object({}) do |(region, attributes), hash|
|
|
112
111
|
hash[unalias_region(region)] = attributes
|
|
113
|
-
hash
|
|
114
112
|
end
|
|
115
113
|
end
|
|
116
114
|
|
|
@@ -141,10 +139,9 @@ module StackMaster
|
|
|
141
139
|
end
|
|
142
140
|
|
|
143
141
|
def normalise_region_defaults(region_defaults)
|
|
144
|
-
region_defaults.
|
|
142
|
+
region_defaults.each_with_object({}) do |(region_or_alias, value), normalised_aliases|
|
|
145
143
|
region = unalias_region(region_or_alias)
|
|
146
144
|
normalised_aliases[Utils.underscore_to_hyphen(region)] = value
|
|
147
|
-
normalised_aliases
|
|
148
145
|
end
|
|
149
146
|
end
|
|
150
147
|
end
|
data/lib/stack_master/diff.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module StackMaster
|
|
2
2
|
class Diff
|
|
3
|
-
def initialize(name: nil,
|
|
3
|
+
def initialize(before:, after:, name: nil, context: 10_000)
|
|
4
4
|
@name = name
|
|
5
5
|
@before = before
|
|
6
6
|
@after = after
|
|
@@ -10,7 +10,7 @@ module StackMaster
|
|
|
10
10
|
def display
|
|
11
11
|
stdout.print "#{@name} diff: "
|
|
12
12
|
if diff == ''
|
|
13
|
-
stdout.puts
|
|
13
|
+
stdout.puts 'No changes'
|
|
14
14
|
else
|
|
15
15
|
stdout.puts
|
|
16
16
|
display_colorized_diff
|
|
@@ -7,13 +7,12 @@ module StackMaster
|
|
|
7
7
|
def self.load(parameter_files: [], parameters: {})
|
|
8
8
|
StackMaster.debug 'Searching for parameter files...'
|
|
9
9
|
all_parameters = parameter_files.map { |file_name| load_parameters(file_name) } + [parameters]
|
|
10
|
-
all_parameters.
|
|
10
|
+
all_parameters.each_with_object({ template_parameters: {}, compile_time_parameters: {} }) do |parameters, hash|
|
|
11
11
|
template_parameters = create_template_parameters(parameters)
|
|
12
12
|
compile_time_parameters = create_compile_time_parameters(parameters)
|
|
13
13
|
|
|
14
14
|
merge_and_camelize(hash[:template_parameters], template_parameters)
|
|
15
15
|
merge_and_camelize(hash[:compile_time_parameters], compile_time_parameters)
|
|
16
|
-
hash
|
|
17
16
|
end
|
|
18
17
|
end
|
|
19
18
|
|
|
@@ -15,13 +15,12 @@ module StackMaster
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def resolve
|
|
18
|
-
@parameters.
|
|
18
|
+
@parameters.each_with_object({}) do |(key, value), parameters|
|
|
19
19
|
begin
|
|
20
20
|
parameters[key] = resolve_parameter_value(key, value)
|
|
21
21
|
rescue InvalidParameter
|
|
22
22
|
raise InvalidParameter, "Unable to resolve parameter #{key.inspect} value causing error: #{$!.message}"
|
|
23
23
|
end
|
|
24
|
-
parameters
|
|
25
24
|
end
|
|
26
25
|
end
|
|
27
26
|
|
|
@@ -30,11 +29,9 @@ module StackMaster
|
|
|
30
29
|
def require_parameter_resolver(file_name)
|
|
31
30
|
require "stack_master/parameter_resolvers/#{file_name}"
|
|
32
31
|
rescue LoadError
|
|
33
|
-
if file_name == file_name.singularize
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
require_parameter_resolver(file_name.singularize)
|
|
37
|
-
end
|
|
32
|
+
raise ResolverNotFound.new(file_name) if file_name == file_name.singularize
|
|
33
|
+
|
|
34
|
+
require_parameter_resolver(file_name.singularize)
|
|
38
35
|
end
|
|
39
36
|
|
|
40
37
|
def load_parameter_resolver(class_name)
|
|
@@ -46,9 +43,11 @@ module StackMaster
|
|
|
46
43
|
end
|
|
47
44
|
|
|
48
45
|
def resolve_parameter_value(key, parameter_value)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
if parameter_value.is_a?(Numeric) || parameter_value == true || parameter_value == false
|
|
47
|
+
return parameter_value.to_s
|
|
48
|
+
end
|
|
49
|
+
return resolve_array_parameter_values(key, parameter_value).join(',') if parameter_value.is_a?(Array)
|
|
50
|
+
return parameter_value unless parameter_value.is_a?(Hash)
|
|
52
51
|
|
|
53
52
|
resolve_parameter_resolver_hash(key, parameter_value)
|
|
54
53
|
rescue Aws::CloudFormation::Errors::ValidationError
|
|
@@ -73,15 +72,13 @@ module StackMaster
|
|
|
73
72
|
end
|
|
74
73
|
end
|
|
75
74
|
|
|
76
|
-
def assume_role_if_present(account, role, key)
|
|
75
|
+
def assume_role_if_present(account, role, key, &block)
|
|
77
76
|
return yield if account.nil? && role.nil?
|
|
78
77
|
if account.nil? || role.nil?
|
|
79
78
|
raise InvalidParameter, "Both 'account' and 'role' are required to assume role for parameter '#{key}'"
|
|
80
79
|
end
|
|
81
80
|
|
|
82
|
-
role_assumer.assume_role(account, role)
|
|
83
|
-
yield
|
|
84
|
-
end
|
|
81
|
+
role_assumer.assume_role(account, role, &block)
|
|
85
82
|
end
|
|
86
83
|
|
|
87
84
|
def resolve_array_parameter_values(key, parameter_values)
|
|
@@ -114,9 +111,9 @@ module StackMaster
|
|
|
114
111
|
end
|
|
115
112
|
|
|
116
113
|
def validate_parameter_value!(key, parameter_value)
|
|
117
|
-
if parameter_value.keys.size
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
return if parameter_value.keys.size == 1
|
|
115
|
+
|
|
116
|
+
raise InvalidParameter, "#{key} hash contained more than one key: #{parameter_value.inspect}"
|
|
120
117
|
end
|
|
121
118
|
|
|
122
119
|
def role_assumer
|
|
@@ -6,12 +6,11 @@ module StackMaster
|
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def build_filters_from_string(value, prefix = nil)
|
|
9
|
-
|
|
9
|
+
value.split(',').map do |name_with_value|
|
|
10
10
|
name, value = name_with_value.strip.split('=')
|
|
11
11
|
name = prefix ? "#{prefix}:#{name}" : name
|
|
12
12
|
{ name: name, values: [value] }
|
|
13
13
|
end
|
|
14
|
-
filters
|
|
15
14
|
end
|
|
16
15
|
|
|
17
16
|
def build_filters_from_hash(hash)
|
|
@@ -22,10 +22,10 @@ module StackMaster
|
|
|
22
22
|
private
|
|
23
23
|
|
|
24
24
|
def validate_ejson_file_specified
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
return unless @stack_definition.ejson_file.nil?
|
|
26
|
+
|
|
27
|
+
raise ArgumentError, 'No ejson_file defined for stack definition ' \
|
|
28
|
+
"#{@stack_definition.stack_name} in #{@stack_definition.region}"
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def decrypt_ejson_file
|
|
@@ -10,7 +10,7 @@ module StackMaster
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def resolve(value)
|
|
13
|
-
filters = @ami_finder.build_filters_from_string(value, prefix =
|
|
13
|
+
filters = @ami_finder.build_filters_from_string(value, prefix = 'tag')
|
|
14
14
|
@ami_finder.find_latest_ami(filters)&.image_id
|
|
15
15
|
end
|
|
16
16
|
end
|
|
@@ -10,7 +10,7 @@ module StackMaster
|
|
|
10
10
|
|
|
11
11
|
def resolve(parameters)
|
|
12
12
|
if parameters['repository_name'].nil?
|
|
13
|
-
raise ArgumentError,
|
|
13
|
+
raise ArgumentError, 'repository_name parameter is required but was not supplied'
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
@region = parameters['region'] || @stack_definition.region
|
|
@@ -43,8 +43,8 @@ module StackMaster
|
|
|
43
43
|
registry_id: registry_id,
|
|
44
44
|
next_token: next_token,
|
|
45
45
|
filter: {
|
|
46
|
-
tag_status:
|
|
47
|
-
}
|
|
46
|
+
tag_status: 'TAGGED'
|
|
47
|
+
}
|
|
48
48
|
}
|
|
49
49
|
)
|
|
50
50
|
|
|
@@ -16,7 +16,7 @@ module StackMaster
|
|
|
16
16
|
def resolve(params = {})
|
|
17
17
|
if ENV.keys.grep(/OP_SESSION_\w+$/).empty?
|
|
18
18
|
raise OnePasswordNotAbleToAuthenticate,
|
|
19
|
-
|
|
19
|
+
'1password requires the `OP_SESSION_<name>` to be set, (remember to sign in?)'
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
get_items(params)
|
|
@@ -25,7 +25,7 @@ module StackMaster
|
|
|
25
25
|
private
|
|
26
26
|
|
|
27
27
|
def validate_op_installed?
|
|
28
|
-
|
|
28
|
+
`op --version`
|
|
29
29
|
rescue Errno::ENOENT => exception
|
|
30
30
|
raise OnePasswordBinaryNotFound, "The op cli needs to be installed and in the PATH, #{exception}"
|
|
31
31
|
end
|
|
@@ -53,7 +53,7 @@ module StackMaster
|
|
|
53
53
|
|
|
54
54
|
def op_get_item(item, vault)
|
|
55
55
|
validate_op_installed?
|
|
56
|
-
item =
|
|
56
|
+
item = `op get item --vault='#{vault}' '#{item}' 2>&1`
|
|
57
57
|
item if validate_response?(item)
|
|
58
58
|
end
|
|
59
59
|
|
|
@@ -79,9 +79,9 @@ module StackMaster
|
|
|
79
79
|
def get_items(params)
|
|
80
80
|
case params['type']
|
|
81
81
|
when 'password'
|
|
82
|
-
|
|
82
|
+
get_password(params['title'], params['vault'])
|
|
83
83
|
when 'secureNote'
|
|
84
|
-
|
|
84
|
+
get_secure_note(params['title'], params['vault'])
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
end
|
|
@@ -17,18 +17,14 @@ module StackMaster
|
|
|
17
17
|
def resolve(value)
|
|
18
18
|
region, stack_name, output_name = parse!(value)
|
|
19
19
|
stack = find_stack(stack_name, region)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if output
|
|
25
|
-
output.output_value
|
|
26
|
-
else
|
|
27
|
-
raise StackOutputNotFound, "Stack exists (#{stack_name}), but output does not: #{output_name}"
|
|
28
|
-
end
|
|
29
|
-
else
|
|
30
|
-
raise StackNotFound, "Stack in StackOutput not found: #{value}"
|
|
20
|
+
raise StackNotFound, "Stack in StackOutput not found: #{value}" unless stack
|
|
21
|
+
|
|
22
|
+
output = stack.outputs.find do |stack_output|
|
|
23
|
+
stack_output.output_key == output_name.camelize || stack_output.output_key == output_name
|
|
31
24
|
end
|
|
25
|
+
raise StackOutputNotFound, "Stack exists (#{stack_name}), but output does not: #{output_name}" unless output
|
|
26
|
+
|
|
27
|
+
output.output_value
|
|
32
28
|
end
|
|
33
29
|
|
|
34
30
|
private
|
|
@@ -14,11 +14,7 @@ module StackMaster
|
|
|
14
14
|
missing_parameters.each do |parameter_name|
|
|
15
15
|
message << " - #{parameter_name}\n"
|
|
16
16
|
end
|
|
17
|
-
|
|
18
|
-
message << message_for_parameter_globs
|
|
19
|
-
else
|
|
20
|
-
message << message_for_parameter_files
|
|
21
|
-
end
|
|
17
|
+
message << (@stack_definition.parameter_files.empty? ? message_for_parameter_globs : message_for_parameter_files)
|
|
22
18
|
message
|
|
23
19
|
end
|
|
24
20
|
|
|
@@ -10,7 +10,7 @@ module StackMaster
|
|
|
10
10
|
StackMaster.stdin.getch.chomp
|
|
11
11
|
else
|
|
12
12
|
StackMaster.stdout.puts
|
|
13
|
-
StackMaster.stdout.puts
|
|
13
|
+
StackMaster.stdout.puts 'STDOUT or STDIN was not a TTY. Defaulting to no. To force yes use -y'
|
|
14
14
|
'n'
|
|
15
15
|
end
|
|
16
16
|
else
|
|
@@ -13,13 +13,13 @@ module StackMaster
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def resolver_class
|
|
16
|
-
|
|
16
|
+
raise "Method resolver_class not implemented on #{self.class}"
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
class Resolver
|
|
21
21
|
def self.array_resolver(options = {})
|
|
22
|
-
resolver_class ||= Object.const_get(
|
|
22
|
+
resolver_class ||= Object.const_get(name)
|
|
23
23
|
array_resolver_class_name = options[:class_name] || resolver_class.to_s.demodulize.pluralize
|
|
24
24
|
|
|
25
25
|
klass = Class.new(ResolverArray) do
|
|
@@ -15,10 +15,10 @@ module StackMaster
|
|
|
15
15
|
groups = @resource.security_groups({
|
|
16
16
|
filters: [
|
|
17
17
|
{
|
|
18
|
-
name:
|
|
19
|
-
values: [reference]
|
|
20
|
-
}
|
|
21
|
-
]
|
|
18
|
+
name: 'group-name',
|
|
19
|
+
values: [reference]
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
22
|
})
|
|
23
23
|
|
|
24
24
|
raise SecurityGroupNotFound, "No security group with name #{reference} found" unless groups.any?
|
|
@@ -22,7 +22,7 @@ module StackMaster
|
|
|
22
22
|
|
|
23
23
|
def invalid_values
|
|
24
24
|
values = build_values(@definition, @parameter)
|
|
25
|
-
values.reject { |value| value.to_s.match(
|
|
25
|
+
values.reject { |value| value.to_s.match(/#{@definition[KEY]}/) }
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def create_error
|
|
@@ -21,16 +21,16 @@ module StackMaster
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def convert_strings_to_array
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
return unless @definition[:multiple] && @value.is_a?(String)
|
|
25
|
+
|
|
26
|
+
@value = @value.split(',').map(&:strip)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def convert_strings_to_numbers
|
|
30
|
-
if @definition[:type]
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
return if @definition[:type] != :number
|
|
31
|
+
|
|
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
34
|
end
|
|
35
35
|
end
|
|
36
36
|
end
|
|
@@ -27,9 +27,7 @@ module StackMaster
|
|
|
27
27
|
private
|
|
28
28
|
|
|
29
29
|
def convert_to_array(definition, parameter)
|
|
30
|
-
if definition[:multiple] && parameter.is_a?(String)
|
|
31
|
-
return parameter.split(',').map(&:strip)
|
|
32
|
-
end
|
|
30
|
+
return parameter.split(',').map(&:strip) if definition[:multiple] && parameter.is_a?(String)
|
|
33
31
|
|
|
34
32
|
parameter.is_a?(Array) ? parameter : [parameter]
|
|
35
33
|
end
|
|
@@ -49,14 +49,14 @@ module StackMaster
|
|
|
49
49
|
def _joined_file(file_name, vars = {})
|
|
50
50
|
join!(Template.render('joined_file', file_name, vars))
|
|
51
51
|
end
|
|
52
|
-
|
|
52
|
+
alias joined_file! _joined_file
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
module UserDataFile
|
|
56
56
|
def _user_data_file(file_name, vars = {})
|
|
57
57
|
base64!(join!(Template.render('user_data', file_name, vars)))
|
|
58
58
|
end
|
|
59
|
-
|
|
59
|
+
alias user_data_file! _user_data_file
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
end
|
data/lib/stack_master/stack.rb
CHANGED
|
@@ -20,9 +20,8 @@ module StackMaster
|
|
|
20
20
|
TemplateUtils
|
|
21
21
|
.template_hash(template)
|
|
22
22
|
.fetch('Parameters', {})
|
|
23
|
-
.
|
|
23
|
+
.each_with_object({}) do |(parameter_name, description), result|
|
|
24
24
|
result[parameter_name] = description['Default']&.to_s
|
|
25
|
-
result
|
|
26
25
|
end
|
|
27
26
|
end
|
|
28
27
|
|
|
@@ -35,19 +34,22 @@ module StackMaster
|
|
|
35
34
|
cf_stack = cf.describe_stacks({ stack_name: stack_name }).stacks.first
|
|
36
35
|
return unless cf_stack
|
|
37
36
|
|
|
38
|
-
parameters = cf_stack.parameters.
|
|
37
|
+
parameters = cf_stack.parameters.each_with_object({}) do |param_struct, params_hash|
|
|
39
38
|
params_hash[param_struct.parameter_key] = param_struct.parameter_value
|
|
40
|
-
params_hash
|
|
41
39
|
end
|
|
42
40
|
template_body ||= cf.get_template({ stack_name: stack_name, template_stage: 'Original' }).template_body
|
|
43
41
|
template_format = TemplateUtils.identify_template_format(template_body)
|
|
44
42
|
stack_policy_body ||= cf.get_stack_policy({ stack_name: stack_name }).stack_policy_body
|
|
45
43
|
outputs = cf_stack.outputs
|
|
44
|
+
tags = cf_stack.tags&.each_with_object({}) do |tag_struct, tags_hash|
|
|
45
|
+
tags_hash[tag_struct.key] = tag_struct.value
|
|
46
|
+
end || {}
|
|
46
47
|
|
|
47
48
|
new(region: region,
|
|
48
49
|
stack_name: stack_name,
|
|
49
50
|
stack_id: cf_stack.stack_id,
|
|
50
51
|
parameters: parameters,
|
|
52
|
+
tags: tags,
|
|
51
53
|
template_body: template_body,
|
|
52
54
|
template_format: template_format,
|
|
53
55
|
outputs: outputs,
|
|
@@ -35,7 +35,7 @@ module StackMaster
|
|
|
35
35
|
@compiler = nil
|
|
36
36
|
super
|
|
37
37
|
@additional_parameter_lookup_dirs ||= []
|
|
38
|
-
@base_dir ||=
|
|
38
|
+
@base_dir ||= ''
|
|
39
39
|
@template_dir ||= File.join(@base_dir, 'templates')
|
|
40
40
|
@parameters_dir ||= File.join(@base_dir, 'parameters')
|
|
41
41
|
@allowed_accounts = Array(@allowed_accounts)
|
|
@@ -44,7 +44,7 @@ module StackMaster
|
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def ==(other)
|
|
47
|
-
self.class
|
|
47
|
+
other.is_a?(self.class) &&
|
|
48
48
|
@region == other.region &&
|
|
49
49
|
@stack_name == other.stack_name &&
|
|
50
50
|
@template == other.template &&
|
|
@@ -74,13 +74,12 @@ module StackMaster
|
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
def s3_files
|
|
77
|
-
files.
|
|
77
|
+
files.each_with_object({}) do |file, hash|
|
|
78
78
|
path = File.join(files_dir, file)
|
|
79
79
|
hash[file] = {
|
|
80
80
|
path: path,
|
|
81
81
|
body: File.read(path)
|
|
82
82
|
}
|
|
83
|
-
hash
|
|
84
83
|
end
|
|
85
84
|
end
|
|
86
85
|
|