stack_master 2.17.0 → 2.17.1

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -5
  3. data/lib/stack_master/aws_driver/cloud_formation.rb +21 -19
  4. data/lib/stack_master/aws_driver/s3.rb +18 -11
  5. data/lib/stack_master/change_set.rb +5 -5
  6. data/lib/stack_master/cli.rb +24 -9
  7. data/lib/stack_master/commands/apply.rb +5 -1
  8. data/lib/stack_master/commands/delete.rb +2 -3
  9. data/lib/stack_master/commands/drift.rb +6 -3
  10. data/lib/stack_master/commands/init.rb +6 -5
  11. data/lib/stack_master/commands/nag.rb +0 -1
  12. data/lib/stack_master/commands/resources.rb +9 -1
  13. data/lib/stack_master/commands/tidy.rb +4 -1
  14. data/lib/stack_master/config.rb +16 -11
  15. data/lib/stack_master/identity.rb +2 -1
  16. data/lib/stack_master/parameter_loader.rb +3 -4
  17. data/lib/stack_master/parameter_resolver.rb +4 -1
  18. data/lib/stack_master/parameter_resolvers/acm_certificate.rb +4 -1
  19. data/lib/stack_master/parameter_resolvers/ami_finder.rb +1 -1
  20. data/lib/stack_master/parameter_resolvers/ejson.rb +7 -4
  21. data/lib/stack_master/parameter_resolvers/env.rb +1 -2
  22. data/lib/stack_master/parameter_resolvers/latest_container.rb +6 -4
  23. data/lib/stack_master/parameter_resolvers/one_password.rb +7 -3
  24. data/lib/stack_master/parameter_resolvers/parameter_store.rb +1 -5
  25. data/lib/stack_master/parameter_resolvers/security_group.rb +1 -1
  26. data/lib/stack_master/parameter_resolvers/sso_group_id.rb +2 -1
  27. data/lib/stack_master/parameter_resolvers/stack_output.rb +3 -1
  28. data/lib/stack_master/parameter_validator.rb +1 -0
  29. data/lib/stack_master/prompter.rb +11 -10
  30. data/lib/stack_master/resolver_array.rb +0 -1
  31. data/lib/stack_master/role_assumer.rb +7 -5
  32. data/lib/stack_master/security_group_finder.rb +3 -1
  33. data/lib/stack_master/sns_topic_finder.rb +3 -2
  34. data/lib/stack_master/sparkle_formation/compile_time/allowed_pattern_validator.rb +1 -2
  35. data/lib/stack_master/sparkle_formation/compile_time/allowed_values_validator.rb +2 -3
  36. data/lib/stack_master/sparkle_formation/compile_time/definitions_validator.rb +5 -5
  37. data/lib/stack_master/sparkle_formation/compile_time/empty_validator.rb +0 -2
  38. data/lib/stack_master/sparkle_formation/compile_time/max_length_validator.rb +1 -2
  39. data/lib/stack_master/sparkle_formation/compile_time/max_size_validator.rb +1 -2
  40. data/lib/stack_master/sparkle_formation/compile_time/min_length_validator.rb +2 -3
  41. data/lib/stack_master/sparkle_formation/compile_time/min_size_validator.rb +2 -3
  42. data/lib/stack_master/sparkle_formation/compile_time/number_validator.rb +1 -2
  43. data/lib/stack_master/sparkle_formation/compile_time/parameters_validator.rb +0 -1
  44. data/lib/stack_master/sparkle_formation/compile_time/state_builder.rb +0 -2
  45. data/lib/stack_master/sparkle_formation/compile_time/string_validator.rb +2 -3
  46. data/lib/stack_master/sparkle_formation/compile_time/value_builder.rb +0 -2
  47. data/lib/stack_master/sparkle_formation/compile_time/value_validator.rb +2 -3
  48. data/lib/stack_master/sparkle_formation/compile_time/value_validator_factory.rb +11 -13
  49. data/lib/stack_master/sparkle_formation/template_file.rb +0 -2
  50. data/lib/stack_master/sso_group_id_finder.rb +14 -11
  51. data/lib/stack_master/stack.rb +47 -16
  52. data/lib/stack_master/stack_definition.rb +3 -1
  53. data/lib/stack_master/stack_differ.rb +4 -0
  54. data/lib/stack_master/stack_events/fetcher.rb +3 -1
  55. data/lib/stack_master/stack_events/presenter.rb +6 -1
  56. data/lib/stack_master/stack_events/streamer.rb +3 -1
  57. data/lib/stack_master/stack_status.rb +1 -0
  58. data/lib/stack_master/template_compilers/sparkle_formation.rb +10 -7
  59. data/lib/stack_master/template_utils.rb +6 -2
  60. data/lib/stack_master/test_driver/cloud_formation.rb +27 -10
  61. data/lib/stack_master/utils.rb +1 -0
  62. data/lib/stack_master/validator.rb +6 -5
  63. data/lib/stack_master/version.rb +1 -1
  64. data/lib/stack_master.rb +2 -0
  65. metadata +19 -9
  66. data/lib/stack_master/parameter_resolvers/accounts_by_tags.rb +0 -60
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 637daba2dddc707df22584fad412d87df4ee24aab069885231561d847c762496
4
- data.tar.gz: 7abcea21ecfbc080886b4181dc66392066a9360255ed2186bf2e7d652f6101e2
3
+ metadata.gz: e73f1b3d79a230203a083898d14d256ac7c61fb0dd4a49627af097759341ca96
4
+ data.tar.gz: 193c5824b8972d6ddc36f66dd23d83360c1af43562a3b038c413bb6ff624626a
5
5
  SHA512:
6
- metadata.gz: dba94d8ecf220d837673ef95f68c8d534b979bd31d67b8056e0836355a88f713499ca55420906ffb16855f7c3acb17e320c41ec90cb9c84263c59539f00c4cb2
7
- data.tar.gz: 680f31e8fef7a94d387582acdb6c9381844aae4e2c56e6c4088f36d9c1ac2969feb27b9703c90c21416cef96572efc32455d4621951567611a18cb3481f22f56
6
+ metadata.gz: 41d00dda80224d66ae46e73746b43f1e0738ef075ad8ce3122494db579c545b6cd2b15497622cf5aa683efa2bf6f67f411a031c1cb5063c0a94b40dcef8261a0
7
+ data.tar.gz: e26a3fa7eeae1b2be191fa579e585f34f8f781c4b94e68d42c0619a3d1effbe86cd0761b119a79058a86d98f113d6db573dfbfd0b733792ca9d21554de98684c
data/README.md CHANGED
@@ -794,11 +794,6 @@ CLI directly rather than via a stack update.
794
794
  applied in CloudFormation. This can happen if the template or computed parameters have changed in code and the change
795
795
  hasn't been applied to this stack.
796
796
 
797
- ## Maintainers
798
-
799
- - [Steve Hodgkiss](https://github.com/stevehodgkiss)
800
- - [Glen Stampoultzis](https://github.com/gstamp)
801
-
802
797
  ## License
803
798
 
804
799
  StackMaster uses the MIT license. See [LICENSE.txt](https://github.com/envato/stack_master/blob/master/LICENSE.txt) for details.
@@ -14,31 +14,33 @@ module StackMaster
14
14
  end
15
15
  end
16
16
 
17
- def_delegators :cf, :create_change_set,
18
- :describe_change_set,
19
- :execute_change_set,
20
- :delete_change_set,
21
- :delete_stack,
22
- :cancel_update_stack,
23
- :describe_stack_resources,
24
- :get_template,
25
- :get_stack_policy,
26
- :set_stack_policy,
27
- :describe_stack_events,
28
- :update_stack,
29
- :create_stack,
30
- :validate_template,
31
- :describe_stacks,
32
- :detect_stack_drift,
33
- :describe_stack_drift_detection_status,
34
- :describe_stack_resource_drifts
17
+ def_delegators(
18
+ :cf,
19
+ :create_change_set,
20
+ :describe_change_set,
21
+ :execute_change_set,
22
+ :delete_change_set,
23
+ :delete_stack,
24
+ :cancel_update_stack,
25
+ :describe_stack_resources,
26
+ :get_template,
27
+ :get_stack_policy,
28
+ :set_stack_policy,
29
+ :describe_stack_events,
30
+ :update_stack,
31
+ :create_stack,
32
+ :validate_template,
33
+ :describe_stacks,
34
+ :detect_stack_drift,
35
+ :describe_stack_drift_detection_status,
36
+ :describe_stack_resource_drifts
37
+ )
35
38
 
36
39
  private
37
40
 
38
41
  def cf
39
42
  @cf ||= Aws::CloudFormation::Client.new({ region: region, retry_limit: 10 })
40
43
  end
41
-
42
44
  end
43
45
  end
44
46
  end
@@ -11,16 +11,20 @@ module StackMaster
11
11
  end
12
12
 
13
13
  def upload_files(bucket: nil, prefix: nil, region: nil, files: {})
14
- raise StackMaster::AwsDriver::S3ConfigurationError, 'A bucket must be specified in order to use S3' unless bucket
14
+ unless bucket
15
+ raise StackMaster::AwsDriver::S3ConfigurationError, 'A bucket must be specified in order to use S3'
16
+ end
15
17
 
16
18
  return if files.empty?
17
19
 
18
20
  s3 = new_s3_client(region: region)
19
21
 
20
- current_objects = s3.list_objects({
21
- prefix: prefix,
22
- bucket: bucket
23
- }).map(&:contents).flatten.inject({}){|h,obj|
22
+ current_objects = s3.list_objects(
23
+ {
24
+ prefix: prefix,
25
+ bucket: bucket
26
+ }
27
+ ).map(&:contents).flatten.inject({}) { |h, obj|
24
28
  h.merge(obj.key => obj)
25
29
  }
26
30
 
@@ -35,15 +39,18 @@ module StackMaster
35
39
  s3_md5 = current_objects[object_key] ? current_objects[object_key].etag.gsub("\"", '') : nil
36
40
 
37
41
  next if compiled_template_md5 == s3_md5
42
+
38
43
  s3_uri = "s3://#{bucket}/#{object_key}"
39
44
  StackMaster.stdout.print "- #{File.basename(path)} => #{s3_uri} "
40
45
 
41
- s3.put_object({
42
- bucket: bucket,
43
- key: object_key,
44
- body: body,
45
- metadata: { md5: compiled_template_md5 }
46
- })
46
+ s3.put_object(
47
+ {
48
+ bucket: bucket,
49
+ key: object_key,
50
+ body: body,
51
+ metadata: { md5: compiled_template_md5 }
52
+ }
53
+ )
47
54
  StackMaster.stdout.puts "done."
48
55
  end
49
56
  end
@@ -42,15 +42,15 @@ module StackMaster
42
42
  end
43
43
 
44
44
  def display(io)
45
- io.puts <<-EOL
45
+ io.puts <<~EOL
46
46
 
47
- ========================================
48
- Proposed change set:
49
- EOL
47
+ ========================================
48
+ Proposed change set:
49
+ EOL
50
50
  @response.changes.each do |change|
51
51
  display_resource_change(io, change.resource_change)
52
52
  end
53
- io.puts "========================================"
53
+ io.puts "========================================"
54
54
  end
55
55
 
56
56
  def failed?
@@ -5,7 +5,7 @@ module StackMaster
5
5
  class CLI
6
6
  include Commander::Methods
7
7
 
8
- def initialize(argv, stdin=STDIN, stdout=STDOUT, stderr=STDERR, kernel=Kernel)
8
+ def initialize(argv, stdin = STDIN, stdout = STDOUT, stderr = STDERR, kernel = Kernel)
9
9
  @argv, @stdin, @stdout, @stderr, @kernel = argv, stdin, stdout, stderr, kernel
10
10
  Commander::Runner.instance_variable_set('@instance', Commander::Runner.new(argv))
11
11
  StackMaster.stdout = @stdout
@@ -41,9 +41,14 @@ module StackMaster
41
41
  command :apply do |c|
42
42
  c.syntax = 'stack_master apply [region_or_alias] [stack_name]'
43
43
  c.summary = 'Creates or updates a stack'
44
- c.description = "Creates or updates a stack. Shows a diff of the proposed stack's template and parameters. Tails stack events until CloudFormation has completed."
44
+ c.description = "Creates or updates a stack. Shows a diff of the proposed stack's template and parameters. " \
45
+ 'Tails stack events until CloudFormation has completed.'
45
46
  c.example 'update a stack named myapp-vpc in us-east-1', 'stack_master apply us-east-1 myapp-vpc'
46
- c.option '--on-failure ACTION', String, "Action to take on CREATE_FAILURE. Valid Values: [ DO_NOTHING | ROLLBACK | DELETE ]. Default: ROLLBACK\nNote: You cannot use this option with Serverless Application Model (SAM) templates."
47
+ c.option '--on-failure ACTION', String,
48
+ 'Action to take on CREATE_FAILURE. ' \
49
+ 'Valid Values: [ DO_NOTHING | ROLLBACK | DELETE ]. ' \
50
+ "Default: ROLLBACK\n" \
51
+ 'Note: You cannot use this option with Serverless Application Model (SAM) templates.'
47
52
  c.option '--yes-param PARAM_NAME', String, "Auto-approve stack updates when only parameter PARAM_NAME changes"
48
53
  c.action do |args, options|
49
54
  options.default config: default_config_file
@@ -171,11 +176,13 @@ module StackMaster
171
176
  command :status do |c|
172
177
  c.syntax = 'stack_master status'
173
178
  c.summary = 'Check the current status stacks.'
174
- c.description = 'Checks the status of all stacks defined in the stack_master.yml file. Warning this operation can be somewhat slow.'
179
+ c.description = 'Checks the status of all stacks defined in the stack_master.yml file. ' \
180
+ 'Warning this operation can be somewhat slow.'
175
181
  c.example 'description', 'Check the status of all stack definitions'
176
182
  c.action do |args, options|
177
183
  options.default config: default_config_file
178
184
  say "Invalid arguments. stack_master status" and return unless args.size == 0
185
+
179
186
  config = load_config(options.config)
180
187
  StackMaster::Commands::Status.perform(config, nil, options)
181
188
  end
@@ -184,11 +191,13 @@ module StackMaster
184
191
  command :tidy do |c|
185
192
  c.syntax = 'stack_master tidy'
186
193
  c.summary = 'Try to identify extra & missing files.'
187
- c.description = 'Cross references stack_master.yml with the template and parameter directories to identify extra or missing files.'
194
+ c.description = 'Cross references stack_master.yml with the template ' \
195
+ 'and parameter directories to identify extra or missing files.'
188
196
  c.example 'description', 'Check for missing or extra files'
189
197
  c.action do |args, options|
190
198
  options.default config: default_config_file
191
199
  say "Invalid arguments. stack_master tidy" and return unless args.size == 0
200
+
192
201
  config = load_config(options.config)
193
202
  StackMaster::Commands::Tidy.perform(config, nil, options)
194
203
  end
@@ -269,11 +278,14 @@ module StackMaster
269
278
  success = false
270
279
  end
271
280
  stack_definitions = stack_definitions.select do |stack_definition|
272
- running_in_allowed_account?(stack_definition.allowed_accounts) && StackStatus.new(config, stack_definition).changed?
281
+ running_in_allowed_account?(stack_definition.allowed_accounts) &&
282
+ StackStatus.new(config, stack_definition).changed?
273
283
  end if options.changed
274
284
  stack_definitions.each do |stack_definition|
275
285
  StackMaster.cloud_formation_driver.set_region(stack_definition.region)
276
- StackMaster.stdout.puts "Executing #{command.command_name} on #{stack_definition.stack_name} in #{stack_definition.region}"
286
+ StackMaster.stdout.puts(
287
+ "Executing #{command.command_name} on #{stack_definition.stack_name} in #{stack_definition.region}"
288
+ )
277
289
  success = execute_if_allowed_account(stack_definition.allowed_accounts) do
278
290
  command.perform(config, stack_definition, options).success?
279
291
  end
@@ -283,7 +295,7 @@ module StackMaster
283
295
  end
284
296
 
285
297
  def show_other_region_candidates(config, stack_name)
286
- candidates = config.filter(region="", stack_name=stack_name)
298
+ candidates = config.filter(region = "", stack_name = stack_name)
287
299
  return if candidates.empty?
288
300
 
289
301
  StackMaster.stdout.puts "Stack name #{stack_name} exists in regions: #{candidates.map(&:region).join(', ')}"
@@ -291,12 +303,15 @@ module StackMaster
291
303
 
292
304
  def execute_if_allowed_account(allowed_accounts, &block)
293
305
  raise ArgumentError, "Block required to execute this method" unless block_given?
306
+
294
307
  if running_in_allowed_account?(allowed_accounts)
295
308
  block.call
296
309
  else
297
310
  account_text = "'#{identity.account}'"
298
311
  account_text << " (#{identity.account_aliases.join(', ')})" if identity.account_aliases.any?
299
- StackMaster.stdout.puts "Account #{account_text} is not an allowed account. Allowed accounts are #{allowed_accounts}."
312
+ StackMaster.stdout.puts(
313
+ "Account #{account_text} is not an allowed account. Allowed accounts are #{allowed_accounts}."
314
+ )
300
315
  false
301
316
  end
302
317
  end
@@ -144,6 +144,7 @@ module StackMaster
144
144
 
145
145
  def upload_files
146
146
  return unless use_s3?
147
+
147
148
  s3.upload_files(**s3_options)
148
149
  end
149
150
 
@@ -153,7 +154,8 @@ module StackMaster
153
154
 
154
155
  def template_value
155
156
  if use_s3?
156
- s3.url(bucket: @s3_config['bucket'], prefix: @s3_config['prefix'], region: @s3_config['region'], template: @stack_definition.s3_template_file_name)
157
+ s3.url(bucket: @s3_config['bucket'], prefix: @s3_config['prefix'], region: @s3_config['region'],
158
+ template: @stack_definition.s3_template_file_name)
157
159
  else
158
160
  proposed_stack.template
159
161
  end
@@ -161,6 +163,7 @@ module StackMaster
161
163
 
162
164
  def files_to_upload
163
165
  return {} unless use_s3?
166
+
164
167
  @stack_definition.s3_files.tap do |files|
165
168
  files[@stack_definition.s3_template_file_name] = {
166
169
  path: @stack_definition.template_file_path,
@@ -218,6 +221,7 @@ module StackMaster
218
221
  proposed_policy = proposed_stack.stack_policy_body
219
222
  # No need to reset a stack policy if it's nil or not changed
220
223
  return if proposed_policy.nil? || proposed_policy == current_policy
224
+
221
225
  StackMaster.stdout.print 'Setting a stack policy...'
222
226
  cf.set_stack_policy(
223
227
  stack_name: stack_name,
@@ -12,7 +12,6 @@ module StackMaster
12
12
  end
13
13
 
14
14
  def perform
15
-
16
15
  return unless check_exists
17
16
 
18
17
  unless ask?("Really delete stack #{@stack_name} (y/n)? ")
@@ -27,11 +26,11 @@ module StackMaster
27
26
  private
28
27
 
29
28
  def delete_stack
30
- cf.delete_stack({stack_name: @stack_name})
29
+ cf.delete_stack({ stack_name: @stack_name })
31
30
  end
32
31
 
33
32
  def check_exists
34
- cf.describe_stacks({stack_name: @stack_name})
33
+ cf.describe_stacks({ stack_name: @stack_name })
35
34
  true
36
35
  rescue Aws::CloudFormation::Errors::ValidationError
37
36
  failed("Stack does not exist")
@@ -15,7 +15,8 @@ module StackMaster
15
15
  detect_stack_drift_result = cf.detect_stack_drift(stack_name: stack_name)
16
16
  drift_results = wait_for_drift_results(detect_stack_drift_result.stack_drift_detection_id)
17
17
 
18
- puts colorize("Drift Status: #{drift_results.stack_drift_status}", stack_drift_status_color(drift_results.stack_drift_status))
18
+ puts colorize("Drift Status: #{drift_results.stack_drift_status}",
19
+ stack_drift_status_color(drift_results.stack_drift_status))
19
20
  return if drift_results.stack_drift_status == 'IN_SYNC'
20
21
 
21
22
  failed
@@ -51,8 +52,10 @@ module StackMaster
51
52
  end
52
53
 
53
54
  def display_resource_drift(drift)
54
- diff = ::StackMaster::Diff.new(before: prettify_json(drift.expected_properties),
55
- after: prettify_json(drift.actual_properties))
55
+ diff = ::StackMaster::Diff.new(
56
+ before: prettify_json(drift.expected_properties),
57
+ after: prettify_json(drift.actual_properties)
58
+ )
56
59
  diff.display_colorized_diff
57
60
  end
58
61
 
@@ -28,11 +28,12 @@ module StackMaster
28
28
  @region_parameters_filename = File.join("parameters", @region, "#{@stack_name}.yml")
29
29
 
30
30
  if !@options.overwrite
31
- [@stack_master_filename, @stack_json_filename, @parameters_filename, @region_parameters_filename].each do |filename|
32
- if File.exist?(filename)
33
- StackMaster.stderr.puts("Aborting: #{filename} already exists. Use --overwrite to force overwriting file.")
34
- return false
35
- end
31
+ [@stack_master_filename, @stack_json_filename, @parameters_filename,
32
+ @region_parameters_filename].each do |filename|
33
+ next unless File.exist?(filename)
34
+
35
+ StackMaster.stderr.puts("Aborting: #{filename} already exists. Use --overwrite to force overwriting file.")
36
+ return false
36
37
  end
37
38
  end
38
39
  true
@@ -24,7 +24,6 @@ module StackMaster
24
24
  def proposed_stack
25
25
  @proposed_stack ||= Stack.generate(stack_definition, @config)
26
26
  end
27
-
28
27
  end
29
28
  end
30
29
  end
@@ -8,7 +8,15 @@ module StackMaster
8
8
 
9
9
  def perform
10
10
  if stack_resources
11
- tp stack_resources, :logical_resource_id, :resource_type, :timestamp, :resource_status, :resource_status_reason, :description
11
+ tp(
12
+ stack_resources,
13
+ :logical_resource_id,
14
+ :resource_type,
15
+ :timestamp,
16
+ :resource_status,
17
+ :resource_status_reason,
18
+ :description
19
+ )
12
20
  else
13
21
  failed("Stack doesn't exist")
14
22
  end
@@ -19,7 +19,10 @@ module StackMaster
19
19
  templates.delete(template)
20
20
 
21
21
  if !File.exist?(template)
22
- StackMaster.stdout.puts "Stack \"#{stack_definition.stack_name}\" in \"#{stack_definition.region}\" missing template \"#{rel_path(template)}\""
22
+ StackMaster.stdout.puts(
23
+ "Stack \"#{stack_definition.stack_name}\" in \"#{stack_definition.region}\" " \
24
+ "missing template \"#{rel_path(template)}\""
25
+ )
23
26
  end
24
27
  end
25
28
  end
@@ -14,14 +14,16 @@ module StackMaster
14
14
  raise ConfigParseError, "Unable to parse #{resolved_config_file}: #{error}"
15
15
  end
16
16
 
17
- attr_accessor :stacks,
18
- :base_dir,
19
- :template_dir,
20
- :parameters_dir,
21
- :stack_defaults,
22
- :region_defaults,
23
- :region_aliases,
24
- :template_compilers,
17
+ attr_accessor(
18
+ :stacks,
19
+ :base_dir,
20
+ :template_dir,
21
+ :parameters_dir,
22
+ :stack_defaults,
23
+ :region_defaults,
24
+ :region_aliases,
25
+ :template_compilers
26
+ )
25
27
 
26
28
  def self.search_up_and_chdir(config_file)
27
29
  return config_file unless File.dirname(config_file) == "."
@@ -52,6 +54,7 @@ module StackMaster
52
54
  @stacks = []
53
55
 
54
56
  raise ConfigParseError.new("Stack defaults can't be undefined") if @stack_defaults.nil?
57
+
55
58
  load_template_compilers(config)
56
59
  load_config
57
60
  end
@@ -72,6 +75,7 @@ module StackMaster
72
75
  end
73
76
 
74
77
  private
78
+
75
79
  def load_template_compilers(config)
76
80
  @template_compilers = {}
77
81
  populate_template_compilers(config.fetch('template_compilers', {}))
@@ -92,9 +96,9 @@ module StackMaster
92
96
  {
93
97
  rb: :sparkle_formation,
94
98
  json: :json,
95
- yml: :yaml,
99
+ yml: :yaml,
96
100
  yaml: :yaml,
97
- erb: :yaml_erb,
101
+ erb: :yaml_erb,
98
102
  }
99
103
  end
100
104
 
@@ -123,7 +127,8 @@ module StackMaster
123
127
  'base_dir' => @base_dir,
124
128
  'template_dir' => @template_dir,
125
129
  'parameters_dir' => @parameters_dir,
126
- 'additional_parameter_lookup_dirs' => @region_to_aliases[region])
130
+ 'additional_parameter_lookup_dirs' => @region_to_aliases[region]
131
+ )
127
132
  stack_attributes['allowed_accounts'] = attributes['allowed_accounts'] if attributes['allowed_accounts']
128
133
  @stacks << StackDefinition.new(stack_attributes)
129
134
  end
@@ -21,7 +21,8 @@ module StackMaster
21
21
  def account_aliases
22
22
  @aliases ||= iam.list_account_aliases.account_aliases
23
23
  rescue Aws::IAM::Errors::AccessDenied
24
- raise MissingIamPermissionsError, 'Failed to retrieve account aliases. Missing required IAM permission: iam:ListAccountAliases'
24
+ raise MissingIamPermissionsError,
25
+ 'Failed to retrieve account aliases. Missing required IAM permission: iam:ListAccountAliases'
25
26
  end
26
27
 
27
28
  private
@@ -2,13 +2,12 @@ require 'active_support/core_ext/object/deep_dup'
2
2
 
3
3
  module StackMaster
4
4
  class ParameterLoader
5
-
6
5
  COMPILE_TIME_PARAMETERS_KEY = 'compile_time_parameters'
7
6
 
8
7
  def self.load(parameter_files: [], parameters: {})
9
8
  StackMaster.debug 'Searching for parameter files...'
10
9
  all_parameters = parameter_files.map { |file_name| load_parameters(file_name) } + [parameters]
11
- all_parameters.reduce({template_parameters: {}, compile_time_parameters: {}}) do |hash, parameters|
10
+ all_parameters.reduce({ template_parameters: {}, compile_time_parameters: {} }) do |hash, parameters|
12
11
  template_parameters = create_template_parameters(parameters)
13
12
  compile_time_parameters = create_compile_time_parameters(parameters)
14
13
 
@@ -32,7 +31,8 @@ module StackMaster
32
31
 
33
32
  def self.create_template_parameters(parameters)
34
33
  parameters.deep_dup.tap do |parameters_clone|
35
- parameters_clone.delete(COMPILE_TIME_PARAMETERS_KEY) || parameters_clone.delete(COMPILE_TIME_PARAMETERS_KEY.camelize)
34
+ parameters_clone.delete(COMPILE_TIME_PARAMETERS_KEY) ||
35
+ parameters_clone.delete(COMPILE_TIME_PARAMETERS_KEY.camelize)
36
36
  end
37
37
  end
38
38
 
@@ -43,6 +43,5 @@ module StackMaster
43
43
  def self.merge_and_camelize(hash, parameters)
44
44
  parameters.each { |key, value| hash[key.camelize] = value }
45
45
  end
46
-
47
46
  end
48
47
  end
@@ -49,6 +49,7 @@ module StackMaster
49
49
  return parameter_value.to_s if Numeric === parameter_value || parameter_value == true || parameter_value == false
50
50
  return resolve_array_parameter_values(key, parameter_value).join(',') if Array === parameter_value
51
51
  return parameter_value unless Hash === parameter_value
52
+
52
53
  resolve_parameter_resolver_hash(key, parameter_value)
53
54
  rescue Aws::CloudFormation::Errors::ValidationError
54
55
  raise InvalidParameter, $!.message
@@ -77,6 +78,7 @@ module StackMaster
77
78
  if account.nil? || role.nil?
78
79
  raise InvalidParameter, "Both 'account' and 'role' are required to assume role for parameter '#{key}'"
79
80
  end
81
+
80
82
  role_assumer.assume_role(account, role) do
81
83
  yield
82
84
  end
@@ -105,7 +107,8 @@ module StackMaster
105
107
  begin
106
108
  @resolvers[class_name] = resolver_class_const(class_name).new(@config, @stack_definition)
107
109
  rescue NameError
108
- raise ResolverNotFound, "Could not find parameter resolver called #{class_name}, please double check your configuration"
110
+ raise ResolverNotFound,
111
+ "Could not find parameter resolver called #{class_name}, please double check your configuration"
109
112
  end
110
113
  end
111
114
  end
@@ -10,7 +10,10 @@ module StackMaster
10
10
 
11
11
  def resolve(domain_name)
12
12
  cert_arn = find_cert_arn_by_domain_name(domain_name)
13
- raise CertificateNotFound, "Could not find certificate #{domain_name} in #{@stack_definition.region}" unless cert_arn
13
+ unless cert_arn
14
+ raise CertificateNotFound, "Could not find certificate #{domain_name} in #{@stack_definition.region}"
15
+ end
16
+
14
17
  cert_arn
15
18
  end
16
19
 
@@ -15,7 +15,7 @@ module StackMaster
15
15
  end
16
16
 
17
17
  def build_filters_from_hash(hash)
18
- hash.map { |key, value| {name: key, values: Array(value.to_s)}}
18
+ hash.map { |key, value| { name: key, values: Array(value.to_s) } }
19
19
  end
20
20
 
21
21
  def find_latest_ami(filters, owners = ['self'])
@@ -23,16 +23,19 @@ module StackMaster
23
23
 
24
24
  def validate_ejson_file_specified
25
25
  if @stack_definition.ejson_file.nil?
26
- raise ArgumentError, "No ejson_file defined for stack definition #{@stack_definition.stack_name} in #{@stack_definition.region}"
26
+ raise ArgumentError, 'No ejson_file defined for stack definition ' \
27
+ "#{@stack_definition.stack_name} in #{@stack_definition.region}"
27
28
  end
28
29
  end
29
30
 
30
31
  def decrypt_ejson_file
31
32
  ejson_file_key = credentials_key
32
33
  @decrypted_ejson_files.fetch(ejson_file_key) do
33
- @decrypted_ejson_files[ejson_file_key] = EJSONWrapper.decrypt(ejson_file_path,
34
- use_kms: @stack_definition.ejson_file_kms,
35
- region: ejson_file_region)
34
+ @decrypted_ejson_files[ejson_file_key] = EJSONWrapper.decrypt(
35
+ ejson_file_path,
36
+ use_kms: @stack_definition.ejson_file_kms,
37
+ region: ejson_file_region
38
+ )
36
39
  end
37
40
  end
38
41
 
@@ -1,7 +1,6 @@
1
1
  module StackMaster
2
2
  module ParameterResolvers
3
3
  class Env < Resolver
4
-
5
4
  def initialize(config, stack_definition)
6
5
  @config = config
7
6
  @stack_definition = stack_definition
@@ -10,9 +9,9 @@ module StackMaster
10
9
  def resolve(value)
11
10
  environment_variable = ENV[value]
12
11
  raise ArgumentError, "The environment variable #{value} is not set" if environment_variable.nil?
12
+
13
13
  environment_variable
14
14
  end
15
-
16
15
  end
17
16
  end
18
17
  end
@@ -28,7 +28,8 @@ module StackMaster
28
28
  latest_image = images.first
29
29
 
30
30
  # aws_account_id.dkr.ecr.region.amazonaws.com/repository@sha256:digest
31
- "#{latest_image.registry_id}.dkr.ecr.#{@region}.amazonaws.com/#{parameters['repository_name']}@#{latest_image.image_digest}"
31
+ "#{latest_image.registry_id}.dkr.ecr.#{@region}.amazonaws.com/#{parameters['repository_name']}@" \
32
+ "#{latest_image.image_digest}"
32
33
  end
33
34
 
34
35
  private
@@ -36,15 +37,16 @@ module StackMaster
36
37
  def fetch_images(repository_name, registry_id, ecr)
37
38
  images = []
38
39
  next_token = nil
39
- while
40
- resp = ecr.describe_images({
40
+ while resp = ecr.describe_images(
41
+ {
41
42
  repository_name: repository_name,
42
43
  registry_id: registry_id,
43
44
  next_token: next_token,
44
45
  filter: {
45
46
  tag_status: "TAGGED",
46
47
  },
47
- })
48
+ }
49
+ )
48
50
 
49
51
  images += resp.image_details
50
52
  next_token = resp.next_token
@@ -13,8 +13,12 @@ module StackMaster
13
13
  @stack_definition = stack_definition
14
14
  end
15
15
 
16
- def resolve(params={})
17
- raise OnePasswordNotAbleToAuthenticate, "1password requires the `OP_SESSION_<name>` to be set, (remember to sign in?)" if ENV.keys.grep(/OP_SESSION_\w+$/).empty?
16
+ def resolve(params = {})
17
+ if ENV.keys.grep(/OP_SESSION_\w+$/).empty?
18
+ raise OnePasswordNotAbleToAuthenticate,
19
+ "1password requires the `OP_SESSION_<name>` to be set, (remember to sign in?)"
20
+ end
21
+
18
22
  get_items(params)
19
23
  end
20
24
 
@@ -40,7 +44,7 @@ module StackMaster
40
44
  end
41
45
 
42
46
  def password_item(data)
43
- data.details.password
47
+ data.details.password
44
48
  end
45
49
 
46
50
  def login_item(data)