Skip to content

Commit f294c2e

Browse files
author
nyo
committed
Allow overriding appspec path + fallback to appspec.yml and appspec.yaml
Removed leftover debug typos Renamed variable to not have default in the name
1 parent a0e45b6 commit f294c2e

File tree

4 files changed

+158
-34
lines changed

4 files changed

+158
-34
lines changed

lib/instance_agent/plugins/codedeploy/command_executor.rb

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ def map
154154
:deployment_root_dir => deployment_root_dir(deployment_spec),
155155
:last_successful_deployment_dir => last_successful_deployment_dir(deployment_spec.deployment_group_id),
156156
:most_recent_deployment_dir => most_recent_deployment_dir(deployment_spec.deployment_group_id),
157-
:app_spec_path => app_spec_path)
157+
:app_spec_path => deployment_spec.app_spec_path)
158158
script_log.concat_log(hook_command.execute)
159159
end
160160
script_log.log
@@ -183,7 +183,7 @@ def last_successful_deployment_dir(deployment_group)
183183
return unless File.exist? last_successful_install_file_location
184184
File.open last_successful_install_file_location do |f|
185185
return f.read.chomp
186-
end
186+
end
187187
end
188188

189189
private
@@ -192,18 +192,18 @@ def most_recent_deployment_dir(deployment_group)
192192
return unless File.exist? most_recent_install_file_location
193193
File.open most_recent_install_file_location do |f|
194194
return f.read.chomp
195-
end
195+
end
196196
end
197197

198198
private
199199
def default_app_spec(deployment_spec)
200-
default_app_spec_location = File.join(archive_root_dir(deployment_spec), app_spec_path)
201-
log(:debug, "Checking for app spec in #{default_app_spec_location}")
202-
validate_app_spec_hooks(ApplicationSpecification::ApplicationSpecification.parse(File.read(default_app_spec_location)), deployment_spec.all_possible_lifecycle_events)
200+
app_spec_location = app_spec_real_path(deployment_spec)
201+
validate_app_spec_hooks(app_spec_location, deployment_spec.all_possible_lifecycle_events)
203202
end
204203

205204
private
206-
def validate_app_spec_hooks(app_spec, all_possible_lifecycle_events)
205+
def validate_app_spec_hooks(app_spec_location, all_possible_lifecycle_events)
206+
app_spec = ApplicationSpecification::ApplicationSpecification.parse(File.read(app_spec_location))
207207
unless all_possible_lifecycle_events.nil?
208208
app_spec_hooks_plus_hooks_from_mapping = app_spec.hooks.keys.to_set.merge(@hook_mapping.keys).to_a
209209
unless app_spec_hooks_plus_hooks_from_mapping.to_set.subset?(all_possible_lifecycle_events.to_set)
@@ -238,7 +238,7 @@ def most_recent_install_file_path(deployment_group)
238238
private
239239
def download_from_s3(deployment_spec, bucket, key, version, etag)
240240
log(:debug, "Downloading artifact bundle from bucket '#{bucket}' and key '#{key}', version '#{version}', etag '#{etag}'")
241-
241+
242242
s3 = Aws::S3::Client.new(s3_options)
243243

244244
File.open(artifact_bundle(deployment_spec), 'wb') do |file|
@@ -269,14 +269,14 @@ def s3_options
269269
if !InstanceAgent::Config.config[:s3_endpoint_override].to_s.empty?
270270
options[:endpoint] = URI(InstanceAgent::Config.config[:s3_endpoint_override])
271271
elsif InstanceAgent::Config.config[:use_fips_mode]
272-
#S3 Fips pseudo-regions are not supported by the SDK yet
272+
#S3 Fips pseudo-regions are not supported by the SDK yet
273273
#source for the URL: https://aws.amazon.com/compliance/fips/
274274
options[:endpoint] = "https://s3-fips.#{region}.amazonaws.com"
275-
end
275+
end
276276
proxy_uri = nil
277277
if InstanceAgent::Config.config[:proxy_uri]
278278
proxy_uri = URI(InstanceAgent::Config.config[:proxy_uri])
279-
end
279+
end
280280
options[:http_proxy] = proxy_uri
281281

282282
if InstanceAgent::Config.config[:log_aws_wire]
@@ -288,10 +288,10 @@ def s3_options
288288
64 * 1024 * 1024)
289289
options[:http_wire_trace] = true
290290
end
291-
292-
options
293-
end
294-
291+
292+
options
293+
end
294+
295295
private
296296
def download_from_github(deployment_spec, account, repo, commit, anonymous, token)
297297

@@ -402,7 +402,7 @@ def unpack_bundle(cmd, bundle_file, deployment_spec)
402402

403403
# If the top level of the archive is a directory that contains an appspec,
404404
# strip that before giving up
405-
if ((archive_root_files.size == 1) &&
405+
if ((archive_root_files.size == 1) &&
406406
File.directory?(File.join(dst, archive_root_files[0])) &&
407407
Dir.entries(File.join(dst, archive_root_files[0])).grep(/appspec/i).any?)
408408
log(:info, "Stripping leading directory from archive bundle contents.")
@@ -417,7 +417,7 @@ def unpack_bundle(cmd, bundle_file, deployment_spec)
417417
FileUtils.mv(nested_archive_root, dst)
418418
FileUtils.rmdir(tmp_dst)
419419

420-
log(:debug, Dir.entries(dst).join("; "))
420+
log(:debug, Dir.entries(dst).join("; "))
421421
end
422422
end
423423

@@ -433,7 +433,7 @@ def update_most_recent_install(deployment_spec)
433433
File.open(most_recent_install_file_path(deployment_spec.deployment_group_id), 'w+') do |f|
434434
f.write deployment_root_dir(deployment_spec)
435435
end
436-
end
436+
end
437437

438438
private
439439
def cleanup_old_archives(deployment_spec)
@@ -445,7 +445,7 @@ def cleanup_old_archives(deployment_spec)
445445

446446
full_path_deployment_archives = deployment_archives.map{ |f| File.join(ProcessManager::Config.config[:root_dir], deployment_group, f)}
447447
full_path_deployment_archives.delete(deployment_root_dir(deployment_spec))
448-
448+
449449
extra = full_path_deployment_archives.size - @archives_to_retain + 1
450450
return unless extra > 0
451451

@@ -458,7 +458,7 @@ def cleanup_old_archives(deployment_spec)
458458

459459
# Absolute path takes care of relative root directories
460460
directories = oldest_extra.map{ |f| File.absolute_path(f) }
461-
log(:debug,"Delete Files #{directories}" )
461+
log(:debug, "Delete Files #{directories}")
462462
InstanceAgent::Platform.util.delete_dirs_command(directories)
463463

464464
end
@@ -473,6 +473,24 @@ def app_spec_path
473473
'appspec.yml'
474474
end
475475

476+
# Checks for existence the possible extensions of the app_spec_path (.yml and .yaml)
477+
private
478+
def app_spec_real_path(deployment_spec)
479+
app_spec_param_location = File.join(archive_root_dir(deployment_spec), deployment_spec.app_spec_path)
480+
app_spec_yaml_location = File.join(archive_root_dir(deployment_spec), "appspec.yaml")
481+
app_spec_yml_location = File.join(archive_root_dir(deployment_spec), "appspec.yml")
482+
if File.exist? app_spec_param_location
483+
log(:debug, "Using appspec file #{app_spec_param_location}")
484+
app_spec_param_location
485+
elsif File.exist? app_spec_yaml_location
486+
log(:debug, "Using appspec file #{app_spec_yaml_location}")
487+
app_spec_yaml_location
488+
else
489+
log(:debug, "Using appspec file #{app_spec_yml_location}")
490+
app_spec_yml_location
491+
end
492+
end
493+
476494
private
477495
def description
478496
self.class.to_s

lib/instance_agent/plugins/codedeploy/deployment_specification.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class DeploymentSpecification
1313
attr_accessor :external_account, :repository, :commit_id, :anonymous, :external_auth_token
1414
attr_accessor :file_exists_behavior
1515
attr_accessor :local_location, :all_possible_lifecycle_events
16+
attr_accessor :app_spec_path
1617
class << self
1718
attr_accessor :cert_store
1819
end
@@ -47,6 +48,12 @@ def initialize(data)
4748
@deployment_creator = data["DeploymentCreator"] || "user"
4849
@deployment_type = data["DeploymentType"] || "IN_PLACE"
4950

51+
if property_set?(data, "AppSpecPath")
52+
@app_spec_path = data["AppSpecPath"]
53+
else
54+
@app_spec_path = "appspec.yml"
55+
end
56+
5057
raise 'Must specify a revison' unless data["Revision"]
5158
@revision_source = data["Revision"]["RevisionType"]
5259
raise 'Must specify a revision source' unless @revision_source

test/instance_agent/plugins/codedeploy/command_executor_test.rb

Lines changed: 96 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,8 @@ def generate_signed_message_for(map)
148148
File.stubs(:open).with(@last_successful_install_file_location)
149149

150150
@app_spec = mock("parsed application specification")
151-
File.
152-
stubs(:read).
153-
with("#@archive_root_dir/appspec.yml").
154-
returns("APP SPEC")
151+
File.stubs(:exist?).with("#@archive_root_dir/appspec.yml").returns(true)
152+
File.stubs(:read).with("#@archive_root_dir/appspec.yml").returns("APP SPEC")
155153
ApplicationSpecification::ApplicationSpecification.stubs(:parse).with("APP SPEC").returns(@app_spec)
156154
end
157155

@@ -234,6 +232,91 @@ def generate_signed_message_for(map)
234232
@command_executor.execute_command(@command, deployment_spec)
235233
end
236234
end
235+
236+
should 'honor the AppSpecPath command variable' do
237+
deployment_spec = generate_signed_message_for({
238+
"DeploymentId" => @deployment_id.to_s,
239+
"DeploymentGroupId" => @deployment_group_id,
240+
"ApplicationName" => @application_name,
241+
"DeploymentGroupName" => @deployment_group_name,
242+
"DeploymentCreator" => @deployment_creator,
243+
"DeploymentType" => @deployment_type,
244+
"AgentActionOverrides" => @agent_actions_overrides,
245+
"AppSpecPath" => "appspec-override.yaml",
246+
"Revision" => {
247+
"RevisionType" => "S3",
248+
"S3Revision" => @s3Revision
249+
}
250+
})
251+
252+
File.expects(:exist?).with("#@archive_root_dir/appspec-override.yaml").returns(true)
253+
File.expects(:read).with("#@archive_root_dir/appspec-override.yaml").returns("APP SPEC")
254+
@command_executor.execute_command(@command, deployment_spec)
255+
end
256+
257+
should 'fallback to appspec.yaml if provided AppSpecPath variable points to a file which does\'t exist' do
258+
deployment_spec = generate_signed_message_for({
259+
"DeploymentId" => @deployment_id.to_s,
260+
"DeploymentGroupId" => @deployment_group_id,
261+
"ApplicationName" => @application_name,
262+
"DeploymentGroupName" => @deployment_group_name,
263+
"DeploymentCreator" => @deployment_creator,
264+
"DeploymentType" => @deployment_type,
265+
"AgentActionOverrides" => @agent_actions_overrides,
266+
"AppSpecPath" => "appspec-override.yaml",
267+
"Revision" => {
268+
"RevisionType" => "S3",
269+
"S3Revision" => @s3Revision
270+
}
271+
})
272+
273+
File.expects(:exist?).with("#@archive_root_dir/appspec-override.yaml").returns(false)
274+
File.expects(:exist?).with("#@archive_root_dir/appspec.yaml").returns(true)
275+
File.expects(:read).with("#@archive_root_dir/appspec.yaml").returns("APP SPEC")
276+
@command_executor.execute_command(@command, deployment_spec)
277+
end
278+
should 'fallback to appspec.yaml if both AppSpecPath variable and appspec.yaml don\'t exist' do
279+
deployment_spec = generate_signed_message_for({
280+
"DeploymentId" => @deployment_id.to_s,
281+
"DeploymentGroupId" => @deployment_group_id,
282+
"ApplicationName" => @application_name,
283+
"DeploymentGroupName" => @deployment_group_name,
284+
"DeploymentCreator" => @deployment_creator,
285+
"DeploymentType" => @deployment_type,
286+
"AgentActionOverrides" => @agent_actions_overrides,
287+
"AppSpecPath" => "appspec-override.yaml",
288+
"Revision" => {
289+
"RevisionType" => "S3",
290+
"S3Revision" => @s3Revision
291+
}
292+
})
293+
294+
File.expects(:exist?).with("#@archive_root_dir/appspec-override.yaml").returns(false)
295+
File.expects(:exist?).with("#@archive_root_dir/appspec.yaml").returns(false)
296+
File.expects(:read).with("#@archive_root_dir/appspec.yml").returns("APP SPEC")
297+
@command_executor.execute_command(@command, deployment_spec)
298+
end
299+
300+
should 'fallback to appspec.yaml if appspec.yml is not there and no AppSpecPath arg is specified' do
301+
deployment_spec = generate_signed_message_for({
302+
"DeploymentId" => @deployment_id.to_s,
303+
"DeploymentGroupId" => @deployment_group_id,
304+
"ApplicationName" => @application_name,
305+
"DeploymentGroupName" => @deployment_group_name,
306+
"DeploymentCreator" => @deployment_creator,
307+
"DeploymentType" => @deployment_type,
308+
"AgentActionOverrides" => @agent_actions_overrides,
309+
"Revision" => {
310+
"RevisionType" => "S3",
311+
"S3Revision" => @s3Revision
312+
}
313+
})
314+
315+
File.expects(:exist?).with("#@archive_root_dir/appspec.yml").returns(false)
316+
File.expects(:exist?).with("#@archive_root_dir/appspec.yaml").returns(true)
317+
File.expects(:read).with("#@archive_root_dir/appspec.yaml").returns("APP SPEC")
318+
@command_executor.execute_command(@command, deployment_spec)
319+
end
237320
end
238321

239322
context "when executing the DownloadBundle command" do
@@ -317,36 +400,36 @@ def generate_signed_message_for(map)
317400
end
318401

319402
context "when creating S3 options" do
320-
403+
321404
should "use right region" do
322405
assert_equal 'us-east-1', @command_executor.s3_options[:region]
323406
end
324-
325-
should "use right signature version" do
407+
408+
should "use right signature version" do
326409
assert_equal 'v4', @command_executor.s3_options[:signature_version]
327410
end
328-
411+
329412
should "use right endpoint when using Fips" do
330413
InstanceAgent::Config.config[:use_fips_mode] = true
331414
assert_equal 'https://s3-fips.us-east-1.amazonaws.com', @command_executor.s3_options[:endpoint]
332415
InstanceAgent::Config.config[:use_fips_mode] = false
333416
end
334-
417+
335418
should "use right endpoint when using endpoint override" do
336419
s3_endpoint_override_url = 'htpp://testendpointoverride'
337420
InstanceAgent::Config.config[:s3_endpoint_override] = s3_endpoint_override_url
338421
assert_equal s3_endpoint_override_url, @command_executor.s3_options[:endpoint].to_s
339422
InstanceAgent::Config.config[:s3_endpoint_override] = nil
340423
end
341-
424+
342425
should "use no endpoint when neither using Fips nor Endpoint override" do
343426
InstanceAgent::Config.config[:s3_endpoint_override] = nil
344427
InstanceAgent::Config.config[:use_fips_mode] = false
345428
assert_false @command_executor.s3_options.include? :endpoint
346429
end
347-
430+
348431
end
349-
432+
350433
context "downloading bundle from S3" do
351434
setup do
352435
File.expects(:open).with(File.join(@deployment_root_dir, 'bundle.tar'), 'wb').yields(@mock_file)
@@ -598,7 +681,7 @@ def generate_signed_message_for(map)
598681
:deployment_group_id => @deployment_group_id,
599682
:deployment_creator => @deployment_creator,
600683
:deployment_type => @deployment_type,
601-
:deployment_root_dir => @deployment_root_dir,
684+
:deployment_root_dir => @deployment_root_dir,
602685
:last_successful_deployment_dir => nil,
603686
:most_recent_deployment_dir => nil,
604687
:app_spec_path => 'appspec.yml'}

test/instance_agent/plugins/codedeploy/deployment_specification_test.rb

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def generate_signed_message_for(map)
2525
@agent_actions_overrides = {"AgentOverrides" => @agent_actions_overrides_map}
2626
@bundle_type = 'tar'
2727
InstanceAgent::Config.init
28-
end
28+
end
2929

3030
context 'With Github Revision' do
3131
setup do
@@ -601,6 +601,22 @@ def generate_signed_message_for(map)
601601
end
602602
end
603603

604+
context "with app_spec_path" do
605+
should "use the variable set by the AppSpecPath variable" do
606+
@deployment_spec["AppSpecPath"] = "foo.yaml"
607+
@packed_message = generate_signed_message_for(@deployment_spec)
608+
parsed_deployment_spec = InstanceAgent::Plugins::CodeDeployPlugin::DeploymentSpecification.parse(@packed_message)
609+
assert_equal "foo.yaml", parsed_deployment_spec.app_spec_path
610+
end
611+
612+
should "fallback to appspec.yml if AppSpecPath is not set" do
613+
@deployment_spec.delete("AppSPecPath")
614+
@packed_message = generate_signed_message_for(@deployment_spec)
615+
parsed_deployment_spec = InstanceAgent::Plugins::CodeDeployPlugin::DeploymentSpecification.parse(@packed_message)
616+
assert_equal "appspec.yml", parsed_deployment_spec.app_spec_path
617+
end
618+
end
619+
604620
context "with file_exists_behavior" do
605621
should "set file_exists_behavior to DISALLOW when AgentActionOverrides is not set" do
606622
@deployment_spec.delete("AgentActionOverrides")

0 commit comments

Comments
 (0)