moonshot 2.0.0.beta6 → 2.0.0.beta7

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 (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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  # Displays information about existing stack parameters to the user, with
3
5
  # information on what a stack update would do.
@@ -18,7 +20,7 @@ module Moonshot
18
20
 
19
21
  def format_value(value)
20
22
  if value.size > 60
21
- value[0..60] + '...'
23
+ "#{value[0..60]}..."
22
24
  else
23
25
  value
24
26
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  # A StackTemplate loads the template from disk and stores information
3
5
  # about it.
data/lib/moonshot/task.rb CHANGED
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  class Task
3
5
  attr_reader :name, :desc, :block
6
+
4
7
  def initialize(name, desc, &block)
5
8
  @name = name.to_sym
6
9
  @desc = desc
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  module Tools
3
5
  class ASGRollout
@@ -20,14 +22,15 @@ module Moonshot
20
22
  autoscaling.update_auto_scaling_group(
21
23
  auto_scaling_group_name: @name,
22
24
  max_size: max,
23
- desired_capacity: desired)
25
+ desired_capacity: desired
26
+ )
24
27
  end
25
28
 
26
29
  def non_conforming_instances
27
30
  asg = load_asg
28
31
 
29
32
  asg.instances
30
- .select { |i| i.launch_configuration_name != asg.launch_configuration_name }
33
+ .reject { |i| i.launch_configuration_name == asg.launch_configuration_name }
31
34
  .map(&:instance_id)
32
35
  end
33
36
 
@@ -59,17 +62,17 @@ module Moonshot
59
62
  resp = autoscaling.detach_instances(
60
63
  auto_scaling_group_name: @name,
61
64
  instance_ids: [id],
62
- should_decrement_desired_capacity: decrement)
65
+ should_decrement_desired_capacity: decrement
66
+ )
63
67
 
64
68
  activity = resp.activities.first
65
- unless activity
66
- raise 'Did not receive Activity from DetachInstances call!'
67
- end
69
+ raise 'Did not receive Activity from DetachInstances call!' unless activity
68
70
 
69
71
  # Wait for the detach activity to complete:
70
72
  loop do
71
73
  resp = autoscaling.describe_scaling_activities(
72
- auto_scaling_group_name: @name)
74
+ auto_scaling_group_name: @name
75
+ )
73
76
 
74
77
  current_status = resp.activities
75
78
  .find { |a| a.activity_id == activity.activity_id }
@@ -97,7 +100,8 @@ module Moonshot
97
100
 
98
101
  def asg_instance_state(id)
99
102
  resp = autoscaling.describe_auto_scaling_instances(
100
- instance_ids: [id])
103
+ instance_ids: [id]
104
+ )
101
105
 
102
106
  instance_info = resp.auto_scaling_instances.first
103
107
  return 'Missing' unless instance_info
@@ -108,14 +112,11 @@ module Moonshot
108
112
  def elb_instance_state(id)
109
113
  resp = loadbalancing.describe_instance_health(
110
114
  load_balancer_name: elb_name,
111
- instances: [
112
- { instance_id: id }
113
- ])
115
+ instances: [{ instance_id: id }]
116
+ )
114
117
 
115
118
  instance_info = resp.instance_states.first
116
- unless instance_info
117
- raise "Failed to call DescribeInstanceHealth for #{id}!"
118
- end
119
+ raise "Failed to call DescribeInstanceHealth for #{id}!" unless instance_info
119
120
 
120
121
  instance_info.state
121
122
  rescue Aws::ElasticLoadBalancing::Errors::InvalidInstance
@@ -133,11 +134,10 @@ module Moonshot
133
134
 
134
135
  def load_asg
135
136
  resp = autoscaling.describe_auto_scaling_groups(
136
- auto_scaling_group_names: [@name])
137
+ auto_scaling_group_names: [@name]
138
+ )
137
139
 
138
- if resp.auto_scaling_groups.empty?
139
- raise "Failed to call DescribeAutoScalingGroups for #{@name}!"
140
- end
140
+ raise "Failed to call DescribeAutoScalingGroups for #{@name}!" if resp.auto_scaling_groups.empty?
141
141
 
142
142
  asg = resp.auto_scaling_groups.first
143
143
  @last_seen_ids = asg.instances.map(&:instance_id)
@@ -149,9 +149,7 @@ module Moonshot
149
149
  return @elb_name if @elb_name
150
150
 
151
151
  asg = load_asg
152
- if asg.load_balancer_names.size > 1
153
- raise 'ASGRollout does not support configurations with multiple ELBs!'
154
- end
152
+ raise 'ASGRollout does not support configurations with multiple ELBs!' if asg.load_balancer_names.size > 1
155
153
 
156
154
  @elb_name ||= asg.load_balancer_names.first
157
155
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  module Tools
3
5
  class ASGRollout
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'moonshot/ssh_fork_executor'
2
4
 
3
5
  module Moonshot
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  module Tools
3
5
  class ASGRollout
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  module Tools
3
- class ASGRollout # rubocop:disable ClassLength
5
+ class ASGRollout # rubocop:disable Metrics/ClassLength
4
6
  attr_accessor :config
5
7
 
6
8
  def initialize(controller:, logical_id:)
@@ -16,7 +18,7 @@ module Moonshot
16
18
  new_instance = wait_for_new_instance
17
19
  begin
18
20
  wait_for_in_service(new_instance)
19
- rescue
21
+ rescue StandardError
20
22
  next
21
23
  end
22
24
  break
@@ -74,6 +76,7 @@ module Moonshot
74
76
  raise "Instance #{new_instance.blue} went OutOfService while waiting to join..."
75
77
  end
76
78
  break if instance_health.in_service?
79
+
77
80
  s.continue "Instance #{new_instance.blue} is #{instance_health}..."
78
81
  sleep @config.instance_health_delay
79
82
  end
@@ -83,22 +86,22 @@ module Moonshot
83
86
  end
84
87
 
85
88
  def run_pre_detach(instance)
86
- if @config.pre_detach
87
- log.start_threaded "Running PreDetach hook on #{instance.blue}..." do |s|
88
- he = HookExecEnvironment.new(@controller.config, instance)
89
- if false == @config.pre_detach.call(he)
90
- s.failure "PreDetach hook failed for #{instance.blue}!"
91
- raise "PreDetach hook failed for #{instance.blue}!"
92
- end
89
+ return unless @config.pre_detach
93
90
 
94
- s.success "PreDetach hook complete for #{instance.blue}!"
91
+ log.start_threaded "Running PreDetach hook on #{instance.blue}..." do |s|
92
+ he = HookExecEnvironment.new(@controller.config, instance)
93
+ if @config.pre_detach.call(he) == false
94
+ s.failure "PreDetach hook failed for #{instance.blue}!"
95
+ raise "PreDetach hook failed for #{instance.blue}!"
95
96
  end
97
+
98
+ s.success "PreDetach hook complete for #{instance.blue}!"
96
99
  end
97
100
  end
98
101
 
99
102
  def detach(instance, decrement:)
100
103
  log.start_threaded "Detaching instance #{instance.blue}..." do |s|
101
- asg.detach_instance(instance, decrement: decrement)
104
+ asg.detach_instance(instance, decrement:)
102
105
 
103
106
  if decrement
104
107
  s.success "Detached instance #{instance.blue}, and decremented DesiredCapacity."
@@ -115,6 +118,7 @@ module Moonshot
115
118
  loop do
116
119
  instance_health = asg.instance_health(instance)
117
120
  break if instance_health.out_of_service?
121
+
118
122
  s.continue "Instance #{instance.blue} is #{instance_health}..."
119
123
  sleep @config.instance_health_delay
120
124
  end
@@ -155,9 +159,7 @@ module Moonshot
155
159
  return @asg if @asg
156
160
 
157
161
  asg_name = @controller.stack.physical_id_for(@logical_id)
158
- unless asg_name
159
- raise "Could not find Auto Scaling Group #{@logical_id}!"
160
- end
162
+ raise "Could not find Auto Scaling Group #{@logical_id}!" unless asg_name
161
163
 
162
164
  @asg ||= ASGRollout::ASG.new(asg_name)
163
165
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  module Tools
3
5
  class ASGRolloutConfig
@@ -1,4 +1,4 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'colorize'
4
4
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'yaml'
2
4
 
3
5
  module Moonshot
data/lib/moonshot.rb CHANGED
@@ -1,5 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'English'
2
- require 'aws-sdk'
4
+
5
+ require 'aws-sdk-cloudformation'
6
+ require 'aws-sdk-codedeploy'
7
+ require 'aws-sdk-ec2'
8
+ require 'aws-sdk-iam'
9
+ require 'aws-sdk-autoscaling'
10
+ require 'aws-sdk-s3'
11
+
3
12
  require 'logger'
4
13
  require 'thor'
5
14
  require 'interactive-logger'
@@ -16,10 +25,13 @@ module Moonshot
16
25
 
17
26
  module ArtifactRepository
18
27
  end
28
+
19
29
  module BuildMechanism
20
30
  end
31
+
21
32
  module DeploymentMechanism
22
33
  end
34
+
23
35
  module Plugins
24
36
  end
25
37
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rubygems/package'
2
4
  require 'zlib'
3
5
  require 'yaml'
@@ -20,7 +22,7 @@ module Moonshot
20
22
  def initialize
21
23
  yield self if block_given?
22
24
  validate_configuration
23
- @target_name ||= '%{app_name}_%{timestamp}_%{user}.tar.gz'
25
+ @target_name ||= '%<app_name>s_%<timestamp>s_%<user>s.tar.gz'
24
26
  end
25
27
 
26
28
  # Factory method to create preconfigured Backup plugins. Uploads current
@@ -29,11 +31,12 @@ module Moonshot
29
31
  # @return [Backup] configured backup object
30
32
  def self.to_bucket(bucket)
31
33
  raise ArgumentError if bucket.nil? || bucket.empty?
34
+
32
35
  Moonshot::Plugins::Backup.new do |b|
33
36
  b.bucket = bucket
34
37
  b.backup_parameters = true
35
38
  b.backup_template = true
36
- b.hooks = [:post_create, :post_update]
39
+ b.hooks = %i[post_create post_update]
37
40
  end
38
41
  end
39
42
 
@@ -53,18 +56,16 @@ module Moonshot
53
56
  return if @target_bucket.nil?
54
57
 
55
58
  resources.ilog.start("#{log_message} in progress.") do |s|
56
- begin
57
- tar_out = tar(@files)
58
- zip_out = zip(tar_out)
59
- upload(zip_out)
60
-
61
- s.success("#{log_message} succeeded.")
62
- rescue => e
63
- s.failure("#{log_message} failed: #{e}")
64
- ensure
65
- tar_out.close unless tar_out.nil?
66
- zip_out.close unless zip_out.nil?
67
- end
59
+ tar_out = tar(@files)
60
+ zip_out = zip(tar_out)
61
+ upload(zip_out)
62
+
63
+ s.success("#{log_message} succeeded.")
64
+ rescue StandardError => e
65
+ s.failure("#{log_message} failed: #{e}")
66
+ ensure
67
+ tar_out&.close
68
+ zip_out&.close
68
69
  end
69
70
  end
70
71
 
@@ -110,7 +111,7 @@ module Moonshot
110
111
 
111
112
  # adding template file
112
113
  if @backup_template
113
- template_file_path = render('cloud_formation/%{app_name}.json')
114
+ template_file_path = render('cloud_formation/%<app_name>s.json')
114
115
  add_file_to_tar(writer, template_file_path)
115
116
  end
116
117
  end
@@ -123,12 +124,10 @@ module Moonshot
123
124
  # @param writer [TarWriter]
124
125
  # @param file_name [String]
125
126
  def add_file_to_tar(writer, file_name)
126
- writer.add_file(File.basename(file_name), 0644) do |io|
127
- begin
128
- File.open(file_name, 'r') { |f| io.write(f.read) }
129
- rescue Errno::ENOENT
130
- warn "'#{file_name}' was not found."
131
- end
127
+ writer.add_file(File.basename(file_name), 0o644) do |io|
128
+ File.open(file_name, 'r') { |f| io.write(f.read) }
129
+ rescue Errno::ENOENT
130
+ warn "'#{file_name}' was not found."
132
131
  end
133
132
  end
134
133
 
@@ -139,7 +138,7 @@ module Moonshot
139
138
  # @param target_filename [String]
140
139
  # @param content [String]
141
140
  def add_str_to_tar(writer, target_filename, content)
142
- writer.add_file(File.basename(target_filename), 0644) do |io|
141
+ writer.add_file(File.basename(target_filename), 0o644) do |io|
143
142
  io.write(content.to_yaml)
144
143
  end
145
144
  end
@@ -196,17 +195,12 @@ module Moonshot
196
195
  end
197
196
 
198
197
  def define_bucket
199
- case
200
198
  # returning already calculated bucket name
201
- when @target_bucket
202
- @target_bucket
199
+ return @target_bucket if @target_bucket
203
200
  # single bucket for all accounts
204
- when @bucket
205
- @bucket
201
+ return @bucket if @bucket
206
202
  # calculating bucket based on account name
207
- when @buckets
208
- bucket_by_account(iam_account)
209
- end
203
+ return bucket_by_account(iam_account) if @buckets
210
204
  end
211
205
 
212
206
  def bucket_by_account(account)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  module Plugins
3
5
  # Plugin to ensure CodeDeploy has all necessary S3 buckets created.
@@ -33,11 +35,11 @@ module Moonshot
33
35
  # Create an S3 bucket in each supported region for CodeDeploy
34
36
  def setup_code_deploy_s3_buckets
35
37
  @regions.uniq.each do |region|
36
- client = s3_client(region: region)
38
+ client = s3_client(region:)
37
39
  name = bucket_name(region)
38
40
  bucket = Aws::S3::Bucket.new(
39
41
  name,
40
- client: client
42
+ client:
41
43
  )
42
44
  bucket.create unless bucket.exists?
43
45
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moonshot
4
+ module Plugins
5
+ class DynamicTemplate
6
+ def initialize(source:, parameters:, destination:)
7
+ @dynamic_template = ::Moonshot::DynamicTemplate.new(
8
+ source:,
9
+ parameters:,
10
+ destination:
11
+ )
12
+ end
13
+
14
+ def run_hook
15
+ @dynamic_template.process
16
+ end
17
+
18
+ def cli_hook(parser)
19
+ parser.on('--template-file=FILE', 'Override the path to the CloudFormation template.') do |v|
20
+ @dynamic_template.destination = v
21
+ Moonshot.config.template_file = v
22
+ end
23
+ end
24
+
25
+ # Moonshot hooks to trigger this plugin.
26
+ alias setup_create run_hook
27
+ alias setup_update run_hook
28
+ alias setup_delete run_hook
29
+
30
+ # Moonshot hooks to add CLI options.
31
+ alias create_cli_hook cli_hook
32
+ alias delete_cli_hook cli_hook
33
+ alias update_cli_hook cli_hook
34
+ end
35
+ end
36
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Moonshot
2
4
  module Plugins
3
5
  class EncryptedParameters
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
  module Moonshot
3
5
  module Plugins
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This plugin encrypts parameters of the stack using a KMS Key,
2
4
  # storing and passing the key used to the stack as a parameter as
3
5
  # well. The resources in the stack can then use that KMS Key to
@@ -96,7 +98,7 @@ module Moonshot
96
98
 
97
99
  @ilog.start_threaded "Checking for KMS Key #{@kms_key_parameter_name}" do |s|
98
100
  if Moonshot.config.parameters.key?(@kms_key_parameter_name)
99
- if 'Auto' == Moonshot.config.parameters[@kms_key_parameter_name].value
101
+ if Moonshot.config.parameters[@kms_key_parameter_name].value == 'Auto'
100
102
  s.continue "Auto-generating KMS Key for #{@kms_key_parameter_name.blue}... "
101
103
  key_arn = KmsKey.create.arn
102
104
  Moonshot.config.parameters[@kms_key_parameter_name].set(key_arn)