moonshot 2.0.0.beta6 → 2.0.0.beta7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +5 -5
  2. data/bin/moonshot +4 -1
  3. data/lib/default/bin/build.sh +0 -0
  4. data/lib/moonshot/account_context.rb +2 -0
  5. data/lib/moonshot/always_use_default_source.rb +5 -4
  6. data/lib/moonshot/artifact_repository/s3_bucket.rb +11 -5
  7. data/lib/moonshot/artifact_repository/s3_bucket_via_github_releases.rb +7 -7
  8. data/lib/moonshot/ask_user_source.rb +2 -0
  9. data/lib/moonshot/build_mechanism/github_release.rb +9 -2
  10. data/lib/moonshot/build_mechanism/script.rb +8 -7
  11. data/lib/moonshot/build_mechanism/travis_deploy.rb +5 -5
  12. data/lib/moonshot/build_mechanism/version_proxy.rb +13 -0
  13. data/lib/moonshot/change_set.rb +17 -35
  14. data/lib/moonshot/command.rb +3 -1
  15. data/lib/moonshot/command_line.rb +12 -9
  16. data/lib/moonshot/command_line_dispatcher.rb +5 -7
  17. data/lib/moonshot/commands/build.rb +6 -0
  18. data/lib/moonshot/commands/console.rb +2 -0
  19. data/lib/moonshot/commands/create.rb +14 -2
  20. data/lib/moonshot/commands/delete.rb +9 -0
  21. data/lib/moonshot/commands/deploy.rb +4 -8
  22. data/lib/moonshot/commands/doctor.rb +2 -0
  23. data/lib/moonshot/commands/generate_template.rb +46 -0
  24. data/lib/moonshot/commands/interactive_command.rb +15 -0
  25. data/lib/moonshot/commands/list.rb +2 -0
  26. data/lib/moonshot/commands/new.rb +5 -2
  27. data/lib/moonshot/commands/parameter_arguments.rb +5 -4
  28. data/lib/moonshot/commands/parent_stack_option.rb +2 -0
  29. data/lib/moonshot/commands/push.rb +2 -0
  30. data/lib/moonshot/commands/show_all_events_option.rb +2 -0
  31. data/lib/moonshot/commands/ssh.rb +4 -0
  32. data/lib/moonshot/commands/status.rb +2 -0
  33. data/lib/moonshot/commands/update.rb +7 -1
  34. data/lib/moonshot/commands/version.rb +2 -0
  35. data/lib/moonshot/controller.rb +28 -13
  36. data/lib/moonshot/controller_config.rb +12 -27
  37. data/lib/moonshot/creds_helper.rb +2 -0
  38. data/lib/moonshot/deployment_mechanism/code_deploy.rb +44 -37
  39. data/lib/moonshot/doctor_helper.rb +14 -15
  40. data/lib/moonshot/dynamic_template.rb +76 -0
  41. data/lib/moonshot/interactive_logger_proxy.rb +4 -4
  42. data/lib/moonshot/json_stack_template.rb +3 -0
  43. data/lib/moonshot/parameter_collection.rb +3 -0
  44. data/lib/moonshot/parent_stack_parameter_loader.rb +7 -3
  45. data/lib/moonshot/resources.rb +2 -0
  46. data/lib/moonshot/resources_helper.rb +5 -1
  47. data/lib/moonshot/shell.rb +8 -8
  48. data/lib/moonshot/ssh_command.rb +2 -0
  49. data/lib/moonshot/ssh_command_builder.rb +3 -1
  50. data/lib/moonshot/ssh_config.rb +3 -2
  51. data/lib/moonshot/ssh_fork_executor.rb +2 -0
  52. data/lib/moonshot/ssh_target_selector.rb +3 -1
  53. data/lib/moonshot/stack.rb +50 -46
  54. data/lib/moonshot/stack_asg_printer.rb +14 -12
  55. data/lib/moonshot/stack_config.rb +3 -2
  56. data/lib/moonshot/stack_events_poller.rb +3 -1
  57. data/lib/moonshot/stack_list_printer.rb +2 -0
  58. data/lib/moonshot/stack_lister.rb +6 -2
  59. data/lib/moonshot/stack_output_printer.rb +2 -0
  60. data/lib/moonshot/stack_parameter.rb +5 -9
  61. data/lib/moonshot/stack_parameter_printer.rb +3 -1
  62. data/lib/moonshot/stack_template.rb +2 -0
  63. data/lib/moonshot/task.rb +3 -0
  64. data/lib/moonshot/tools/asg_rollout/asg.rb +19 -21
  65. data/lib/moonshot/tools/asg_rollout/asg_instance.rb +2 -0
  66. data/lib/moonshot/tools/asg_rollout/hook_exec_environment.rb +2 -0
  67. data/lib/moonshot/tools/asg_rollout/instance_health.rb +2 -0
  68. data/lib/moonshot/tools/asg_rollout.rb +16 -14
  69. data/lib/moonshot/tools/asg_rollout_config.rb +2 -0
  70. data/lib/moonshot/unicode_table.rb +1 -1
  71. data/lib/moonshot/yaml_stack_template.rb +2 -0
  72. data/lib/moonshot.rb +13 -1
  73. data/lib/plugins/backup.rb +24 -30
  74. data/lib/plugins/code_deploy_setup.rb +4 -2
  75. data/lib/plugins/dynamic_template.rb +36 -0
  76. data/lib/plugins/encrypted_parameters/kms_key.rb +2 -0
  77. data/lib/plugins/encrypted_parameters/parameter_encrypter.rb +2 -0
  78. data/lib/plugins/encrypted_parameters.rb +3 -1
  79. metadata +124 -57
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+
5
+ module Moonshot
6
+ class TemplateExists < StandardError; end
7
+ class InvalidTemplate < StandardError; end
8
+
9
+ class DynamicTemplate
10
+ # A class to encapsulate template parameters, passing a hash to `process` is
11
+ # only available from Ruby 2.5.
12
+ class Parameters
13
+ def initialize(parameters)
14
+ parameters.each do |k, v|
15
+ instance_variable_set("@#{k}".to_sym, v)
16
+ # Adding an attribute reader for flexibility, this way you can add
17
+ # either `@parameter` or just `parameter` to your template.
18
+ self.class.send(:attr_reader, k.to_sym)
19
+ end
20
+ end
21
+
22
+ def expose_binding
23
+ binding
24
+ end
25
+ end
26
+
27
+ attr_writer :destination
28
+
29
+ def initialize(source:, parameters:, destination:)
30
+ @source = File.read(source)
31
+ @parameters = parameters
32
+ @destination = destination
33
+ end
34
+
35
+ def parameters_obj
36
+ @parameters_obj ||= Parameters.new(parameters_file)
37
+ end
38
+
39
+ def parameters_file
40
+ env_name = Moonshot.config.environment_name
41
+ @parameters.respond_to?(:call) ? @parameters.call(env_name) : @parameters
42
+ end
43
+
44
+ def process
45
+ validate_destination_exists
46
+ new_template = generate_template
47
+
48
+ validate_template(new_template)
49
+ write_output(new_template)
50
+ end
51
+
52
+ private
53
+
54
+ def validate_destination_exists
55
+ return unless File.file?(@destination)
56
+
57
+ raise TemplateExists, "Output file '#{@destination}' already exists."
58
+ end
59
+
60
+ def validate_template(template)
61
+ Aws::CloudFormation::Client.new.validate_template(
62
+ template_body: template
63
+ )
64
+ rescue Aws::CloudFormation::Errors::ValidationError => e
65
+ raise InvalidTemplate, "Invalid template:\n#{e}"
66
+ end
67
+
68
+ def generate_template
69
+ ERB.new(@source).result(parameters_obj.expose_binding)
70
+ end
71
+
72
+ def write_output(content)
73
+ File.write(@destination, content)
74
+ end
75
+ end
76
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'forwardable'
2
4
 
3
5
  module Moonshot
@@ -10,8 +12,7 @@ module Moonshot
10
12
  @logger = logger
11
13
  end
12
14
 
13
- def blank
14
- end
15
+ def blank; end
15
16
 
16
17
  def continue(str = nil)
17
18
  @logger.info(str) if str
@@ -21,8 +22,7 @@ module Moonshot
21
22
  @logger.error(str)
22
23
  end
23
24
 
24
- def repaint
25
- end
25
+ def repaint; end
26
26
 
27
27
  def success(str = 'Success')
28
28
  @logger.info(str)
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
4
+ require_relative 'stack_template'
2
5
 
3
6
  module Moonshot
4
7
  # Handles JSON formatted AWS template files.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  # A Rigid Hash-like structure that only accepts manipulation of
3
5
  # parameters defined in the Stack template. Anything else results in
@@ -6,6 +8,7 @@ module Moonshot
6
8
  extend Forwardable
7
9
 
8
10
  def_delegators :@hash, :key?, :fetch, :[], :keys, :values
11
+ attr_reader :hash
9
12
 
10
13
  def self.from_template(template)
11
14
  obj = new
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  class ParentStackParameterLoader
3
5
  def initialize(config)
@@ -8,30 +10,32 @@ module Moonshot
8
10
  @config.parent_stacks.each do |stack_name|
9
11
  count = 0
10
12
 
11
- resp = cf_client.describe_stacks(stack_name: stack_name)
13
+ resp = cf_client.describe_stacks(stack_name:)
12
14
  raise "Parent Stack #{stack_name} not found!" unless resp.stacks.size == 1
13
15
 
14
16
  # If there is an input parameters matching a stack output, pass it.
15
17
  resp.stacks[0].outputs.each do |output|
16
18
  next unless @config.parameters.key?(output.output_key)
19
+
17
20
  # Our Stack has a Parameter matching this output. Set it's
18
21
  # value to the Output's value.
19
22
  count += 1
20
23
  @config.parameters.fetch(output.output_key).set(output.output_value)
21
24
  end
22
25
 
23
- puts "Imported #{count} parameters from parent stack #{stack_name.blue}!" if count > 0
26
+ puts "Imported #{count} parameters from parent stack #{stack_name.blue}!" if count.positive?
24
27
  end
25
28
  end
26
29
 
27
30
  def load_missing_only!
28
31
  @config.parent_stacks.each do |stack_name|
29
- resp = cf_client.describe_stacks(stack_name: stack_name)
32
+ resp = cf_client.describe_stacks(stack_name:)
30
33
  raise "Parent Stack #{stack_name} not found!" unless resp.stacks.size == 1
31
34
 
32
35
  # If there is an input parameters matching a stack output, pass it.
33
36
  resp.stacks[0].outputs.each do |output|
34
37
  next unless @config.parameters.key?(output.output_key)
38
+
35
39
  # Our Stack has a Parameter matching this output. Set it's
36
40
  # value to the Output's value, but only if we don't already
37
41
  # have a previous value we're using.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  # Resources is a dependency container that holds references to instances
3
5
  # provided to a Mechanism (build, deploy, etc.).
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  # Provides shorthand methods for accessing resources provided by the Resources
3
5
  # container.
@@ -8,16 +10,18 @@ module Moonshot
8
10
 
9
11
  # TODO: Deprecate this interface.
10
12
  def log
11
- @log ||= Logger.new(STDOUT)
13
+ @log ||= Logger.new($stdout)
12
14
  end
13
15
 
14
16
  def stack
15
17
  raise 'Resources not provided to Mechanism!' unless @resources
18
+
16
19
  @resources.stack
17
20
  end
18
21
 
19
22
  def ilog
20
23
  raise 'Resources not provided to Mechanism!' unless @resources
24
+
21
25
  @resources.ilog
22
26
  end
23
27
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thor'
2
4
  require 'retriable'
3
5
 
@@ -17,7 +19,7 @@ module Moonshot::Shell
17
19
 
18
20
  # Run a command, returning stdout. Stderr is suppressed unless the command
19
21
  # returns non-zero.
20
- def sh_out(cmd, fail: true, stdin: '')
22
+ def sh_out(cmd, fail = true, stdin = '')
21
23
  r_in, w_in = IO.pipe
22
24
  r_out, w_out = IO.pipe
23
25
  r_err, w_err = IO.pipe
@@ -53,13 +55,11 @@ module Moonshot::Shell
53
55
  define_method(meth) { |*args| shell.public_send(meth, *args) }
54
56
  end
55
57
 
56
- def sh_step(cmd, args = {})
58
+ def sh_step(cmd, **args)
57
59
  msg = args.delete(:msg) || cmd
58
- if msg.length > (terminal_width - 18)
59
- msg = "#{msg[0..(terminal_width - 22)]}..."
60
- end
60
+ msg = "#{msg[0..(terminal_width - 22)]}..." if msg.length > (terminal_width - 18)
61
61
  ilog.start_threaded(msg) do |step|
62
- out = sh_out(cmd, args)
62
+ out = sh_out(cmd, **args)
63
63
  yield step, out if block_given?
64
64
  step.success
65
65
  end
@@ -73,9 +73,9 @@ module Moonshot::Shell
73
73
  # @param opts [Hash] Options for retriable.
74
74
  #
75
75
  # @return [String] Stdout form the command.
76
- def sh_retry(cmd, fail: true, stdin: '', opts: {})
76
+ def sh_retry(cmd, fail = true, stdin = '', opts: {})
77
77
  Retriable.retriable(DEFAULT_RETRY_OPTIONS.merge(opts)) do
78
- out = sh_out(cmd, stdin: stdin)
78
+ out = sh_out(cmd, stdin:)
79
79
  yield out if block_given?
80
80
  out
81
81
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thor'
2
4
 
3
5
  module Moonshot
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'shellwords'
2
4
 
3
5
  module Moonshot
@@ -25,7 +27,7 @@ module Moonshot
25
27
  @instance_ip ||= Aws::EC2::Client.new
26
28
  .describe_instances(instance_ids: [@instance_id])
27
29
  .reservations.first.instances.first.public_ip_address
28
- rescue
30
+ rescue StandardError
29
31
  raise "Failed to determine public IP address for instance #{@instance_id}!"
30
32
  end
31
33
  end
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  class SSHConfig
3
- attr_accessor :ssh_identity_file
4
- attr_accessor :ssh_user
5
+ attr_accessor :ssh_identity_file, :ssh_user
5
6
 
6
7
  def initialize
7
8
  @ssh_identity_file = ENV['MOONSHOT_SSH_KEY_FILE']
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'open3'
2
4
 
3
5
  module Moonshot
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  # Choose a publically accessible instance to run commands on, given a Moonshot::Stack.
3
5
  class SSHTargetSelector
@@ -23,7 +25,7 @@ module Moonshot
23
25
  Aws::AutoScaling::Client.new.describe_auto_scaling_groups(
24
26
  auto_scaling_group_names: [asg.physical_resource_id]
25
27
  ).auto_scaling_groups.first.instances.map(&:instance_id).first
26
- rescue => e
28
+ rescue StandardError => e
27
29
  raise "Failed to select an instance from the Auto Scaling Group: #{e.message}"
28
30
  end
29
31
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'yaml'
2
4
 
3
5
  module Moonshot
@@ -5,12 +7,11 @@ module Moonshot
5
7
  # stores the state of the active stack running on AWS, but contains a
6
8
  # reference to the StackTemplate that would be applied with an update
7
9
  # action.
8
- class Stack # rubocop:disable ClassLength
10
+ class Stack # rubocop:disable Metrics/ClassLength
9
11
  include CredsHelper
10
12
  include DoctorHelper
11
13
 
12
- attr_reader :app_name
13
- attr_reader :name
14
+ attr_reader :app_name, :name
14
15
 
15
16
  def initialize(config)
16
17
  @config = config
@@ -111,7 +112,7 @@ module Moonshot
111
112
  resource_summary = resource_summaries.find do |r|
112
113
  r.logical_resource_id == logical_id
113
114
  end
114
- resource_summary.physical_resource_id if resource_summary
115
+ resource_summary&.physical_resource_id
115
116
  end
116
117
 
117
118
  # @return [Array<Aws::CloudFormation::Types::StackResourceSummary>]
@@ -152,13 +153,23 @@ module Moonshot
152
153
 
153
154
  # Support the legacy file location from Moonshot 1.0.
154
155
  YamlStackTemplate.new(
155
- File.join(@config.project_root, 'cloud_formation', "#{@config.app_name}.yml")),
156
+ File.join(@config.project_root, 'cloud_formation', "#{@config.app_name}.yml")
157
+ ),
156
158
  JsonStackTemplate.new(
157
- File.join(@config.project_root, 'cloud_formation', "#{@config.app_name}.json"))
159
+ File.join(@config.project_root, 'cloud_formation', "#{@config.app_name}.json")
160
+ )
158
161
  ]
159
162
 
163
+ # If a template file has been specified in the config, look there first.
164
+ if @config.template_file
165
+ templates.unshift YamlStackTemplate.new(@config.template_file)
166
+ templates.unshift JsonStackTemplate.new(@config.template_file)
167
+ end
168
+
160
169
  template = templates.find(&:exist?)
170
+
161
171
  raise 'No template found in moonshot/template.{yml,json}!' unless template
172
+
162
173
  template
163
174
  end
164
175
 
@@ -177,9 +188,7 @@ module Moonshot
177
188
  end
178
189
 
179
190
  def upload_template_to_s3
180
- unless @config.template_s3_bucket
181
- raise 'The S3 bucket to store the template in is not configured.'
182
- end
191
+ raise 'The S3 bucket to store the template in is not configured.' unless @config.template_s3_bucket
183
192
 
184
193
  s3_object_key = "#{@name}-#{Time.now.getutc.to_i}-#{File.basename(template.filename)}"
185
194
  template_url = "http://#{@config.template_s3_bucket}.s3.amazonaws.com/#{s3_object_key}"
@@ -199,7 +208,7 @@ module Moonshot
199
208
  def create_stack
200
209
  parameters = {
201
210
  stack_name: @name,
202
- capabilities: %w(CAPABILITY_IAM CAPABILITY_NAMED_IAM),
211
+ capabilities: %w[CAPABILITY_IAM CAPABILITY_NAMED_IAM],
203
212
  parameters: @config.parameters.values.map(&:to_cf),
204
213
  tags: make_tags
205
214
  }
@@ -221,10 +230,10 @@ module Moonshot
221
230
  ].join('-')
222
231
 
223
232
  parameters = {
224
- change_set_name: change_set_name,
233
+ change_set_name:,
225
234
  description: "Moonshot update command for application '#{Moonshot.config.app_name}'",
226
235
  stack_name: @name,
227
- capabilities: %w(CAPABILITY_IAM CAPABILITY_NAMED_IAM),
236
+ capabilities: %w[CAPABILITY_IAM CAPABILITY_NAMED_IAM],
228
237
  parameters: @config.parameters.values.map(&:to_cf)
229
238
  }
230
239
  if @config.template_s3_bucket
@@ -248,36 +257,31 @@ module Moonshot
248
257
  events.show_only_errors unless @config.show_all_stack_events
249
258
 
250
259
  @ilog.start_threaded "Waiting for #{stack_name} to be successfully #{past_tense_verb}." do |s|
251
- begin
252
- cf_client.wait_until(wait_target, stack_name: stack_id) do |w|
253
- w.delay = 10
254
- w.max_attempts = 360 # 60 minutes.
255
- w.before_wait do |attempt, resp|
256
- begin
257
- events.latest_events.each { |e| @ilog.error(format_event(e)) }
258
- # rubocop:disable Lint/HandleExceptions
259
- rescue Aws::CloudFormation::Errors::ValidationError
260
- # Do nothing. The above event logging block may result in
261
- # a ValidationError while waiting for a stack to delete.
262
- end
263
- # rubocop:enable Lint/HandleExceptions
264
-
265
- if attempt == w.max_attempts - 1
266
- s.failure "#{stack_name} was not #{past_tense_verb} after 30 minutes."
267
- result = false
268
-
269
- # We don't want the interactive logger to catch an exception.
270
- throw :success
271
- end
272
- s.continue "Waiting for CloudFormation Stack to be successfully #{past_tense_verb}, current status '#{resp.stacks.first.stack_status}'." # rubocop:disable LineLength
260
+ cf_client.wait_until(wait_target, stack_name: stack_id) do |w|
261
+ w.delay = 10
262
+ w.max_attempts = 360 # 60 minutes.
263
+ w.before_wait do |attempt, resp|
264
+ begin
265
+ events.latest_events.each { |e| @ilog.error(format_event(e)) }
266
+ rescue Aws::CloudFormation::Errors::ValidationError
267
+ # Do nothing. The above event logging block may result in
268
+ # a ValidationError while waiting for a stack to delete.
273
269
  end
274
- end
270
+ if attempt == w.max_attempts - 1
271
+ s.failure "#{stack_name} was not #{past_tense_verb} after 30 minutes."
272
+ result = false
275
273
 
276
- s.success "#{stack_name} successfully #{past_tense_verb}." if result
277
- rescue Aws::Waiters::Errors::FailureStateError
278
- result = false
279
- s.failure "#{stack_name} failed to update."
274
+ # We don't want the interactive logger to catch an exception.
275
+ throw :success
276
+ end
277
+ s.continue "Waiting for CloudFormation Stack to be successfully #{past_tense_verb}, current status '#{resp.stacks.first.stack_status}'." # rubocop:disable Layout/LineLength
278
+ end
280
279
  end
280
+
281
+ s.success "#{stack_name} successfully #{past_tense_verb}." if result
282
+ rescue Aws::Waiters::Errors::FailureStateError
283
+ result = false
284
+ s.failure "#{stack_name} failed to update."
281
285
  end
282
286
 
283
287
  result
@@ -289,9 +293,7 @@ module Moonshot
289
293
  { key: 'moonshot_environment', value: @config.environment_name }
290
294
  ]
291
295
 
292
- if @config.additional_tag
293
- default_tags << { key: @config.additional_tag, value: @name }
294
- end
296
+ default_tags << { key: @config.additional_tag, value: @name } if @config.additional_tag
295
297
 
296
298
  default_tags
297
299
  end
@@ -320,14 +322,15 @@ module Moonshot
320
322
  end
321
323
 
322
324
  def doctor_check_template_against_aws
325
+ validate_params = {}
323
326
  if @config.template_s3_bucket
324
- parameters[:template_url] = upload_template_to_s3
327
+ validate_params[:template_url] = upload_template_to_s3
325
328
  else
326
- parameters[:template_body] = template.body
329
+ validate_params[:template_body] = template.body
327
330
  end
328
- cf_client.validate_template(parameters)
331
+ cf_client.validate_template(validate_params)
329
332
  success('CloudFormation template is valid.')
330
- rescue => e
333
+ rescue StandardError => e
331
334
  critical('Invalid CloudFormation template!', e.message)
332
335
  end
333
336
 
@@ -351,6 +354,7 @@ module Moonshot
351
354
 
352
355
  success = wait_for_stack_state(:stack_update_complete, 'updated')
353
356
  raise 'Failed to update the CloudFormation Stack.' unless success
357
+
354
358
  success
355
359
  end
356
360
  end
@@ -1,4 +1,5 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  require 'colorize'
3
4
  require 'ruby-duration'
4
5
 
@@ -16,8 +17,8 @@ module Moonshot
16
17
  def print
17
18
  asgs.each do |asg|
18
19
  asg_info = as_client.describe_auto_scaling_groups(
19
- auto_scaling_group_names: [asg.physical_resource_id])
20
- .auto_scaling_groups.first
20
+ auto_scaling_group_names: [asg.physical_resource_id]
21
+ ).auto_scaling_groups.first
21
22
  t_asg_info = @table.add_leaf("ASG: #{asg.logical_resource_id}")
22
23
 
23
24
  add_asg_info(t_asg_info, asg_info)
@@ -70,7 +71,7 @@ module Moonshot
70
71
 
71
72
  # Get additional information about instances not returned by the ASG API.
72
73
  def get_addl_info(instance_ids)
73
- resp = ec2_client.describe_instances(instance_ids: instance_ids)
74
+ resp = ec2_client.describe_instances(instance_ids:)
74
75
 
75
76
  data = {}
76
77
  resp.reservations.map(&:instances).flatten.each do |instance|
@@ -85,7 +86,7 @@ module Moonshot
85
86
 
86
87
  hc = asg_info.health_check_type.blue
87
88
  gp = (asg_info.health_check_grace_period.to_s << 's').blue
88
- table.add_line "Using #{hc} health checks, with a #{gp} health check grace period." # rubocop:disable LineLength
89
+ table.add_line "Using #{hc} health checks, with a #{gp} health check grace period."
89
90
 
90
91
  dc = asg_info.desired_capacity.to_s.blue
91
92
  min = asg_info.min_size.to_s.blue
@@ -93,7 +94,7 @@ module Moonshot
93
94
  table.add_line "Desired Capacity is #{dc} (Min: #{min}, Max: #{max})."
94
95
 
95
96
  lbs = asg_info.load_balancer_names
96
- table.add_line "Has #{lbs.count.to_s.blue} Load Balancer(s): #{lbs.map(&:blue).join(', ')}" # rubocop:disable LineLength
97
+ table.add_line "Has #{lbs.count.to_s.blue} Load Balancer(s): #{lbs.map(&:blue).join(', ')}"
97
98
  end
98
99
 
99
100
  def create_instance_table(asg_info)
@@ -112,11 +113,11 @@ module Moonshot
112
113
 
113
114
  def instance_row(asg_instance, ec2_instance)
114
115
  if ec2_instance
115
- if ec2_instance.public_ip_address
116
- ip_address = "#{ec2_instance.public_ip_address} (#{ec2_instance.private_ip_address})"
117
- else
118
- ip_address = "#{ec2_instance.private_ip_address} (PRV)"
119
- end
116
+ ip_address = if ec2_instance.public_ip_address
117
+ "#{ec2_instance.public_ip_address} (#{ec2_instance.private_ip_address})"
118
+ else
119
+ "#{ec2_instance.private_ip_address} (PRV)"
120
+ end
120
121
  uptime = uptime_format(ec2_instance.launch_time)
121
122
  else
122
123
  # We've seen race conditions where ASG tells us about instances that EC2 is no longer
@@ -142,7 +143,8 @@ module Moonshot
142
143
  def add_recent_activity_leaf(table, asg_name)
143
144
  recent = table.add_leaf('Recent Activity')
144
145
  resp = as_client.describe_scaling_activities(
145
- auto_scaling_group_name: asg_name).activities
146
+ auto_scaling_group_name: asg_name
147
+ ).activities
146
148
 
147
149
  rows = resp.sort_by(&:start_time).reverse.first(10).map do |activity|
148
150
  row_for_activity(activity)
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  # Configuration for the Moonshot::Stack class.
3
5
  class StackConfig
4
- attr_accessor :parent_stacks
5
- attr_accessor :show_all_events
6
+ attr_accessor :parent_stacks, :show_all_events
6
7
 
7
8
  def initialize
8
9
  @parent_stacks = []
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  # The StackEventsPoller queries DescribeStackEvents every time #latest_events
3
5
  # is invoked, filtering out events that have already been returned. It can
@@ -32,7 +34,7 @@ module Moonshot
32
34
  def filter_events(events)
33
35
  if @errors_only
34
36
  events.select do |event|
35
- %w(CREATE_FAILED UPDATE_FAILED DELETE_FAILED).include?(event.resource_status)
37
+ %w[CREATE_FAILED UPDATE_FAILED DELETE_FAILED].include?(event.resource_status)
36
38
  end
37
39
  else
38
40
  events
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  class StackListPrinter
3
5
  attr_accessor :stacks
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  # The StackLister is world renoun for it's ability to list stacks.
3
5
  class StackLister
@@ -13,7 +15,7 @@ module Moonshot
13
15
  result = []
14
16
  next_token = nil
15
17
  loop do
16
- resp = cf_client.describe_stacks(next_token: next_token)
18
+ resp = cf_client.describe_stacks(next_token:)
17
19
  resp.stacks.each do |stack|
18
20
  app_tag = stack.tags.find { |t| t.key == 'moonshot_application' }
19
21
  env_tag = stack.tags.find { |t| t.key == 'moonshot_environment' }
@@ -22,15 +24,17 @@ module Moonshot
22
24
  if app_tag && app_tag.value == Moonshot.config.app_name
23
25
  result <<
24
26
  EnvironmentDescription.new(env_tag.value, stack.creation_time, stack.stack_status)
25
- elsif legacy_tag && legacy_tag.value.start_with?(Moonshot.config.app_name)
27
+ elsif legacy_tag&.value&.start_with?(Moonshot.config.app_name)
26
28
  result <<
27
29
  EnvironmentDescription.new(legacy_tag.value, stack.creation_time, stack.stack_status)
28
30
  end
29
31
  end
30
32
  break unless resp.next_token
33
+
31
34
  next_token = resp.next_token
32
35
  end
33
36
  result.sort_by(&:name)
34
37
  end
38
+ # rubocop:enable Metrics/AbcSize
35
39
  end
36
40
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  # Display the stack outputs to the user.
3
5
  class StackOutputPrinter
@@ -1,8 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  class StackParameter
3
- attr_reader :name
4
- attr_reader :default
5
- attr_reader :description
5
+ attr_reader :name, :default, :description
6
6
 
7
7
  def initialize(name, default: nil, use_previous: false, description: '')
8
8
  @default = default
@@ -32,9 +32,7 @@ module Moonshot
32
32
  end
33
33
 
34
34
  def use_previous!(value)
35
- if @value
36
- raise "Value already set for StackParameter #{@name}, cannot use previous value!"
37
- end
35
+ raise "Value already set for StackParameter #{@name}, cannot use previous value!" if @value
38
36
 
39
37
  # Make the current value available to plugins.
40
38
  @value = value
@@ -42,9 +40,7 @@ module Moonshot
42
40
  end
43
41
 
44
42
  def value
45
- unless @value || default?
46
- raise "No value set and no default for StackParameter #{@name}!"
47
- end
43
+ raise "No value set and no default for StackParameter #{@name}!" unless @value || default?
48
44
 
49
45
  @value || default
50
46
  end