aws-codedeploy-agent 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/aws-codedeploy-agent.gemspec +5 -5
- data/certs/host-agent-deployment-signer-ca-chain.pem +30 -0
- data/conf/codedeployagent.yml +0 -1
- data/lib/instance_agent.rb +1 -13
- data/lib/instance_agent/agent/base.rb +38 -12
- data/lib/instance_agent/agent/plugin.rb +21 -0
- data/lib/instance_agent/config.rb +2 -1
- data/lib/instance_agent/platform/linux_util.rb +4 -0
- data/lib/instance_agent/plugins/codedeploy/application_specification/ace_info.rb +133 -0
- data/lib/instance_agent/plugins/codedeploy/application_specification/acl_info.rb +163 -0
- data/lib/instance_agent/plugins/codedeploy/application_specification/application_specification.rb +143 -0
- data/lib/instance_agent/plugins/codedeploy/application_specification/context_info.rb +23 -0
- data/lib/instance_agent/plugins/codedeploy/application_specification/file_info.rb +23 -0
- data/lib/instance_agent/plugins/codedeploy/application_specification/linux_permission_info.rb +121 -0
- data/lib/instance_agent/plugins/codedeploy/application_specification/mode_info.rb +66 -0
- data/lib/instance_agent/plugins/codedeploy/application_specification/range_info.rb +134 -0
- data/lib/instance_agent/plugins/codedeploy/application_specification/script_info.rb +27 -0
- data/lib/instance_agent/plugins/codedeploy/codedeploy_control.rb +100 -0
- data/lib/instance_agent/plugins/codedeploy/command_executor.rb +359 -0
- data/lib/instance_agent/plugins/codedeploy/command_poller.rb +178 -0
- data/lib/instance_agent/plugins/codedeploy/deployment_specification.rb +161 -0
- data/lib/instance_agent/plugins/codedeploy/hook_executor.rb +226 -0
- data/lib/instance_agent/plugins/codedeploy/install_instruction.rb +389 -0
- data/lib/instance_agent/plugins/codedeploy/installer.rb +147 -0
- data/lib/instance_agent/plugins/codedeploy/onpremise_config.rb +42 -0
- data/lib/instance_agent/plugins/codedeploy/register_plugin.rb +17 -0
- data/lib/instance_agent/runner/child.rb +20 -5
- data/lib/instance_agent/runner/master.rb +2 -15
- data/lib/instance_metadata.rb +2 -2
- data/test/certificate_helper.rb +1 -1
- data/test/helpers/instance_agent_helper.rb +1 -0
- data/test/instance_agent/agent/base_test.rb +16 -3
- data/test/instance_agent/config_test.rb +2 -1
- data/test/instance_agent/plugins/codedeploy/application_specification_test.rb +1713 -0
- data/test/instance_agent/{codedeploy_plugin → plugins/codedeploy}/codedeploy_control_test.rb +1 -1
- data/test/instance_agent/{codedeploy_plugin → plugins/codedeploy}/command_executor_test.rb +32 -9
- data/test/instance_agent/{codedeploy_plugin → plugins/codedeploy}/command_poller_test.rb +13 -14
- data/test/instance_agent/{codedeploy_plugin → plugins/codedeploy}/deployment_specification_test.rb +98 -25
- data/test/instance_agent/{codedeploy_plugin → plugins/codedeploy}/hook_executor_test.rb +83 -15
- data/test/instance_agent/plugins/codedeploy/install_instruction_test.rb +568 -0
- data/test/instance_agent/{codedeploy_plugin → plugins/codedeploy}/installer_test.rb +12 -9
- data/test/instance_agent/plugins/codedeploy/onpremise_config_test.rb +72 -0
- data/test/instance_agent/runner/child_test.rb +1 -1
- data/vendor/gems/.codedeploy-commands-1.0.0.created.rid +1 -1
- data/vendor/gems/codedeploy-commands/lib/aws/plugins/deploy_control_endpoint.rb +4 -0
- data/vendor/gems/jmespath-1.0.1/lib/jmespath.rb +41 -0
- data/vendor/gems/jmespath-1.0.1/lib/jmespath/caching_parser.rb +30 -0
- data/vendor/gems/jmespath-1.0.1/lib/jmespath/errors.rb +17 -0
- data/vendor/gems/jmespath-1.0.1/lib/jmespath/expr_node.rb +15 -0
- data/vendor/gems/jmespath-1.0.1/lib/jmespath/lexer.rb +116 -0
- data/vendor/gems/jmespath-1.0.1/lib/jmespath/parser.rb +347 -0
- data/vendor/gems/jmespath-1.0.1/lib/jmespath/runtime.rb +71 -0
- data/vendor/gems/jmespath-1.0.1/lib/jmespath/token.rb +41 -0
- data/vendor/gems/jmespath-1.0.1/lib/jmespath/token_stream.rb +60 -0
- data/vendor/gems/jmespath-1.0.1/lib/jmespath/tree_interpreter.rb +523 -0
- data/vendor/gems/jmespath-1.0.1/lib/jmespath/version.rb +3 -0
- data/vendor/gems/process_manager/lib/process_manager/master.rb +16 -5
- data/vendor/specifications/{aws-sdk-core-2.0.5.gemspec → aws-sdk-core-2.0.42.gemspec} +9 -11
- data/vendor/specifications/builder-3.2.2.gemspec +1 -1
- data/vendor/specifications/codedeploy-commands-1.0.0.gemspec +7 -6
- data/vendor/specifications/gli-2.5.6.gemspec +1 -1
- data/vendor/specifications/jmespath-1.0.1.gemspec +29 -0
- data/vendor/specifications/little-plugger-1.1.3.gemspec +1 -1
- data/vendor/specifications/logging-1.8.1.gemspec +1 -1
- data/vendor/specifications/multi_json-1.7.7.gemspec +1 -1
- data/vendor/specifications/multi_json-1.8.4.gemspec +1 -1
- data/vendor/specifications/multi_xml-0.5.5.gemspec +1 -1
- data/vendor/specifications/process_manager-0.0.13.gemspec +1 -1
- data/vendor/specifications/simple_pid-0.2.1.gemspec +1 -1
- metadata +76 -63
- data/lib/instance_agent/codedeploy_plugin/application_specification/ace_info.rb +0 -133
- data/lib/instance_agent/codedeploy_plugin/application_specification/acl_info.rb +0 -163
- data/lib/instance_agent/codedeploy_plugin/application_specification/application_specification.rb +0 -142
- data/lib/instance_agent/codedeploy_plugin/application_specification/context_info.rb +0 -23
- data/lib/instance_agent/codedeploy_plugin/application_specification/file_info.rb +0 -23
- data/lib/instance_agent/codedeploy_plugin/application_specification/linux_permission_info.rb +0 -121
- data/lib/instance_agent/codedeploy_plugin/application_specification/mode_info.rb +0 -66
- data/lib/instance_agent/codedeploy_plugin/application_specification/range_info.rb +0 -134
- data/lib/instance_agent/codedeploy_plugin/application_specification/script_info.rb +0 -27
- data/lib/instance_agent/codedeploy_plugin/codedeploy_control.rb +0 -72
- data/lib/instance_agent/codedeploy_plugin/command_executor.rb +0 -357
- data/lib/instance_agent/codedeploy_plugin/command_poller.rb +0 -170
- data/lib/instance_agent/codedeploy_plugin/deployment_specification.rb +0 -150
- data/lib/instance_agent/codedeploy_plugin/hook_executor.rb +0 -206
- data/lib/instance_agent/codedeploy_plugin/install_instruction.rb +0 -374
- data/lib/instance_agent/codedeploy_plugin/installer.rb +0 -143
- data/lib/instance_agent/codedeploy_plugin/request_helper.rb +0 -28
- data/test/instance_agent/codedeploy_plugin/application_specification_test.rb +0 -1710
- data/test/instance_agent/codedeploy_plugin/install_instruction_test.rb +0 -566
- data/test/instance_agent/codedeploy_plugin/request_helper_test.rb +0 -37
- data/vendor/specifications/jamespath-0.5.1.gemspec +0 -35
@@ -1,357 +0,0 @@
|
|
1
|
-
require 'openssl'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'instance_agent/codedeploy_plugin/installer'
|
4
|
-
require 'instance_agent/codedeploy_plugin/hook_executor'
|
5
|
-
require 'aws-sdk-core'
|
6
|
-
require 'zlib'
|
7
|
-
require 'zip'
|
8
|
-
require 'instance_metadata'
|
9
|
-
require 'open-uri'
|
10
|
-
require 'uri'
|
11
|
-
|
12
|
-
module InstanceAgent
|
13
|
-
module CodeDeployPlugin
|
14
|
-
ARCHIVES_TO_RETAIN = 5
|
15
|
-
class CommandExecutor
|
16
|
-
class << self
|
17
|
-
attr_reader :command_methods
|
18
|
-
end
|
19
|
-
|
20
|
-
attr_reader :deployment_system
|
21
|
-
|
22
|
-
InvalidCommandNameFailure = Class.new(Exception)
|
23
|
-
|
24
|
-
def initialize(options = {})
|
25
|
-
@deployment_system = "CodeDeploy"
|
26
|
-
@deploy_control_client = options[:deploy_control_client]
|
27
|
-
@hook_mapping = options[:hook_mapping]
|
28
|
-
if(!@hook_mapping.nil?)
|
29
|
-
map
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.command(name, &blk)
|
34
|
-
@command_methods ||= Hash.new
|
35
|
-
|
36
|
-
method = Seahorse::Util.underscore(name).to_sym
|
37
|
-
@command_methods[name] = method
|
38
|
-
|
39
|
-
define_method(method, &blk)
|
40
|
-
end
|
41
|
-
|
42
|
-
def execute_command(command, deployment_specification)
|
43
|
-
method_name = command_method(command.command_name)
|
44
|
-
log(:debug, "Command #{command.command_name} maps to method #{method_name}")
|
45
|
-
|
46
|
-
deployment_specification = DeploymentSpecification.parse(deployment_specification)
|
47
|
-
log(:debug, "Successfully parsed the deployment spec")
|
48
|
-
|
49
|
-
log(:debug, "Creating deployment root directory #{deployment_root_dir(deployment_specification)}")
|
50
|
-
FileUtils.mkdir_p(deployment_root_dir(deployment_specification))
|
51
|
-
raise "Error creating deployment root directory #{deployment_root_dir(deployment_specification)}" if !File.directory?(deployment_root_dir(deployment_specification))
|
52
|
-
|
53
|
-
send(method_name, command, deployment_specification)
|
54
|
-
end
|
55
|
-
|
56
|
-
def command_method(command_name)
|
57
|
-
raise InvalidCommandNameFailure.new("Unsupported command type: #{command_name}.") unless self.class.command_methods.has_key?(command_name)
|
58
|
-
self.class.command_methods[command_name]
|
59
|
-
end
|
60
|
-
|
61
|
-
command "DownloadBundle" do |cmd, deployment_spec|
|
62
|
-
cleanup_old_archives(deployment_spec.deployment_group_id)
|
63
|
-
log(:debug, "Executing DownloadBundle command for execution #{cmd.deployment_execution_id}")
|
64
|
-
|
65
|
-
case deployment_spec.revision_source
|
66
|
-
when 'S3'
|
67
|
-
download_from_s3(
|
68
|
-
deployment_spec,
|
69
|
-
deployment_spec.bucket,
|
70
|
-
deployment_spec.key,
|
71
|
-
deployment_spec.version,
|
72
|
-
deployment_spec.etag)
|
73
|
-
when 'GitHub'
|
74
|
-
download_from_github(
|
75
|
-
deployment_spec,
|
76
|
-
deployment_spec.external_account,
|
77
|
-
deployment_spec.repository,
|
78
|
-
deployment_spec.commit_id,
|
79
|
-
deployment_spec.anonymous,
|
80
|
-
deployment_spec.external_auth_token)
|
81
|
-
else
|
82
|
-
# This should never happen since this is checked during creation of the deployment_spec object.
|
83
|
-
raise "Unknown revision type '#{deployment_spec.revision_source}'"
|
84
|
-
end
|
85
|
-
|
86
|
-
FileUtils.rm_rf(File.join(deployment_root_dir(deployment_spec), 'deployment-archive'))
|
87
|
-
bundle_file = artifact_bundle(deployment_spec)
|
88
|
-
|
89
|
-
unpack_bundle(cmd, bundle_file, deployment_spec)
|
90
|
-
|
91
|
-
nil
|
92
|
-
end
|
93
|
-
|
94
|
-
command "Install" do |cmd, deployment_spec|
|
95
|
-
log(:debug, "Executing Install command for execution #{cmd.deployment_execution_id}")
|
96
|
-
|
97
|
-
FileUtils.mkdir_p(deployment_instructions_dir)
|
98
|
-
log(:debug, "Instructions directory created at #{deployment_instructions_dir}")
|
99
|
-
|
100
|
-
installer = Installer.new(:deployment_instructions_dir => deployment_instructions_dir,
|
101
|
-
:deployment_archive_dir => archive_root_dir(deployment_spec))
|
102
|
-
|
103
|
-
log(:debug, "Installing revision #{deployment_spec.revision} in "+
|
104
|
-
"instance group #{deployment_spec.deployment_group_id}")
|
105
|
-
installer.install(deployment_spec.deployment_group_id, default_app_spec(deployment_spec))
|
106
|
-
update_last_successful_install(deployment_spec)
|
107
|
-
nil
|
108
|
-
end
|
109
|
-
|
110
|
-
def map
|
111
|
-
@hook_mapping.each_pair do |command, lifecycle_events|
|
112
|
-
InstanceAgent::CodeDeployPlugin::CommandExecutor.command command do |cmd, deployment_spec|
|
113
|
-
#run the scripts
|
114
|
-
script_log = ScriptLog.new
|
115
|
-
lifecycle_events.each do |lifecycle_event|
|
116
|
-
hook_command = HookExecutor.new(:lifecycle_event => lifecycle_event,
|
117
|
-
:deployment_root_dir => deployment_root_dir(deployment_spec),
|
118
|
-
:last_successful_deployment_dir => last_successful_deployment_dir(deployment_spec.deployment_group_id),
|
119
|
-
:app_spec_path => app_spec_path)
|
120
|
-
script_log.concat_log(hook_command.execute)
|
121
|
-
end
|
122
|
-
script_log.log
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
private
|
128
|
-
def deployment_root_dir(deployment_spec)
|
129
|
-
File.join(ProcessManager::Config.config[:root_dir], deployment_spec.deployment_group_id, deployment_spec.deployment_id)
|
130
|
-
end
|
131
|
-
|
132
|
-
private
|
133
|
-
def deployment_instructions_dir()
|
134
|
-
File.join(ProcessManager::Config.config[:root_dir], 'deployment-instructions')
|
135
|
-
end
|
136
|
-
|
137
|
-
private
|
138
|
-
def archive_root_dir(deployment_spec)
|
139
|
-
File.join(deployment_root_dir(deployment_spec), 'deployment-archive')
|
140
|
-
end
|
141
|
-
|
142
|
-
private
|
143
|
-
def last_successful_deployment_dir(deployment_group)
|
144
|
-
last_install_file_location = last_install_file_path(deployment_group)
|
145
|
-
return unless File.exist? last_install_file_location
|
146
|
-
File.open last_install_file_location do |f|
|
147
|
-
return f.read.chomp
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
private
|
152
|
-
def default_app_spec(deployment_spec)
|
153
|
-
default_app_spec_location = File.join(archive_root_dir(deployment_spec), app_spec_path)
|
154
|
-
log(:debug, "Checking for app spec in #{default_app_spec_location}")
|
155
|
-
app_spec = ApplicationSpecification::ApplicationSpecification.parse(File.read(default_app_spec_location))
|
156
|
-
end
|
157
|
-
|
158
|
-
private
|
159
|
-
def last_install_file_path(deployment_group)
|
160
|
-
File.join(deployment_instructions_dir, "#{deployment_group}_last_successful_install")
|
161
|
-
end
|
162
|
-
|
163
|
-
private
|
164
|
-
def download_from_s3(deployment_spec, bucket, key, version, etag)
|
165
|
-
log(:debug, "Downloading artifact bundle from bucket '#{bucket}' and key '#{key}', version '#{version}', etag '#{etag}'")
|
166
|
-
region = ENV['AWS_REGION'] || InstanceMetadata.region
|
167
|
-
|
168
|
-
if InstanceAgent::Config.config[:log_aws_wire]
|
169
|
-
s3 = Aws::S3::Client.new(
|
170
|
-
:region => region,
|
171
|
-
:ssl_ca_directory => ENV['AWS_SSL_CA_DIRECTORY'],
|
172
|
-
# wire logs might be huge; customers should be careful about turning them on
|
173
|
-
# allow 1GB of old wire logs in 64MB chunks
|
174
|
-
:logger => Logger.new(
|
175
|
-
File.join(InstanceAgent::Config.config[:log_dir], "#{InstanceAgent::Config.config[:program_name]}.aws_wire.log"),
|
176
|
-
16,
|
177
|
-
64 * 1024 * 1024),
|
178
|
-
:http_wire_trace => true)
|
179
|
-
else
|
180
|
-
s3 = Aws::S3::Client.new(
|
181
|
-
:region => region,
|
182
|
-
:ssl_ca_directory => ENV['AWS_SSL_CA_DIRECTORY'])
|
183
|
-
end
|
184
|
-
|
185
|
-
File.open(artifact_bundle(deployment_spec), 'wb') do |file|
|
186
|
-
|
187
|
-
if !version.nil?
|
188
|
-
object = s3.get_object({:bucket => bucket, :key => key, :version_id => version}, :target => file)
|
189
|
-
else
|
190
|
-
object = s3.get_object({:bucket => bucket, :key => key}, :target => file)
|
191
|
-
end
|
192
|
-
|
193
|
-
if(!etag.nil? && !(etag.gsub(/"/,'').eql? object.etag.gsub(/"/,'')))
|
194
|
-
msg = "Expected deployment artifact bundle etag #{etag} but was actually #{object.etag}"
|
195
|
-
log(:error, msg)
|
196
|
-
raise RuntimeError, msg
|
197
|
-
end
|
198
|
-
end
|
199
|
-
log(:debug, "Download complete from bucket #{bucket} and key #{key}")
|
200
|
-
end
|
201
|
-
|
202
|
-
private
|
203
|
-
def download_from_github(deployment_spec, account, repo, commit, anonymous, token)
|
204
|
-
|
205
|
-
retries = 0
|
206
|
-
errors = []
|
207
|
-
|
208
|
-
if InstanceAgent::Platform.util.supported_oses == 'windows'
|
209
|
-
deployment_spec.bundle_type = 'zip'
|
210
|
-
format = 'zipball'
|
211
|
-
else
|
212
|
-
deployment_spec.bundle_type = 'tar'
|
213
|
-
format = 'tarball'
|
214
|
-
end
|
215
|
-
|
216
|
-
uri = URI.parse("https://api.github.com/repos/#{account}/#{repo}/#{format}/#{commit}")
|
217
|
-
options = {:ssl_verify_mode => OpenSSL::SSL::VERIFY_PEER, :redirect => true, :ssl_ca_cert => ENV['AWS_SSL_CA_DIRECTORY']}
|
218
|
-
|
219
|
-
if anonymous
|
220
|
-
log(:debug, "Anonymous GitHub repository download requested.")
|
221
|
-
else
|
222
|
-
log(:debug, "Authenticated GitHub repository download requested.")
|
223
|
-
options.update({'Authorization' => "token #{token}"})
|
224
|
-
end
|
225
|
-
|
226
|
-
begin
|
227
|
-
# stream bundle file to disk
|
228
|
-
log(:info, "Requesting URL: '#{uri.to_s}'")
|
229
|
-
File.open(artifact_bundle(deployment_spec), 'w+b') do |file|
|
230
|
-
uri.open(options) do |github|
|
231
|
-
log(:debug, "GitHub response: '#{github.meta.to_s}'")
|
232
|
-
|
233
|
-
while (buffer = github.read(8 * 1024 * 1024))
|
234
|
-
file.write buffer
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end
|
238
|
-
rescue OpenURI::HTTPError => e
|
239
|
-
log(:error, "Could not download bundle at '#{uri.to_s}'. Server returned code #{e.io.status[0]} '#{e.io.status[1]}'")
|
240
|
-
log(:debug, "Server returned error response body #{e.io.string}")
|
241
|
-
errors << "#{e.io.status[0]} '#{e.io.status[1]}'"
|
242
|
-
|
243
|
-
if retries < 3
|
244
|
-
time_to_sleep = (10 * (3 ** retries)) # 10 sec, 30 sec, 90 sec
|
245
|
-
log(:debug, "Retrying download in #{time_to_sleep} seconds.")
|
246
|
-
sleep(time_to_sleep)
|
247
|
-
retries += 1
|
248
|
-
retry
|
249
|
-
else
|
250
|
-
raise "Could not download bundle at '#{uri.to_s}' after #{retries} retries. Server returned codes: #{errors.join("; ")}."
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
private
|
256
|
-
def unpack_bundle(cmd, bundle_file, deployment_spec)
|
257
|
-
strip_leading_directory = deployment_spec.revision_source == 'GitHub'
|
258
|
-
|
259
|
-
if strip_leading_directory
|
260
|
-
# Extract to a temporary directory first so we can move the files around
|
261
|
-
dst = File.join(deployment_root_dir(deployment_spec), 'deployment-archive-temp')
|
262
|
-
actual_dst = File.join(deployment_root_dir(deployment_spec), 'deployment-archive')
|
263
|
-
FileUtils.rm_rf(dst)
|
264
|
-
else
|
265
|
-
dst = File.join(deployment_root_dir(deployment_spec), 'deployment-archive')
|
266
|
-
end
|
267
|
-
|
268
|
-
if "tar".eql? deployment_spec.bundle_type
|
269
|
-
InstanceAgent::Platform.util.extract_tar(bundle_file, dst)
|
270
|
-
elsif "tgz".eql? deployment_spec.bundle_type
|
271
|
-
InstanceAgent::Platform.util.extract_tgz(bundle_file, dst)
|
272
|
-
elsif "zip".eql? deployment_spec.bundle_type
|
273
|
-
Zip::File.open(bundle_file) do |zipfile|
|
274
|
-
zipfile.each do |f|
|
275
|
-
file_dst = File.join(dst, f.name)
|
276
|
-
FileUtils.mkdir_p(File.dirname(file_dst))
|
277
|
-
zipfile.extract(f, file_dst)
|
278
|
-
end
|
279
|
-
end
|
280
|
-
else
|
281
|
-
# If the bundle was a generated through a Sabini Repository
|
282
|
-
# it will be in tar format, and it won't have a bundle type
|
283
|
-
InstanceAgent::Platform.util.extract_tar(bundle_file, dst)
|
284
|
-
end
|
285
|
-
|
286
|
-
if strip_leading_directory
|
287
|
-
log(:info, "Stripping leading directory from archive bundle contents.")
|
288
|
-
|
289
|
-
# Find leading directory to remove
|
290
|
-
archive_root_files = Dir.entries(dst)
|
291
|
-
archive_root_files.delete_if { |name| name == '.' || name == '..' }
|
292
|
-
|
293
|
-
if (archive_root_files.size != 1)
|
294
|
-
log(:warn, "Expected archive to have a single root directory containing the actual bundle root, but it had #{archive_root_files.size} entries instead. Skipping leading directory removal and using archive as is.")
|
295
|
-
FileUtils.mv(dst, actual_dst)
|
296
|
-
return
|
297
|
-
end
|
298
|
-
|
299
|
-
nested_archive_root = File.join(dst, archive_root_files[0])
|
300
|
-
log(:debug, "Actual archive root at #{nested_archive_root}. Moving to #{actual_dst}")
|
301
|
-
|
302
|
-
FileUtils.mv(nested_archive_root, actual_dst)
|
303
|
-
FileUtils.rmdir(dst)
|
304
|
-
|
305
|
-
log(:debug, Dir.entries(actual_dst).join("; "))
|
306
|
-
end
|
307
|
-
end
|
308
|
-
|
309
|
-
private
|
310
|
-
def update_last_successful_install(deployment_spec)
|
311
|
-
File.open(last_install_file_path(deployment_spec.deployment_group_id), 'w+') do |f|
|
312
|
-
f.write deployment_root_dir(deployment_spec)
|
313
|
-
end
|
314
|
-
end
|
315
|
-
|
316
|
-
private
|
317
|
-
def cleanup_old_archives(deployment_group)
|
318
|
-
deployment_archives = Dir[File.join(ProcessManager::Config.config[:root_dir], deployment_group, '*')]
|
319
|
-
extra = deployment_archives.size - ARCHIVES_TO_RETAIN
|
320
|
-
return unless extra > 0
|
321
|
-
|
322
|
-
# Never remove the last successful deployment
|
323
|
-
last_success = last_successful_deployment_dir(deployment_group)
|
324
|
-
deployment_archives.delete(last_success)
|
325
|
-
|
326
|
-
# Sort oldest -> newest, take first `extra` elements
|
327
|
-
oldest_extra = deployment_archives.sort_by{ |f| File.mtime(f) }.take(extra)
|
328
|
-
|
329
|
-
# Absolute path takes care of relative root directories
|
330
|
-
directories = oldest_extra.map{ |f| File.absolute_path(f) }
|
331
|
-
FileUtils.rm_rf(directories)
|
332
|
-
|
333
|
-
end
|
334
|
-
|
335
|
-
private
|
336
|
-
def artifact_bundle(deployment_spec)
|
337
|
-
File.join(deployment_root_dir(deployment_spec), 'bundle.tar')
|
338
|
-
end
|
339
|
-
|
340
|
-
private
|
341
|
-
def app_spec_path
|
342
|
-
'appspec.yml'
|
343
|
-
end
|
344
|
-
|
345
|
-
private
|
346
|
-
def description
|
347
|
-
self.class.to_s
|
348
|
-
end
|
349
|
-
|
350
|
-
private
|
351
|
-
def log(severity, message)
|
352
|
-
raise ArgumentError, "Unknown severity #{severity.inspect}" unless InstanceAgent::Log::SEVERITIES.include?(severity.to_s)
|
353
|
-
InstanceAgent::Log.send(severity.to_sym, "#{description}: #{message}")
|
354
|
-
end
|
355
|
-
end
|
356
|
-
end
|
357
|
-
end
|
@@ -1,170 +0,0 @@
|
|
1
|
-
require 'instance_agent/codedeploy_plugin/command_executor'
|
2
|
-
require 'instance_metadata'
|
3
|
-
require 'socket'
|
4
|
-
require 'instance_agent/codedeploy_plugin/codedeploy_control'
|
5
|
-
|
6
|
-
module InstanceAgent
|
7
|
-
module CodeDeployPlugin
|
8
|
-
class CommandPoller < InstanceAgent::Agent::Base
|
9
|
-
|
10
|
-
VERSION = "2013-04-23"
|
11
|
-
|
12
|
-
def initialize
|
13
|
-
region = ENV['AWS_REGION'] || InstanceMetadata.region
|
14
|
-
@host_identifier = ENV['AWS_HOST_IDENTIFIER'] || InstanceMetadata.host_identifier
|
15
|
-
|
16
|
-
log(:debug, "Configuring deploy control client: Region = #{region.inspect}")
|
17
|
-
log(:debug, "Deploy control endpoint override = " + ENV['AWS_DEPLOY_CONTROL_ENDPOINT'].inspect)
|
18
|
-
|
19
|
-
@deploy_control_client = InstanceAgent::CodeDeployPlugin::CodeDeployControl.new(:region => region, :logger => InstanceAgent::Log, :ssl_ca_directory => ENV['AWS_SSL_CA_DIRECTORY']).get_client
|
20
|
-
|
21
|
-
@plugin = InstanceAgent::CodeDeployPlugin::CommandExecutor.new(
|
22
|
-
:deploy_control_client => @deploy_control_client,
|
23
|
-
:hook_mapping => create_hook_mapping)
|
24
|
-
|
25
|
-
log(:debug, "Initializing Host Agent: " +
|
26
|
-
"Host Identifier = #{@host_identifier}")
|
27
|
-
end
|
28
|
-
|
29
|
-
def create_hook_mapping
|
30
|
-
#Map commands to lifecycle hooks
|
31
|
-
{ "BeforeELBRemove"=>["BeforeELBRemove"],
|
32
|
-
"AfterELBRemove"=>["AfterELBRemove"],
|
33
|
-
"ApplicationStop"=>["ApplicationStop"],
|
34
|
-
"BeforeInstall"=>["BeforeInstall"],
|
35
|
-
"AfterInstall"=>["AfterInstall"],
|
36
|
-
"ApplicationStart"=>["ApplicationStart"],
|
37
|
-
"BeforeELBAdd"=>["BeforeELBAdd"],
|
38
|
-
"AfterELBAdd"=>["AfterELBAdd"],
|
39
|
-
"ValidateService"=>["ValidateService"]}
|
40
|
-
end
|
41
|
-
|
42
|
-
def perform
|
43
|
-
return unless command = next_command
|
44
|
-
return unless acknowledge_command(command)
|
45
|
-
|
46
|
-
begin
|
47
|
-
spec = get_deployment_specification(command)
|
48
|
-
#Successful commands will complete without raising an exception
|
49
|
-
script_output = process_command(command, spec)
|
50
|
-
log(:debug, 'Calling PutHostCommandComplete: "Succeeded"')
|
51
|
-
@deploy_control_client.put_host_command_complete(
|
52
|
-
:command_status => 'Succeeded',
|
53
|
-
:diagnostics => {:format => "JSON", :payload => gather_diagnostics()},
|
54
|
-
:host_command_identifier => command.host_command_identifier)
|
55
|
-
|
56
|
-
#Commands that throw an exception will be considered to have failed
|
57
|
-
rescue ScriptError => e
|
58
|
-
log(:debug, 'Calling PutHostCommandComplete: "Code Error" ')
|
59
|
-
@deploy_control_client.put_host_command_complete(
|
60
|
-
:command_status => "Failed",
|
61
|
-
:diagnostics => {:format => "JSON", :payload => gather_diagnostics_from_script_error(e)},
|
62
|
-
:host_command_identifier => command.host_command_identifier)
|
63
|
-
raise e
|
64
|
-
rescue Exception => e
|
65
|
-
log(:debug, 'Calling PutHostCommandComplete: "Code Error" ')
|
66
|
-
@deploy_control_client.put_host_command_complete(
|
67
|
-
:command_status => "Failed",
|
68
|
-
:diagnostics => {:format => "JSON", :payload => gather_diagnostics_from_error(e)},
|
69
|
-
:host_command_identifier => command.host_command_identifier)
|
70
|
-
raise e
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def next_command
|
75
|
-
log(:debug, "Calling PollHostCommand:")
|
76
|
-
output = @deploy_control_client.poll_host_command(:host_identifier => @host_identifier)
|
77
|
-
command = output.host_command
|
78
|
-
if command.nil?
|
79
|
-
log(:debug, "PollHostCommand: Host Command = nil")
|
80
|
-
else
|
81
|
-
log(:debug, "PollHostCommand: " +
|
82
|
-
"Host Identifier = #{command.host_identifier}; " +
|
83
|
-
"Host Command Identifier = #{command.host_command_identifier}; " +
|
84
|
-
"Deployment Execution ID = #{command.deployment_execution_id}; " +
|
85
|
-
"Command Name = #{command.command_name}")
|
86
|
-
raise "Host Identifier mismatch: #{@host_identifier} != #{command.host_identifier}" unless @host_identifier.include? command.host_identifier
|
87
|
-
raise "Command Name missing" if command.command_name.nil? || command.command_name.empty?
|
88
|
-
end
|
89
|
-
command
|
90
|
-
end
|
91
|
-
|
92
|
-
def acknowledge_command(command)
|
93
|
-
log(:debug, "Calling PutHostCommandAcknowledgement:")
|
94
|
-
output = @deploy_control_client.put_host_command_acknowledgement(
|
95
|
-
:diagnostics => nil,
|
96
|
-
:host_command_identifier => command.host_command_identifier)
|
97
|
-
status = output.command_status
|
98
|
-
log(:debug, "Command Status = #{status}")
|
99
|
-
|
100
|
-
if status == 'Succeeded' || status == 'Failed'
|
101
|
-
log(:debug, "Calling PutHostCommandComplete: \"#{status}\" ")
|
102
|
-
@deploy_control_client.put_host_command_complete(
|
103
|
-
:command_status => status,
|
104
|
-
:diagnostics => {:format => "JSON", :payload => gather_diagnostics_from_acknowledge(status)},
|
105
|
-
:host_command_identifier => command.host_command_identifier)
|
106
|
-
return false
|
107
|
-
end
|
108
|
-
|
109
|
-
return true
|
110
|
-
end
|
111
|
-
|
112
|
-
def get_deployment_specification(command)
|
113
|
-
log(:debug, "Calling GetDeploymentSpecification:")
|
114
|
-
output = @deploy_control_client.get_deployment_specification(
|
115
|
-
:deployment_execution_id => command.deployment_execution_id,
|
116
|
-
:host_identifier => @host_identifier)
|
117
|
-
log(:debug, "GetDeploymentSpecification: " +
|
118
|
-
"Deployment System = #{output.deployment_system}")
|
119
|
-
raise "Deployment System mismatch: #{@plugin.deployment_system} != #{output.deployment_system}" unless @plugin.deployment_system == output.deployment_system
|
120
|
-
raise "Deployment Specification missing" if output.deployment_specification.nil?
|
121
|
-
output.deployment_specification.generic_envelope
|
122
|
-
end
|
123
|
-
|
124
|
-
def process_command(command, spec)
|
125
|
-
log(:debug, "Calling #{@plugin.to_s}.execute_command")
|
126
|
-
@plugin.execute_command(command, spec)
|
127
|
-
end
|
128
|
-
|
129
|
-
private
|
130
|
-
def gather_diagnostics_from_script_error(script_error)
|
131
|
-
script_error.to_json
|
132
|
-
end
|
133
|
-
|
134
|
-
private
|
135
|
-
def gather_diagnostics_from_error(error)
|
136
|
-
begin
|
137
|
-
message = error.message || ""
|
138
|
-
raise ScriptError.new(ScriptError::UNKNOWN_ERROR_CODE, "", ScriptLog.new), message
|
139
|
-
rescue ScriptError => e
|
140
|
-
script_error = e
|
141
|
-
end
|
142
|
-
gather_diagnostics_from_script_error(script_error)
|
143
|
-
end
|
144
|
-
|
145
|
-
private
|
146
|
-
def gather_diagnostics()
|
147
|
-
begin
|
148
|
-
raise ScriptError.new(ScriptError::SUCCEEDED_CODE, "", ScriptLog.new), 'Succeeded'
|
149
|
-
rescue ScriptError => e
|
150
|
-
script_error = e
|
151
|
-
end
|
152
|
-
gather_diagnostics_from_script_error(script_error)
|
153
|
-
end
|
154
|
-
|
155
|
-
private
|
156
|
-
def gather_diagnostics_from_acknowledge(status)
|
157
|
-
begin
|
158
|
-
if status == 'Succeeded'
|
159
|
-
raise ScriptError.new(ScriptError::SUCCEEDED_CODE, "", ScriptLog.new), 'Succeeded'
|
160
|
-
else
|
161
|
-
raise ScriptError.new(ScriptError::UNKNOWN_ERROR_CODE, "", ScriptLog.new), 'Failed'
|
162
|
-
end
|
163
|
-
rescue ScriptError => e
|
164
|
-
script_error = e
|
165
|
-
end
|
166
|
-
gather_diagnostics_from_script_error(script_error)
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|