moonshot 2.0.0.beta6 → 3.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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 +24 -34
- 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 +16 -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/tag_arguments.rb +20 -0
- data/lib/moonshot/commands/update.rb +8 -1
- data/lib/moonshot/commands/version.rb +2 -0
- data/lib/moonshot/controller.rb +28 -13
- data/lib/moonshot/controller_config.rb +13 -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 +73 -55
- 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 +22 -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 +5 -3
- 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 +26 -5
- data/lib/plugins/encrypted_parameters/parameter_encrypter.rb +2 -0
- data/lib/plugins/encrypted_parameters.rb +6 -2
- metadata +189 -51
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Moonshot
|
4
|
+
module Commands
|
5
|
+
class GenerateTemplate < Moonshot::Command
|
6
|
+
self.usage = 'generate-template [options]'
|
7
|
+
self.description = 'Processes an ERB formatted CloudFormation template.'
|
8
|
+
|
9
|
+
def initialize(*)
|
10
|
+
super
|
11
|
+
@parameters = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def parser
|
15
|
+
parser = super
|
16
|
+
|
17
|
+
parser.on('--source SOURCE_FILE', 'The ERB template file.') do |v|
|
18
|
+
@source = v
|
19
|
+
end
|
20
|
+
|
21
|
+
parser.on('--parameter KEY=VALUE', '-PKEY=VALUE',
|
22
|
+
'Specify Stack Parameter on the command line') do |v|
|
23
|
+
data = v.split('=', 2)
|
24
|
+
unless data.size == 2
|
25
|
+
raise "Invalid parameter format '#{v}',"\
|
26
|
+
'expected KEY=VALUE (e.g. MyTemplateParameter=12)'
|
27
|
+
end
|
28
|
+
|
29
|
+
@parameters[data[0]] = data[1]
|
30
|
+
end
|
31
|
+
|
32
|
+
parser.on('--destination DESTINATION_FILE', 'Destionation file.') do |v|
|
33
|
+
@destination = v
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def execute
|
38
|
+
::Moonshot::DynamicTemplate.new(
|
39
|
+
source: @source,
|
40
|
+
parameters: @parameters,
|
41
|
+
destination: @destination
|
42
|
+
).process
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Moonshot
|
4
|
+
module Commands
|
5
|
+
module InteractiveCommand
|
6
|
+
def parser
|
7
|
+
parser = super
|
8
|
+
|
9
|
+
parser.on('--[no-]interactive', TrueClass, 'Use interactive prompts.') do |v|
|
10
|
+
Moonshot.config.interactive = v
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Moonshot
|
2
4
|
module Commands
|
3
5
|
class New < Moonshot::Command
|
@@ -25,6 +27,7 @@ module Moonshot
|
|
25
27
|
def create_project_dir
|
26
28
|
raise "Directory '#{@application_name}' already exists!" \
|
27
29
|
if Dir.exist?(project_path)
|
30
|
+
|
28
31
|
Dir.mkdir(project_path)
|
29
32
|
end
|
30
33
|
|
@@ -49,7 +52,7 @@ Moonshot.config do |m|
|
|
49
52
|
m.build_mechanism = Script.new('bin/build.sh')
|
50
53
|
m.deployment_mechanism = CodeDeploy.new(asg: 'AutoScalingGroup')
|
51
54
|
end
|
52
|
-
EOF
|
55
|
+
EOF
|
53
56
|
end
|
54
57
|
|
55
58
|
def print_success_message
|
@@ -69,7 +72,7 @@ You will also need to ensure your Amazon account is configured for
|
|
69
72
|
CodeDeploy by creating a role that allows deployments.
|
70
73
|
|
71
74
|
See: http://moonshot.readthedocs.io/en/latest/mechanisms/deployment/
|
72
|
-
EOF
|
75
|
+
EOF
|
73
76
|
end
|
74
77
|
end
|
75
78
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Layout/LineLength
|
2
4
|
module Moonshot
|
3
5
|
module Commands
|
4
6
|
module ParameterArguments
|
@@ -15,9 +17,7 @@ module Moonshot
|
|
15
17
|
|
16
18
|
parser.on('--parameter KEY=VALUE', '-PKEY=VALUE', 'Specify Stack Parameter on the command line') do |v|
|
17
19
|
data = v.split('=', 2)
|
18
|
-
unless data.size == 2
|
19
|
-
raise "Invalid parameter format '#{v}', expected KEY=VALUE (e.g. MyStackParameter=12)"
|
20
|
-
end
|
20
|
+
raise "Invalid parameter format '#{v}', expected KEY=VALUE (e.g. MyStackParameter=12)" unless data.size == 2
|
21
21
|
|
22
22
|
Moonshot.config.parameter_overrides[data[0]] = data[1]
|
23
23
|
end
|
@@ -25,3 +25,4 @@ module Moonshot
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
28
|
+
# rubocop:enable Layout/LineLength
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Moonshot
|
4
|
+
module Commands
|
5
|
+
module TagArguments
|
6
|
+
def parser
|
7
|
+
parser = super
|
8
|
+
|
9
|
+
parser.on('--tag KEY=VALUE', '-TKEY=VALUE', 'Specify Stack Tag on the command line') do |v|
|
10
|
+
data = v.split('=', 2)
|
11
|
+
unless data.size == 2
|
12
|
+
raise "Invalid tag format '#{v}', expected KEY=VALUE (e.g. MyStackTag=12)"
|
13
|
+
end
|
14
|
+
|
15
|
+
Moonshot.config.extra_tags << { key: data[0], value: data[1] }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Moonshot
|
2
4
|
module Commands
|
3
5
|
class Update < Moonshot::Command
|
4
6
|
include ParameterArguments
|
7
|
+
include TagArguments
|
5
8
|
include ShowAllEventsOption
|
6
9
|
include ParentStackOption
|
7
10
|
|
@@ -11,7 +14,7 @@ module Moonshot
|
|
11
14
|
def parser
|
12
15
|
parser = super
|
13
16
|
|
14
|
-
parser.on('--dry-run', TrueClass, 'Show the changes that would be applied, but do not execute them') do |v|
|
17
|
+
parser.on('--dry-run', TrueClass, 'Show the changes that would be applied, but do not execute them') do |v|
|
15
18
|
@dry_run = v
|
16
19
|
end
|
17
20
|
|
@@ -22,6 +25,10 @@ module Moonshot
|
|
22
25
|
parser.on('--refresh-parameters', TrueClass, 'Update parameters from parent stacks') do |v|
|
23
26
|
@refresh_parameters = v
|
24
27
|
end
|
28
|
+
|
29
|
+
parser.on('--template-file=FILE', 'Override the path to the CloudFormation template.') do |v|
|
30
|
+
Moonshot.config.template_file = v
|
31
|
+
end
|
25
32
|
end
|
26
33
|
|
27
34
|
def execute
|
data/lib/moonshot/controller.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Moonshot
|
2
4
|
# The Controller coordinates and performs all Moonshot actions.
|
3
|
-
class Controller # rubocop:disable ClassLength
|
5
|
+
class Controller # rubocop:disable Metrics/ClassLength
|
4
6
|
attr_accessor :config
|
5
7
|
|
6
8
|
def initialize(config)
|
@@ -11,7 +13,8 @@ module Moonshot
|
|
11
13
|
Moonshot::StackLister.new(@config.app_name).list
|
12
14
|
end
|
13
15
|
|
14
|
-
def create # rubocop:disable AbcSize
|
16
|
+
def create # rubocop:disable Metrics/AbcSize
|
17
|
+
run_plugins(:setup_create)
|
15
18
|
# Scan the template for all required parameters and configure
|
16
19
|
# the ParameterCollection.
|
17
20
|
@config.parameters = ParameterCollection.from_template(stack.template)
|
@@ -34,7 +37,7 @@ module Moonshot
|
|
34
37
|
|
35
38
|
# Interview the user for missing parameters, using the
|
36
39
|
# appropriate prompts.
|
37
|
-
@config.parameters.
|
40
|
+
@config.parameters.hash.each_value do |sp|
|
38
41
|
next if sp.set?
|
39
42
|
|
40
43
|
parameter_source = @config.parameter_sources.fetch(sp.name,
|
@@ -50,12 +53,12 @@ module Moonshot
|
|
50
53
|
# Fail if any parameters are still missing without defaults.
|
51
54
|
missing_parameters = @config.parameters.missing_for_create
|
52
55
|
unless missing_parameters.empty?
|
53
|
-
raise "The following parameters were not provided: #{missing_parameters.map(&:name).join(', ')}"
|
56
|
+
raise "The following parameters were not provided: #{missing_parameters.map(&:name).join(', ')}"
|
54
57
|
end
|
55
58
|
|
56
59
|
run_hook(:deploy, :pre_create)
|
57
60
|
stack_ok = stack.create
|
58
|
-
if stack_ok # rubocop:disable GuardClause
|
61
|
+
if stack_ok # rubocop:disable Style/GuardClause
|
59
62
|
run_hook(:deploy, :post_create)
|
60
63
|
run_plugins(:post_create)
|
61
64
|
else
|
@@ -63,7 +66,8 @@ module Moonshot
|
|
63
66
|
end
|
64
67
|
end
|
65
68
|
|
66
|
-
def update(dry_run:, force:, refresh_parameters:) # rubocop:disable AbcSize
|
69
|
+
def update(dry_run:, force:, refresh_parameters:) # rubocop:disable Metrics/AbcSize
|
70
|
+
run_plugins(:setup_update)
|
67
71
|
# Scan the template for all required parameters and configure
|
68
72
|
# the ParameterCollection.
|
69
73
|
@config.parameters = ParameterCollection.from_template(stack.template)
|
@@ -106,16 +110,17 @@ module Moonshot
|
|
106
110
|
# Fail if any parameters are still missing without defaults.
|
107
111
|
missing_parameters = @config.parameters.missing_for_update
|
108
112
|
unless missing_parameters.empty?
|
109
|
-
raise "The following parameters were not provided: #{missing_parameters.map(&:name).join(', ')}"
|
113
|
+
raise "The following parameters were not provided: #{missing_parameters.map(&:name).join(', ')}"
|
110
114
|
end
|
111
115
|
|
112
116
|
run_hook(:deploy, :pre_update)
|
113
|
-
stack.update(dry_run
|
117
|
+
stack.update(dry_run:, force:)
|
114
118
|
run_hook(:deploy, :post_update)
|
115
119
|
run_plugins(:post_update)
|
116
120
|
end
|
117
121
|
|
118
122
|
def status
|
123
|
+
run_plugins(:setup_status)
|
119
124
|
run_plugins(:pre_status)
|
120
125
|
run_hook(:deploy, :status)
|
121
126
|
stack.status
|
@@ -129,6 +134,7 @@ module Moonshot
|
|
129
134
|
end
|
130
135
|
|
131
136
|
def build_version(version_name)
|
137
|
+
run_plugins(:setup_build)
|
132
138
|
run_plugins(:pre_build)
|
133
139
|
run_hook(:build, :pre_build, version_name)
|
134
140
|
run_hook(:build, :build, version_name)
|
@@ -138,12 +144,14 @@ module Moonshot
|
|
138
144
|
end
|
139
145
|
|
140
146
|
def deploy_version(version_name)
|
147
|
+
run_plugins(:setup_deploy)
|
141
148
|
run_plugins(:pre_deploy)
|
142
149
|
run_hook(:deploy, :deploy, @config.artifact_repository, version_name)
|
143
150
|
run_plugins(:post_deploy)
|
144
151
|
end
|
145
152
|
|
146
153
|
def delete
|
154
|
+
run_plugins(:setup_delete)
|
147
155
|
# Populate the current values of parameters, for use by plugins.
|
148
156
|
@config.parameters = ParameterCollection.from_template(stack.template)
|
149
157
|
stack.parameters.each do |key, value|
|
@@ -153,7 +161,7 @@ module Moonshot
|
|
153
161
|
run_plugins(:pre_delete)
|
154
162
|
run_hook(:deploy, :pre_delete)
|
155
163
|
stack_ok = stack.delete
|
156
|
-
if stack_ok # rubocop:disable GuardClause
|
164
|
+
if stack_ok # rubocop:disable Style/GuardClause
|
157
165
|
run_hook(:deploy, :post_delete)
|
158
166
|
run_plugins(:post_delete)
|
159
167
|
else
|
@@ -176,7 +184,8 @@ module Moonshot
|
|
176
184
|
def ssh
|
177
185
|
run_plugins(:pre_ssh)
|
178
186
|
@config.ssh_instance ||= SSHTargetSelector.new(
|
179
|
-
stack, asg_name: @config.ssh_auto_scaling_group_name
|
187
|
+
stack, asg_name: @config.ssh_auto_scaling_group_name
|
188
|
+
).choose!
|
180
189
|
cb = SSHCommandBuilder.new(@config.ssh_config, @config.ssh_instance)
|
181
190
|
result = cb.build(@config.ssh_command)
|
182
191
|
|
@@ -192,14 +201,14 @@ module Moonshot
|
|
192
201
|
|
193
202
|
def resources
|
194
203
|
@resources ||=
|
195
|
-
Resources.new(stack
|
204
|
+
Resources.new(stack:, ilog: @config.interactive_logger, controller: self)
|
196
205
|
end
|
197
206
|
|
198
207
|
def run_hook(type, name, *args)
|
199
208
|
mech = get_mechanism(type)
|
200
209
|
name = name.to_s << '_hook'
|
201
210
|
|
202
|
-
return unless mech
|
211
|
+
return unless mech.respond_to?(name)
|
203
212
|
|
204
213
|
mech.resources = resources
|
205
214
|
mech.send(name, *args)
|
@@ -209,7 +218,13 @@ module Moonshot
|
|
209
218
|
results = {}
|
210
219
|
@config.plugins.each do |plugin|
|
211
220
|
next unless plugin.respond_to?(type)
|
212
|
-
|
221
|
+
|
222
|
+
results[plugin] =
|
223
|
+
if type =~ /^setup_/
|
224
|
+
plugin.send(type)
|
225
|
+
else
|
226
|
+
plugin.send(type, resources)
|
227
|
+
end
|
213
228
|
end
|
214
229
|
|
215
230
|
results
|
@@ -1,32 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Moonshot
|
2
4
|
# Holds configuration for Moonshot::Controller
|
3
5
|
class ControllerConfig
|
4
6
|
attr_reader :account_alias
|
5
7
|
|
6
|
-
attr_accessor :additional_tag
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
attr_accessor :deployment_mechanism
|
13
|
-
attr_accessor :dev_build_name_proc
|
14
|
-
attr_accessor :environment_name
|
15
|
-
attr_accessor :interactive
|
16
|
-
attr_accessor :interactive_logger
|
17
|
-
attr_accessor :parameter_overrides
|
18
|
-
attr_accessor :parameters
|
19
|
-
attr_accessor :parent_stacks
|
20
|
-
attr_accessor :default_parameter_source
|
21
|
-
attr_accessor :parameter_sources
|
22
|
-
attr_accessor :plugins
|
23
|
-
attr_accessor :project_root
|
24
|
-
attr_accessor :show_all_stack_events
|
25
|
-
attr_accessor :ssh_auto_scaling_group_name
|
26
|
-
attr_accessor :ssh_command
|
27
|
-
attr_accessor :ssh_config
|
28
|
-
attr_accessor :ssh_instance
|
29
|
-
attr_accessor :template_s3_bucket
|
8
|
+
attr_accessor :additional_tag, :answer_file, :app_name, :artifact_repository, :build_mechanism,
|
9
|
+
:changeset_wait_time, :deployment_mechanism, :dev_build_name_proc, :environment_name,
|
10
|
+
:interactive, :interactive_logger, :parameter_overrides, :parameters, :parent_stacks,
|
11
|
+
:default_parameter_source, :parameter_sources, :plugins, :project_root,
|
12
|
+
:show_all_stack_events, :ssh_auto_scaling_group_name, :ssh_command, :ssh_config,
|
13
|
+
:ssh_instance, :template_file, :template_s3_bucket, :extra_tags
|
30
14
|
|
31
15
|
def initialize
|
32
16
|
@default_parameter_source = AskUserSource.new
|
@@ -42,6 +26,7 @@ module Moonshot
|
|
42
26
|
@project_root = Dir.pwd
|
43
27
|
@show_all_stack_events = false
|
44
28
|
@ssh_config = SSHConfig.new
|
29
|
+
@extra_tags = []
|
45
30
|
|
46
31
|
@dev_build_name_proc = lambda do |c|
|
47
32
|
['dev', c.app_name, c.environment_name, Time.now.to_i].join('/')
|
@@ -60,9 +45,10 @@ module Moonshot
|
|
60
45
|
def update_for_account!
|
61
46
|
# Evaluated any account-specific configuration.
|
62
47
|
@account_alias = Moonshot::AccountContext.get
|
63
|
-
|
64
|
-
|
65
|
-
|
48
|
+
return unless @account_alias
|
49
|
+
return unless @per_account_config.key?(@account_alias)
|
50
|
+
|
51
|
+
@per_account_config[@account_alias].call(self)
|
66
52
|
end
|
67
53
|
end
|
68
54
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'colorize'
|
2
4
|
|
3
5
|
# This mechanism is used to deploy software to an auto-scaling group within
|
@@ -8,12 +10,12 @@ require 'colorize'
|
|
8
10
|
# self.artifact_repository = S3Bucket.new('foobucket')
|
9
11
|
# self.deployment_mechanism = CodeDeploy.new(asg: 'AutoScalingGroup')
|
10
12
|
# end
|
11
|
-
class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
|
13
|
+
class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable Metrics/ClassLength
|
12
14
|
include Moonshot::ResourcesHelper
|
13
15
|
include Moonshot::CredsHelper
|
14
16
|
include Moonshot::DoctorHelper
|
15
17
|
|
16
|
-
DEFAULT_ROLE_NAME = 'CodeDeployRole'
|
18
|
+
DEFAULT_ROLE_NAME = 'CodeDeployRole'
|
17
19
|
|
18
20
|
# @param asg [Array, String]
|
19
21
|
# The logical name of the AutoScalingGroup to create and manage a Deployment
|
@@ -37,12 +39,13 @@ class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
|
|
37
39
|
# CodeDeployDefault.OneAtATime.
|
38
40
|
# rubocop:disable Metrics/ParameterLists
|
39
41
|
def initialize(
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
asg: [],
|
43
|
+
optional_asg: [],
|
44
|
+
role: DEFAULT_ROLE_NAME,
|
45
|
+
app_name: nil,
|
46
|
+
group_name: nil,
|
47
|
+
config_name: 'CodeDeployDefault.OneAtATime'
|
48
|
+
)
|
46
49
|
@asg_logical_ids = Array(asg)
|
47
50
|
@optional_asg_logical_ids = Array(optional_asg)
|
48
51
|
@app_name = app_name
|
@@ -51,6 +54,7 @@ class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
|
|
51
54
|
@codedeploy_config = config_name
|
52
55
|
@ignore_app_stop_failures = false
|
53
56
|
end
|
57
|
+
# rubocop:enable Metrics/ParameterLists
|
54
58
|
|
55
59
|
def post_create_hook
|
56
60
|
create_application_if_needed
|
@@ -62,7 +66,7 @@ class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
|
|
62
66
|
def post_update_hook
|
63
67
|
post_create_hook
|
64
68
|
|
65
|
-
unless deployment_group_ok? # rubocop:disable GuardClause
|
69
|
+
unless deployment_group_ok? # rubocop:disable Style/GuardClause
|
66
70
|
delete_deployment_group
|
67
71
|
create_deployment_group_if_needed
|
68
72
|
end
|
@@ -101,7 +105,7 @@ class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
|
|
101
105
|
end
|
102
106
|
|
103
107
|
def deploy_cli_hook(parser)
|
104
|
-
parser.on('--ignore-app-stop-failures', TrueClass, 'Continue deployment on ApplicationStop failures') do |v|
|
108
|
+
parser.on('--ignore-app-stop-failures', TrueClass, 'Continue deployment on ApplicationStop failures') do |v|
|
105
109
|
puts "ignore = #{v}"
|
106
110
|
@ignore_app_stop_failures = v
|
107
111
|
end
|
@@ -178,27 +182,24 @@ class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
|
|
178
182
|
autoscaling_groups = []
|
179
183
|
@asg_logical_ids.each do |asg_logical_id|
|
180
184
|
asg_name = stack.physical_id_for(asg_logical_id)
|
181
|
-
unless asg_name
|
182
|
-
raise "Could not find #{asg_logical_id} resource in Stack."
|
183
|
-
end
|
185
|
+
raise "Could not find #{asg_logical_id} resource in Stack." unless asg_name
|
184
186
|
|
185
187
|
groups = as_client.describe_auto_scaling_groups(
|
186
|
-
auto_scaling_group_names: [asg_name]
|
187
|
-
|
188
|
-
|
189
|
-
|
188
|
+
auto_scaling_group_names: [asg_name]
|
189
|
+
)
|
190
|
+
|
191
|
+
raise "Could not find ASG #{asg_name}." if groups.auto_scaling_groups.empty?
|
190
192
|
|
191
193
|
autoscaling_groups.push(groups.auto_scaling_groups.first)
|
192
194
|
end
|
193
195
|
@optional_asg_logical_ids.each do |asg_logical_id|
|
194
196
|
asg_name = stack.physical_id_for(asg_logical_id)
|
195
197
|
next unless asg_name
|
198
|
+
|
196
199
|
groups = as_client.describe_auto_scaling_groups(
|
197
200
|
auto_scaling_group_names: [asg_name]
|
198
201
|
)
|
199
|
-
unless groups.auto_scaling_groups.empty?
|
200
|
-
autoscaling_groups.push(groups.auto_scaling_groups.first)
|
201
|
-
end
|
202
|
+
autoscaling_groups.push(groups.auto_scaling_groups.first) unless groups.auto_scaling_groups.empty?
|
202
203
|
end
|
203
204
|
autoscaling_groups
|
204
205
|
end
|
@@ -220,13 +221,16 @@ class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
|
|
220
221
|
|
221
222
|
def deployment_group
|
222
223
|
cd_client.get_deployment_group(
|
223
|
-
application_name: app_name,
|
224
|
-
|
224
|
+
application_name: app_name,
|
225
|
+
deployment_group_name: group_name
|
226
|
+
).deployment_group_info
|
225
227
|
end
|
226
228
|
|
227
229
|
def deployment_group_exists?
|
228
230
|
cd_client.get_deployment_group(
|
229
|
-
application_name: app_name,
|
231
|
+
application_name: app_name,
|
232
|
+
deployment_group_name: group_name
|
233
|
+
)
|
230
234
|
true
|
231
235
|
rescue Aws::CodeDeploy::Errors::ApplicationDoesNotExistException,
|
232
236
|
Aws::CodeDeploy::Errors::DeploymentGroupDoesNotExistException
|
@@ -235,13 +239,13 @@ class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
|
|
235
239
|
|
236
240
|
def deployment_group_ok?
|
237
241
|
return false unless deployment_group_exists?
|
242
|
+
|
238
243
|
asgs = deployment_group.auto_scaling_groups
|
239
244
|
return false unless asgs
|
240
245
|
return false unless asgs.count == auto_scaling_groups.count
|
246
|
+
|
241
247
|
asgs.each do |asg|
|
242
|
-
if (auto_scaling_groups.find_index { |a| a.auto_scaling_group_name == asg.name }).nil?
|
243
|
-
return false
|
244
|
-
end
|
248
|
+
return false if (auto_scaling_groups.find_index { |a| a.auto_scaling_group_name == asg.name }).nil?
|
245
249
|
end
|
246
250
|
true
|
247
251
|
end
|
@@ -284,7 +288,8 @@ class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
|
|
284
288
|
ilog.start "Deleting #{pretty_deploy_group}." do |s|
|
285
289
|
cd_client.delete_deployment_group(
|
286
290
|
application_name: app_name,
|
287
|
-
deployment_group_name: group_name
|
291
|
+
deployment_group_name: group_name
|
292
|
+
)
|
288
293
|
s.success
|
289
294
|
end
|
290
295
|
end
|
@@ -294,7 +299,8 @@ class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
|
|
294
299
|
application_name: app_name,
|
295
300
|
deployment_group_name: group_name,
|
296
301
|
service_role_arn: role.arn,
|
297
|
-
auto_scaling_groups: asg_names
|
302
|
+
auto_scaling_groups: asg_names
|
303
|
+
)
|
298
304
|
end
|
299
305
|
|
300
306
|
def wait_for_asg_capacity
|
@@ -306,10 +312,11 @@ class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
|
|
306
312
|
count = asg.instances.count { |i| i.lifecycle_state == 'InService' }
|
307
313
|
if asg.desired_capacity == count
|
308
314
|
asgs_at_capacity += 1
|
309
|
-
s.continue "#{asg.auto_scaling_group_name} DesiredCapacity is #{asg.desired_capacity}, currently #{count} instance(s) are InService." # rubocop:disable LineLength
|
315
|
+
s.continue "#{asg.auto_scaling_group_name} DesiredCapacity is #{asg.desired_capacity}, currently #{count} instance(s) are InService." # rubocop:disable Layout/LineLength
|
310
316
|
end
|
311
317
|
end
|
312
318
|
break if asgs.count == asgs_at_capacity
|
319
|
+
|
313
320
|
sleep 5
|
314
321
|
end
|
315
322
|
|
@@ -327,7 +334,7 @@ class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
|
|
327
334
|
|
328
335
|
case status
|
329
336
|
when 'Created', 'Queued', 'InProgress'
|
330
|
-
step.continue "Waiting for Deployment #{id.blue} to complete, current status is '#{status}'."
|
337
|
+
step.continue "Waiting for Deployment #{id.blue} to complete, current status is '#{status}'."
|
331
338
|
when 'Succeeded'
|
332
339
|
step.success "Deployment #{id.blue} completed successfully!"
|
333
340
|
break
|
@@ -342,10 +349,10 @@ class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
|
|
342
349
|
end
|
343
350
|
|
344
351
|
def handle_deployment_failure(deployment_id)
|
345
|
-
instances = cd_client.list_deployment_instances(deployment_id:
|
352
|
+
instances = cd_client.list_deployment_instances(deployment_id:)
|
346
353
|
.instances_list.map do |instance_id|
|
347
|
-
cd_client.get_deployment_instance(deployment_id
|
348
|
-
instance_id:
|
354
|
+
cd_client.get_deployment_instance(deployment_id:,
|
355
|
+
instance_id:)
|
349
356
|
end
|
350
357
|
|
351
358
|
instances.map(&:instance_summary).each do |inst_summary|
|
@@ -373,7 +380,7 @@ class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
|
|
373
380
|
when Moonshot::ArtifactRepository::S3Bucket
|
374
381
|
s3_revision_for(artifact_repo, version_name)
|
375
382
|
when NilClass
|
376
|
-
raise 'Must specify an ArtifactRepository with CodeDeploy. Take a look at the S3Bucket example.'
|
383
|
+
raise 'Must specify an ArtifactRepository with CodeDeploy. Take a look at the S3Bucket example.'
|
377
384
|
else
|
378
385
|
raise "Cannot use #{artifact_repo.class} to deploy with CodeDeploy."
|
379
386
|
end
|
@@ -404,7 +411,7 @@ class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
|
|
404
411
|
def doctor_check_code_deploy_role
|
405
412
|
role
|
406
413
|
success("#{@codedeploy_role} exists.")
|
407
|
-
rescue => e
|
414
|
+
rescue StandardError => e
|
408
415
|
help = <<-EOF
|
409
416
|
Error: #{e.message}
|
410
417
|
|
@@ -417,9 +424,9 @@ http://docs.aws.amazon.com/codedeploy/latest/userguide/how-to-create-service-rol
|
|
417
424
|
def doctor_check_auto_scaling_resource_defined
|
418
425
|
@asg_logical_ids.each do |asg_logical_id|
|
419
426
|
if stack.template.resource_names.include?(asg_logical_id)
|
420
|
-
success("Resource '#{asg_logical_id}' exists in the CloudFormation template.")
|
427
|
+
success("Resource '#{asg_logical_id}' exists in the CloudFormation template.")
|
421
428
|
else
|
422
|
-
critical("Resource '#{asg_logical_id}' does not exist in the CloudFormation template!")
|
429
|
+
critical("Resource '#{asg_logical_id}' does not exist in the CloudFormation template!")
|
423
430
|
end
|
424
431
|
end
|
425
432
|
end
|