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
@@ -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)