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.
- checksums.yaml +5 -5
- data/bin/moonshot +4 -1
- data/lib/default/bin/build.sh +0 -0
- data/lib/moonshot/account_context.rb +2 -0
- data/lib/moonshot/always_use_default_source.rb +5 -4
- data/lib/moonshot/artifact_repository/s3_bucket.rb +11 -5
- data/lib/moonshot/artifact_repository/s3_bucket_via_github_releases.rb +7 -7
- data/lib/moonshot/ask_user_source.rb +2 -0
- data/lib/moonshot/build_mechanism/github_release.rb +9 -2
- data/lib/moonshot/build_mechanism/script.rb +8 -7
- data/lib/moonshot/build_mechanism/travis_deploy.rb +5 -5
- data/lib/moonshot/build_mechanism/version_proxy.rb +13 -0
- data/lib/moonshot/change_set.rb +17 -35
- data/lib/moonshot/command.rb +3 -1
- data/lib/moonshot/command_line.rb +12 -9
- data/lib/moonshot/command_line_dispatcher.rb +5 -7
- data/lib/moonshot/commands/build.rb +6 -0
- data/lib/moonshot/commands/console.rb +2 -0
- data/lib/moonshot/commands/create.rb +14 -2
- data/lib/moonshot/commands/delete.rb +9 -0
- data/lib/moonshot/commands/deploy.rb +4 -8
- data/lib/moonshot/commands/doctor.rb +2 -0
- data/lib/moonshot/commands/generate_template.rb +46 -0
- data/lib/moonshot/commands/interactive_command.rb +15 -0
- data/lib/moonshot/commands/list.rb +2 -0
- data/lib/moonshot/commands/new.rb +5 -2
- data/lib/moonshot/commands/parameter_arguments.rb +5 -4
- data/lib/moonshot/commands/parent_stack_option.rb +2 -0
- data/lib/moonshot/commands/push.rb +2 -0
- data/lib/moonshot/commands/show_all_events_option.rb +2 -0
- data/lib/moonshot/commands/ssh.rb +4 -0
- data/lib/moonshot/commands/status.rb +2 -0
- data/lib/moonshot/commands/update.rb +7 -1
- data/lib/moonshot/commands/version.rb +2 -0
- data/lib/moonshot/controller.rb +28 -13
- data/lib/moonshot/controller_config.rb +12 -27
- data/lib/moonshot/creds_helper.rb +2 -0
- data/lib/moonshot/deployment_mechanism/code_deploy.rb +44 -37
- data/lib/moonshot/doctor_helper.rb +14 -15
- data/lib/moonshot/dynamic_template.rb +76 -0
- data/lib/moonshot/interactive_logger_proxy.rb +4 -4
- data/lib/moonshot/json_stack_template.rb +3 -0
- data/lib/moonshot/parameter_collection.rb +3 -0
- data/lib/moonshot/parent_stack_parameter_loader.rb +7 -3
- data/lib/moonshot/resources.rb +2 -0
- data/lib/moonshot/resources_helper.rb +5 -1
- data/lib/moonshot/shell.rb +8 -8
- data/lib/moonshot/ssh_command.rb +2 -0
- data/lib/moonshot/ssh_command_builder.rb +3 -1
- data/lib/moonshot/ssh_config.rb +3 -2
- data/lib/moonshot/ssh_fork_executor.rb +2 -0
- data/lib/moonshot/ssh_target_selector.rb +3 -1
- data/lib/moonshot/stack.rb +50 -46
- data/lib/moonshot/stack_asg_printer.rb +14 -12
- data/lib/moonshot/stack_config.rb +3 -2
- data/lib/moonshot/stack_events_poller.rb +3 -1
- data/lib/moonshot/stack_list_printer.rb +2 -0
- data/lib/moonshot/stack_lister.rb +6 -2
- data/lib/moonshot/stack_output_printer.rb +2 -0
- data/lib/moonshot/stack_parameter.rb +5 -9
- data/lib/moonshot/stack_parameter_printer.rb +3 -1
- data/lib/moonshot/stack_template.rb +2 -0
- data/lib/moonshot/task.rb +3 -0
- data/lib/moonshot/tools/asg_rollout/asg.rb +19 -21
- data/lib/moonshot/tools/asg_rollout/asg_instance.rb +2 -0
- data/lib/moonshot/tools/asg_rollout/hook_exec_environment.rb +2 -0
- data/lib/moonshot/tools/asg_rollout/instance_health.rb +2 -0
- data/lib/moonshot/tools/asg_rollout.rb +16 -14
- data/lib/moonshot/tools/asg_rollout_config.rb +2 -0
- data/lib/moonshot/unicode_table.rb +1 -1
- data/lib/moonshot/yaml_stack_template.rb +2 -0
- data/lib/moonshot.rb +13 -1
- data/lib/plugins/backup.rb +24 -30
- data/lib/plugins/code_deploy_setup.rb +4 -2
- data/lib/plugins/dynamic_template.rb +36 -0
- data/lib/plugins/encrypted_parameters/kms_key.rb +2 -0
- data/lib/plugins/encrypted_parameters/parameter_encrypter.rb +2 -0
- data/lib/plugins/encrypted_parameters.rb +3 -1
- 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
|
data/lib/moonshot/task.rb
CHANGED
@@ -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
|
-
.
|
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
|
-
|
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,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
|
-
|
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
|
-
|
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:
|
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
|
data/lib/moonshot.rb
CHANGED
@@ -1,5 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'English'
|
2
|
-
|
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
|
data/lib/plugins/backup.rb
CHANGED
@@ -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 ||= '
|
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 = [
|
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
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
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),
|
127
|
-
|
128
|
-
|
129
|
-
|
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),
|
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
|
-
|
202
|
-
@target_bucket
|
199
|
+
return @target_bucket if @target_bucket
|
203
200
|
# single bucket for all accounts
|
204
|
-
|
205
|
-
@bucket
|
201
|
+
return @bucket if @bucket
|
206
202
|
# calculating bucket based on account name
|
207
|
-
|
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:
|
38
|
+
client = s3_client(region:)
|
37
39
|
name = bucket_name(region)
|
38
40
|
bucket = Aws::S3::Bucket.new(
|
39
41
|
name,
|
40
|
-
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
|
# 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
|
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)
|