Description
Hello team,
We are facing an issue where CodeDeploy is unable to OVERWRITE symlinks during an in-place deployment.
This is hapening since we use --file-exists-behavior "OVERWRITE" option in the deploy script (aws deploy create-deployment).
I've digged, and:
This is the error I got from CodeDeploy:
2017-11-29 18:14:43 ERROR [codedeploy-agent(3901)]: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller: Error during perform: Errno::EEXIST - File exists - (../squizlabs/php_codesniffer/bin/phpcs, /var/www/vhosts/staging/httpdocs/vendor/bin/phpcs) - /usr/share/ruby/fileutils.rb:349:in `symlink'
/usr/share/ruby/fileutils.rb:349:in `block in ln_s'
/usr/share/ruby/fileutils.rb:1574:in `fu_each_src_dest0'
/usr/share/ruby/fileutils.rb:347:in `ln_s'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/install_instruction.rb:235:in `execute'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/installer.rb:49:in `block (2 levels) in install'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/installer.rb:48:in `each'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/installer.rb:48:in `block in install'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/installer.rb:47:in `open'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/installer.rb:47:in `install'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/command_executor.rb:136:in `block in <class:CommandExecutor>'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/command_executor.rb:68:in `execute_command'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/command_poller.rb:134:in `process_command'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/command_poller.rb:67:in `perform'
/opt/codedeploy-agent/lib/instance_agent/agent/base.rb:28:in `run'
/opt/codedeploy-agent/lib/instance_agent/runner/child.rb:38:in `block in run'
/opt/codedeploy-agent/lib/instance_agent/runner/child.rb:55:in `with_error_handling'
/opt/codedeploy-agent/lib/instance_agent/runner/child.rb:37:in `run'
/opt/codedeploy-agent/vendor/gems/process_manager-0.0.13/lib/process_manager/child.rb:70:in `block in run_with_error_handling'
/opt/codedeploy-agent/lib/instance_agent/runner/child.rb:55:in `with_error_handling'
/opt/codedeploy-agent/vendor/gems/process_manager-0.0.13/lib/process_manager/child.rb:69:in `run_with_error_handling'
/opt/codedeploy-agent/vendor/gems/process_manager-0.0.13/lib/process_manager/child.rb:33:in `block in start'
/opt/codedeploy-agent/vendor/gems/process_manager-0.0.13/lib/process_manager/child.rb:22:in `loop'
/opt/codedeploy-agent/vendor/gems/process_manager-0.0.13/lib/process_manager/child.rb:22:in `start'
/opt/codedeploy-agent/vendor/gems/process_manager-0.0.13/lib/process_manager/master.rb:206:in `block in spawn_child'
/opt/codedeploy-agent/vendor/gems/process_manager-0.0.13/lib/process_manager/master.rb:204:in `fork'
/opt/codedeploy-agent/vendor/gems/process_manager-0.0.13/lib/process_manager/master.rb:204:in `spawn_child'
/opt/codedeploy-agent/vendor/gems/process_manager-0.0.13/lib/process_manager/master.rb:196:in `block in spawn_children'
/opt/codedeploy-agent/vendor/gems/process_manager-0.0.13/lib/process_manager/master.rb:195:in `times'
/opt/codedeploy-agent/vendor/gems/process_manager-0.0.13/lib/process_manager/master.rb:195:in `spawn_children'
/opt/codedeploy-agent/vendor/gems/process_manager-0.0.13/lib/process_manager/master.rb:134:in `start'
/opt/codedeploy-agent/vendor/gems/process_manager-0.0.13/lib/process_manager/master.rb:37:in `block in start'
/opt/codedeploy-agent/vendor/gems/process_manager-0.0.13/lib/process_manager/master.rb:36:in `fork'
/opt/codedeploy-agent/vendor/gems/process_manager-0.0.13/lib/process_manager/master.rb:36:in `start'
/opt/codedeploy-agent/bin/../lib/codedeploy-agent.rb:43:in `block (2 levels) in <main>'
/opt/codedeploy-agent/vendor/gems/gli-2.11.0/lib/gli/command_support.rb:126:in `call'
/opt/codedeploy-agent/vendor/gems/gli-2.11.0/lib/gli/command_support.rb:126:in `execute'
/opt/codedeploy-agent/vendor/gems/gli-2.11.0/lib/gli/app_support.rb:284:in `block in call_command'
/opt/codedeploy-agent/vendor/gems/gli-2.11.0/lib/gli/app_support.rb:297:in `call'
/opt/codedeploy-agent/vendor/gems/gli-2.11.0/lib/gli/app_support.rb:297:in `call_command'
/opt/codedeploy-agent/vendor/gems/gli-2.11.0/lib/gli/app_support.rb:79:in `run'
/opt/codedeploy-agent/bin/../lib/codedeploy-agent.rb:90:in `<main>'
2017-11-29 18:14:44 DEBUG [codedeploy-agent(3901)]: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller: Calling PollHostCommand:
2017-11-29 18:14:44 INFO [codedeploy-agent(3901)]: Version file found in /opt/codedeploy-agent/.version with agent version OFFICIAL_1.0-1.1352_rpm.
In /usr/share/ruby/fileutils.rb:349, we have:
def ln_s(src, dest, options = {})
fu_check_options options, OPT_TABLE['ln_s']
fu_output_message "ln -s#{options[:force] ? 'f' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
return if options[:noop]
fu_each_src_dest0(src, dest) do |s,d|
remove_file d, true if options[:force]
File.symlink s, d
end
end
In /opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/install_instruction.rb:235, we have:
def execute(cleanup_file)
# NO need to check if file already exists in here, because if that's the case,
# the CopyCommand entry should not even be created by Installer
cleanup_file.puts(@destination)
if File.symlink?(@source)
FileUtils.symlink(File.readlink(@source), @destination)
else
FileUtils.copy(@source, @destination, :preserve => true)
end
end
The comments clearly shows that It's not expected to have a CopyCommand here.
I think that this def was written when the option --file-exists-behavior "OVERWRITE" was not yet implemented.
Now that we can use this option, you should add :force => true to the symlink parameter, like this:
def execute(cleanup_file)
# NO need to check if file already exists in here, because if that's the case,
# the CopyCommand entry should not even be created by Installer
cleanup_file.puts(@destination)
if File.symlink?(@source)
FileUtils.symlink(File.readlink(@source), @destination, :force => true)
else
FileUtils.copy(@source, @destination, :preserve => true)
end
end
As a last word, I specify here that the Deployment is a new deploy and application and thus it does not have the "history" of a previous one. That is why I use option --file-exists-behavior "OVERWRITE"
Metadata
Metadata
Assignees
Type
Projects
Status