Skip to content

Commit

Permalink
[Agent 1.1.2] Add unit test to verify unpack_bundle ruby unzip mechanism
Browse files Browse the repository at this point in the history
Why is this change needed?
---------
Prior to this change, we didn't have a way to test the "overwrite" logic
in ruby unzip during the fallback mechanism of unpack_bundle method in
DownloadBundle command.

How does it address the issue?
---------
This change adds a unit test to verify if the fallback mechanism works
with a debris file in the deployment archive directory.
  • Loading branch information
Anandaraju Coimbatore Sivaraju authored and Alena Kastsiukavets committed Jul 31, 2020
1 parent 72e0cbd commit 8bc7f07
Showing 1 changed file with 121 additions and 0 deletions.
121 changes: 121 additions & 0 deletions test/instance_agent/plugins/codedeploy/unpack_bundle_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
require 'test_helper'
require 'certificate_helper'
require 'stringio'
require 'aws/codedeploy/local/deployer'

class UnpackBundleTest < InstanceAgentTestCase
include InstanceAgent::Plugins::CodeDeployPlugin
def generate_signed_message_for(map)
message = @cert_helper.sign_message(map.to_json)
spec = OpenStruct.new({ :payload => message })
spec.format = "PKCS7/JSON"

return spec
end

# method to create a local source bundle file as zip
def setup_local_file_bundle
@local_file_directory = File.join(@root_dir, @deployment_group_id.to_s, 'LocalFileDirectory')
FileUtils.rm_rf(@local_file_directory)
FileUtils.mkdir_p(@local_file_directory)

input_filenames = %w(file1.txt file2.txt)
input_filenames.each do |filename|
File.open(File.join(@local_file_directory, filename), "w") do |f|
f.write("content of #{filename}")
f.close
end
end
# create the bundle as a local zip file
@local_file_location = File.join(@local_file_directory, "bundle.zip")
Zip::File.open(@local_file_location, Zip::File::CREATE) do |zipfile|
input_filenames.each do |filename|
zipfile.add(filename, File.join(@local_file_directory, filename))
end
end
end

context 'The CodeDeploy Plugin Command Executor' do
setup do
@test_hook_mapping = {
"BeforeBlockTraffic"=>["BeforeBlockTraffic"],
"AfterBlockTraffic"=>["AfterBlockTraffic"],
"ApplicationStop"=>["ApplicationStop"],
"BeforeInstall"=>["BeforeInstall"],
"AfterInstall"=>["AfterInstall"],
"ApplicationStart"=>["ApplicationStart"],
"BeforeAllowTraffic"=>["BeforeAllowTraffic"],
"AfterAllowTraffic"=>["AfterAllowTraffic"],
"ValidateService"=>["ValidateService"]
}
@deploy_control_client = mock
@command_executor = InstanceAgent::Plugins::CodeDeployPlugin::CommandExecutor.new(
{
:deploy_control_client => @deploy_control_client,
:hook_mapping => @test_hook_mapping
})
@aws_region = 'us-east-1'
InstanceMetadata.stubs(:region).returns(@aws_region)
end

context "when executing a command" do
setup do
@cert_helper = CertificateHelper.new
@deployment_id = SecureRandom.uuid
@deployment_group_name = "TestDeploymentGroup"
@application_name = "TestApplicationName"
@deployment_group_id = "foobar"
@command = Aws::CodeDeployCommand::Types::HostCommandInstance.new(
:host_command_identifier => "command-1",
:deployment_execution_id => "test-execution")
@root_dir = '/tmp/codedeploy/'
@deployment_root_dir = File.join(@root_dir, @deployment_group_id.to_s, @deployment_id.to_s)
@archive_root_dir = File.join(@deployment_root_dir, 'deployment-archive')
ProcessManager::Config.config[:root_dir] = @root_dir
end

context "test fallback mechanism in unpack_bundle in DownloadBundle" do
setup do
setup_local_file_bundle

# Create a debris file in the deployment-archive directory to simulate Zip::DestinationFileExistsError.
# This error will be thrown, if the ruby unzip overwrite option is not enabled and when the @archive_root_dir already has the same file.
# With the ruby unzip overwrite fix, the unpack_bundle should succeed even with debris files.
FileUtils.rm_rf(@archive_root_dir)
FileUtils.mkdir_p(@archive_root_dir)
FileUtils.cp(File.join(@local_file_directory, 'file1.txt'), @archive_root_dir)

# We need to avoid removing @archive_root_dir in the actual logic, to avoid debris file to be deleted.
FileUtils.stubs(:rm_rf).with(@archive_root_dir)
# This exception will let the unpack_bundle method to use the rubyzip fallback mechanism
InstanceAgent::LinuxUtil.expects(:extract_zip)
.with(File.join(@deployment_root_dir, 'bundle.tar'), @archive_root_dir)
.raises("Exception: System unzip throws exception with non-zero exit code")

@command.command_name = 'DownloadBundle'
@bundle_type = 'zip'
@deployment_spec = generate_signed_message_for(
{
"DeploymentId" => @deployment_id.to_s,
"DeploymentGroupId" => @deployment_group_id.to_s,
"ApplicationName" => @application_name,
"DeploymentGroupName" => @deployment_group_name,
"Revision" => {
"RevisionType" => "Local File",
"LocalRevision" => {
"Location" => @local_file_location,
"BundleType" => @bundle_type
}
}
})
end

should 'execute DownloadBundle command with debris file in deployment-archive' do
assert_equal 1, (Dir.entries(@archive_root_dir) - [".", ".."]).size
@command_executor.execute_command(@command, @deployment_spec)
assert_equal 2, (Dir.entries(@archive_root_dir) - [".", ".."]).size
end
end
end
end
end

0 comments on commit 8bc7f07

Please sign in to comment.