stack_master 2.17.1 → 2.19.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/bin/stack_master +3 -5
  4. data/lib/stack_master/aws_driver/cloud_formation.rb +4 -4
  5. data/lib/stack_master/aws_driver/s3.rb +7 -7
  6. data/lib/stack_master/change_set.rb +7 -11
  7. data/lib/stack_master/cli.rb +33 -27
  8. data/lib/stack_master/command.rb +1 -5
  9. data/lib/stack_master/commands/apply.rb +34 -19
  10. data/lib/stack_master/commands/delete.rb +4 -4
  11. data/lib/stack_master/commands/drift.rb +5 -9
  12. data/lib/stack_master/commands/events.rb +4 -6
  13. data/lib/stack_master/commands/init.rb +14 -14
  14. data/lib/stack_master/commands/lint.rb +1 -1
  15. data/lib/stack_master/commands/list_stacks.rb +1 -1
  16. data/lib/stack_master/commands/outputs.rb +1 -1
  17. data/lib/stack_master/commands/status.rb +4 -4
  18. data/lib/stack_master/commands/terminal_helper.rb +3 -3
  19. data/lib/stack_master/commands/tidy.rb +15 -20
  20. data/lib/stack_master/config.rb +8 -11
  21. data/lib/stack_master/diff.rb +2 -2
  22. data/lib/stack_master/parameter_loader.rb +32 -31
  23. data/lib/stack_master/parameter_resolver.rb +14 -17
  24. data/lib/stack_master/parameter_resolvers/ami_finder.rb +1 -2
  25. data/lib/stack_master/parameter_resolvers/ejson.rb +4 -4
  26. data/lib/stack_master/parameter_resolvers/latest_ami_by_tags.rb +1 -1
  27. data/lib/stack_master/parameter_resolvers/latest_container.rb +5 -5
  28. data/lib/stack_master/parameter_resolvers/one_password.rb +5 -5
  29. data/lib/stack_master/parameter_resolvers/sso_group_id.rb +1 -1
  30. data/lib/stack_master/parameter_resolvers/stack_output.rb +7 -11
  31. data/lib/stack_master/parameter_validator.rb +1 -5
  32. data/lib/stack_master/prompter.rb +1 -1
  33. data/lib/stack_master/resolver_array.rb +2 -2
  34. data/lib/stack_master/role_assumer.rb +1 -1
  35. data/lib/stack_master/security_group_finder.rb +4 -4
  36. data/lib/stack_master/sns_topic_finder.rb +1 -1
  37. data/lib/stack_master/sparkle_formation/compile_time/allowed_pattern_validator.rb +1 -1
  38. data/lib/stack_master/sparkle_formation/compile_time/definitions_validator.rb +1 -1
  39. data/lib/stack_master/sparkle_formation/compile_time/value_builder.rb +7 -7
  40. data/lib/stack_master/sparkle_formation/compile_time/value_validator.rb +1 -3
  41. data/lib/stack_master/sparkle_formation/template_file.rb +4 -4
  42. data/lib/stack_master/sso_group_id_finder.rb +3 -3
  43. data/lib/stack_master/stack.rb +6 -4
  44. data/lib/stack_master/stack_definition.rb +3 -4
  45. data/lib/stack_master/stack_differ.rb +33 -10
  46. data/lib/stack_master/template_compiler.rb +1 -1
  47. data/lib/stack_master/template_compilers/json.rb +1 -1
  48. data/lib/stack_master/template_compilers/sparkle_formation.rb +59 -57
  49. data/lib/stack_master/template_utils.rb +2 -2
  50. data/lib/stack_master/test_driver/cloud_formation.rb +12 -4
  51. data/lib/stack_master/test_driver/s3.rb +2 -3
  52. data/lib/stack_master/utils.rb +3 -6
  53. data/lib/stack_master/validator.rb +1 -1
  54. data/lib/stack_master/version.rb +1 -1
  55. data/lib/stack_master.rb +1 -1
  56. metadata +8 -7
@@ -21,11 +21,11 @@ module StackMaster
21
21
  {
22
22
  region: stack_definition.region,
23
23
  stack_name: stack_definition.stack_name,
24
- stack_status: running_in_allowed_account?(allowed_accounts) ? stack_status.status : "Disallowed account",
25
- different: running_in_allowed_account?(allowed_accounts) ? stack_status.changed_message : "N/A",
24
+ stack_status: running_in_allowed_account?(allowed_accounts) ? stack_status.status : 'Disallowed account',
25
+ different: running_in_allowed_account?(allowed_accounts) ? stack_status.changed_message : 'N/A'
26
26
  }
27
27
  end
28
- tp.set :max_width, self.window_size
28
+ tp.set :max_width, window_size
29
29
  tp.set :io, StackMaster.stdout
30
30
  tp status
31
31
  StackMaster.stdout.puts " * No echo parameters can't be diffed"
@@ -34,7 +34,7 @@ module StackMaster
34
34
  private
35
35
 
36
36
  def progress
37
- @progress ||= ProgressBar.create(title: "Fetching stack information",
37
+ @progress ||= ProgressBar.create(title: 'Fetching stack information',
38
38
  total: @config.stacks.size,
39
39
  output: StackMaster.stdout)
40
40
  end
@@ -4,9 +4,9 @@ module StackMaster
4
4
  module Commands
5
5
  module TerminalHelper
6
6
  def window_size
7
- size = ENV.fetch("COLUMNS") { OS.windows? ? windows_window_size : unix_window_size }
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 = %r{^\s+Columns:\s+([0-9]+)$}
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]
@@ -5,26 +5,23 @@ module StackMaster
5
5
  include StackMaster::Commands::TerminalHelper
6
6
 
7
7
  def perform
8
- used_templates = []
9
- used_parameter_files = []
8
+ templates = Set.new(find_templates)
9
+ parameter_files = Set.new(find_parameter_files)
10
10
 
11
- templates = Set.new(find_templates())
12
- parameter_files = Set.new(find_parameter_files())
13
-
14
- status = @config.stacks.each do |stack_definition|
11
+ @config.stacks.each do |stack_definition|
15
12
  parameter_files.subtract(stack_definition.parameter_files_from_globs)
16
13
  template = File.absolute_path(stack_definition.template_file_path)
17
14
 
18
- if template
19
- templates.delete(template)
15
+ next unless template
16
+
17
+ templates.delete(template)
20
18
 
21
- if !File.exist?(template)
22
- StackMaster.stdout.puts(
23
- "Stack \"#{stack_definition.stack_name}\" in \"#{stack_definition.region}\" " \
24
- "missing template \"#{rel_path(template)}\""
25
- )
26
- end
27
- end
19
+ next if File.exist?(template)
20
+
21
+ StackMaster.stdout.puts(
22
+ "Stack \"#{stack_definition.stack_name}\" in \"#{stack_definition.region}\" " \
23
+ "missing template \"#{rel_path(template)}\""
24
+ )
28
25
  end
29
26
 
30
27
  templates.each do |path|
@@ -46,21 +43,19 @@ module StackMaster
46
43
  # template directories) this won't find the right directory.
47
44
  template_dir = @config.template_dir || File.join(@config.base_dir, 'templates')
48
45
 
49
- templates = Dir.glob(File.absolute_path(File.join(template_dir, '**', "*.{rb,yaml,yml,json}")))
46
+ templates = Dir.glob(File.absolute_path(File.join(template_dir, '**', '*.{rb,yaml,yml,json}')))
50
47
  dynamics_dir = File.join(template_dir, 'dynamics')
51
48
 
52
49
  # Exclude sparkleformation dynamics
53
50
  # TODO: Should this filter out anything with 'dynamics', not just the first
54
51
  # subdirectory?
55
- templates = templates.select do |path|
52
+ templates.select do |path|
56
53
  !path.start_with?(dynamics_dir)
57
54
  end
58
-
59
- templates
60
55
  end
61
56
 
62
57
  def find_parameter_files
63
- Dir.glob(File.absolute_path(File.join(@config.base_dir, "parameters", "*.{yml,yaml}")))
58
+ Dir.glob(File.absolute_path(File.join(@config.base_dir, 'parameters', '*.{yml,yaml}')))
64
59
  end
65
60
  end
66
61
  end
@@ -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("..", Dir.pwd)
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("..", dir)
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.inject({}) do |hash, (key, value)|
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 user_defined_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.inject({}) do |hash, (region, attributes)|
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.inject({}) do |normalised_aliases, (region_or_alias, value)|
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
@@ -1,6 +1,6 @@
1
1
  module StackMaster
2
2
  class Diff
3
- def initialize(name: nil, before:, after:, context: 10_000)
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 "No changes"
13
+ stdout.puts 'No changes'
14
14
  else
15
15
  stdout.puts
16
16
  display_colorized_diff
@@ -1,47 +1,48 @@
1
1
  require 'active_support/core_ext/object/deep_dup'
2
2
 
3
3
  module StackMaster
4
- class ParameterLoader
4
+ module ParameterLoader
5
5
  COMPILE_TIME_PARAMETERS_KEY = 'compile_time_parameters'
6
6
 
7
- def self.load(parameter_files: [], parameters: {})
8
- StackMaster.debug 'Searching for parameter files...'
9
- all_parameters = parameter_files.map { |file_name| load_parameters(file_name) } + [parameters]
10
- all_parameters.reduce({ template_parameters: {}, compile_time_parameters: {} }) do |hash, parameters|
11
- template_parameters = create_template_parameters(parameters)
12
- compile_time_parameters = create_compile_time_parameters(parameters)
13
-
14
- merge_and_camelize(hash[:template_parameters], template_parameters)
15
- merge_and_camelize(hash[:compile_time_parameters], compile_time_parameters)
16
- hash
7
+ class << self
8
+ def load(parameter_files: [], parameters: {})
9
+ StackMaster.debug 'Searching for parameter files...'
10
+ all_parameters = parameter_files.map { |file_name| load_parameters(file_name) } + [parameters]
11
+ all_parameters.each_with_object({ template_parameters: {}, compile_time_parameters: {} }) do |parameters, hash|
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
+ end
17
18
  end
18
- end
19
19
 
20
- private
20
+ private
21
21
 
22
- def self.load_parameters(file_name)
23
- file_exists = File.exist?(file_name)
24
- StackMaster.debug file_exists ? " #{file_name} found" : " #{file_name} not found"
25
- file_exists ? load_file(file_name) : {}
26
- end
22
+ def load_parameters(file_name)
23
+ file_exists = File.exist?(file_name)
24
+ StackMaster.debug file_exists ? " #{file_name} found" : " #{file_name} not found"
25
+ file_exists ? load_file(file_name) : {}
26
+ end
27
27
 
28
- def self.load_file(file_name)
29
- YAML.load(File.read(file_name)) || {}
30
- end
28
+ def load_file(file_name)
29
+ YAML.load(File.read(file_name)) || {}
30
+ end
31
31
 
32
- def self.create_template_parameters(parameters)
33
- parameters.deep_dup.tap do |parameters_clone|
34
- parameters_clone.delete(COMPILE_TIME_PARAMETERS_KEY) ||
35
- parameters_clone.delete(COMPILE_TIME_PARAMETERS_KEY.camelize)
32
+ def create_template_parameters(parameters)
33
+ parameters.deep_dup.tap do |parameters_clone|
34
+ parameters_clone.delete(COMPILE_TIME_PARAMETERS_KEY) ||
35
+ parameters_clone.delete(COMPILE_TIME_PARAMETERS_KEY.camelize)
36
+ end
36
37
  end
37
- end
38
38
 
39
- def self.create_compile_time_parameters(parameters)
40
- (parameters[COMPILE_TIME_PARAMETERS_KEY] || parameters[COMPILE_TIME_PARAMETERS_KEY.camelize] || {}).deep_dup
41
- end
39
+ def create_compile_time_parameters(parameters)
40
+ (parameters[COMPILE_TIME_PARAMETERS_KEY] || parameters[COMPILE_TIME_PARAMETERS_KEY.camelize] || {}).deep_dup
41
+ end
42
42
 
43
- def self.merge_and_camelize(hash, parameters)
44
- parameters.each { |key, value| hash[key.camelize] = value }
43
+ def merge_and_camelize(hash, parameters)
44
+ parameters.each { |key, value| hash[key.camelize] = value }
45
+ end
45
46
  end
46
47
  end
47
48
  end
@@ -15,13 +15,12 @@ module StackMaster
15
15
  end
16
16
 
17
17
  def resolve
18
- @parameters.reduce({}) do |parameters, (key, value)|
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
- raise ResolverNotFound.new(file_name)
35
- else
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
- 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
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) do
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 != 1
118
- raise InvalidParameter, "#{key} hash contained more than one key: #{parameter_value.inspect}"
119
- end
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
- filters = value.split(',').map do |name_with_value|
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
- if @stack_definition.ejson_file.nil?
26
- raise ArgumentError, 'No ejson_file defined for stack definition ' \
27
- "#{@stack_definition.stack_name} in #{@stack_definition.region}"
28
- end
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 = "tag")
13
+ filters = @ami_finder.build_filters_from_string(value, '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, "repository_name parameter is required but was not supplied"
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
@@ -37,16 +37,16 @@ module StackMaster
37
37
  def fetch_images(repository_name, registry_id, ecr)
38
38
  images = []
39
39
  next_token = nil
40
- while resp = ecr.describe_images(
40
+ while (resp = ecr.describe_images(
41
41
  {
42
42
  repository_name: repository_name,
43
43
  registry_id: registry_id,
44
44
  next_token: next_token,
45
45
  filter: {
46
- tag_status: "TAGGED",
47
- },
46
+ tag_status: 'TAGGED'
47
+ }
48
48
  }
49
- )
49
+ ))
50
50
 
51
51
  images += resp.image_details
52
52
  next_token = resp.next_token
@@ -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
- "1password requires the `OP_SESSION_<name>` to be set, (remember to sign in?)"
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
- %x(op --version)
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 = %x(op get item --vault='#{vault}' '#{item}' 2>&1)
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
- return get_password(params['title'], params['vault'])
82
+ get_password(params['title'], params['vault'])
83
83
  when 'secureNote'
84
- return get_secure_note(params['title'], params['vault'])
84
+ get_secure_note(params['title'], params['vault'])
85
85
  end
86
86
  end
87
87
  end
@@ -15,7 +15,7 @@ module StackMaster
15
15
  private
16
16
 
17
17
  def sso_group_id_finder
18
- StackMaster::SsoGroupIdFinder.new()
18
+ StackMaster::SsoGroupIdFinder.new
19
19
  end
20
20
  end
21
21
  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
- if stack
21
- output = stack.outputs.find do |stack_output|
22
- stack_output.output_key == output_name.camelize || stack_output.output_key == output_name
23
- end
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
- if @stack_definition.parameter_files.empty?
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 "STDOUT or STDIN was not a TTY. Defaulting to no. To force yes use -y"
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
- fail "Method resolver_class not implemented on #{self.class}"
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(self.name)
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
@@ -48,7 +48,7 @@ module StackMaster
48
48
  {
49
49
  region: StackMaster.cloud_formation_driver.region,
50
50
  role_arn: "arn:aws:iam::#{account}:role/#{role}",
51
- role_session_name: "stack-master-role-assumer"
51
+ role_session_name: 'stack-master-role-assumer'
52
52
  }
53
53
  )
54
54
  end
@@ -15,10 +15,10 @@ module StackMaster
15
15
  groups = @resource.security_groups({
16
16
  filters: [
17
17
  {
18
- name: "group-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?
@@ -21,7 +21,7 @@ module StackMaster
21
21
  private
22
22
 
23
23
  def topic_name_from_arn(arn)
24
- arn.split(":")[5]
24
+ arn.split(':')[5]
25
25
  end
26
26
  end
27
27
  end
@@ -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(%r{#{@definition[KEY]}}) }
25
+ values.reject { |value| value.to_s.match(/#{@definition[KEY]}/) }
26
26
  end
27
27
 
28
28
  def create_error
@@ -4,7 +4,7 @@ module StackMaster
4
4
  module SparkleFormation
5
5
  module CompileTime
6
6
  class DefinitionsValidator
7
- VALID_TYPES = [:string, :number]
7
+ VALID_TYPES = %i[string number]
8
8
  def initialize(definitions)
9
9
  @definitions = definitions
10
10
  end
@@ -21,16 +21,16 @@ module StackMaster
21
21
  end
22
22
 
23
23
  def convert_strings_to_array
24
- if @definition[:multiple] && @value.is_a?(String)
25
- @value = @value.split(',').map(&:strip)
26
- end
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] == :number
31
- @value = @value.to_f if @value.is_a?(String)
32
- @value = @value.map { |item| item.is_a?(String) ? item.to_f : item } if @value.is_a?(Array)
33
- end
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