Skip to content

CodeDeploy agent does not use force option of ruby symlink filetools #143 분석

americanomin edited this page Dec 26, 2018 · 26 revisions

분석 과정

문제 재현

로컬에서 AWS CLI으로 배포하기

aws deploy create-deployment 
--application-name what-is-quality-symbolic-test 
--deployment-config-name CodeDeployDefault.AllAtOnce 
--deployment-group-name what-is-quality-symbolic-test 
--file-exists-behavior OVERWRITE
--description "배포 설명" 
--s3-location bucket=배포할파일버킷위치,bundleType=zip,eTag=배포파일eTag,key=배포파일명

AWS CLI - Deploy Create Deployment

재현 현상

서버에서 Symlink 파일을 직접 생성한 후, 동일한 경로에 Symlink 파일을 만들어서 배포 시도.

OVERWRITE 옵션 영향범위 테스트 케이스

depth 1 depth 2 condition 변경전 변경후
appspec > source 하위 폴더 안에 Symlink 파일/폴더가 있는 경우 파일 Symlink인 경우 source 파일이 Symlink이고, destination에 같은 이름의 일반 파일 / Symlink 파일이 있는 경우 오류남 정상처리
폴더 Symlink인 경우 source 폴더가 Symlink이고, destination에 같은 이름의 일반 폴더가 있는 경우 오류안남. 하지만 Symlink 복사안됨 정상처리
source 폴더가 Symlink이고, destination에 같은 이름의 Symlink 폴더가 있는 경우 오류남 정상처리
source 폴더가 Symlink이고, destination에 같은 이름의 일반 파일이 있는 경우 오류남 정상처리
appspec > source가 Symlink인 경우 파일 Symlink인 경우 - 오류남 정상처리
폴더 Symlink인 경우 - 오류남 정상처리

요약

  • Symlink 함수에 force 옵션을 추가해도 아래와 같은 오류가 여전히 발생한다.
    • Symlink 폴더를 배포할 때, 동일 경로에 일반 폴더가 서버에 존재하는 경우
      • 오류가 나지는 않으나, destination 폴더 안에 symlink 파일이 복사된다.
      • OVERWRITE된 폴더를 삭제하여, 재배포를 해도 해당 폴더가 삭제되지 않는다. ( 재배포를 할때 clean-up 대상에서 제외됨 )
        • 이유
          • 기존 폴더를 symlink 파일로 덮어쓰려고 하니, 폴더 하위에 symlink 파일이 생겼는데,
          • 이건 cleanup 파일에 추가된 파일이 아니여서, RemoveCommand에서 제외된거였음

에러 로그

source 파일이 Symlink이고, destination에 같은 이름의 일반 파일 / Symlink 파일이 있는 경우

2018-12-15 15:43:59 ERROR [codedeploy-agent(2824)]: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller: Error during perform: Errno::EEXIST - File exists @ syserr_fail2_in - /tmp/apps/app/symlink-file.txt - /usr/lib/ruby/2.3.0/fileutils.rb:358:in `symlink'
/usr/lib/ruby/2.3.0/fileutils.rb:358:in `block in ln_s'
/usr/lib/ruby/2.3.0/fileutils.rb:1587:in `fu_each_src_dest0'
/usr/lib/ruby/2.3.0/fileutils.rb:356:in `ln_s'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/install_instruction.rb:236: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:114:in `process_command'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/command_poller.rb:96:in `acknowledge_and_process_command'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/command_poller.rb:75:in `block in perform'
/opt/codedeploy-agent/vendor/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:348:in `run_task'
/opt/codedeploy-agent/vendor/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:337:in `block (3 levels) in create_worker'
/opt/codedeploy-agent/vendor/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `loop'
/opt/codedeploy-agent/vendor/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `block (2 levels) in create_worker'
/opt/codedeploy-agent/vendor/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `catch'
/opt/codedeploy-agent/vendor/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `block in create_worker'
/opt/codedeploy-agent/vendor/gems/logging-1.8.2/lib/logging/diagnostic_context.rb:323:in `block in create_with_logging_context'
2018-12-15 15:43:59 WARN  [codedeploy-agent(2824)]: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller: Calling PutHostCommandComplete: "Code Error" 

source 폴더가 Symlink이고, destination에 같은 이름의 Symlink 폴더가 있는 경우

source 폴더가 Symlink이고, destination에 같은 이름의 일반 파일이 있는 경우

2018-12-18 12:17:48 ERROR [codedeploy-agent(2824)]: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller: Error during perform: Errno::EEXIST - File exists @ dir_s_mkdir - /tmp/apps/app/181218-sym-folder - /usr/lib/ruby/2.3.0/fileutils.rb:253:in `mkdir'
/usr/lib/ruby/2.3.0/fileutils.rb:253:in `fu_mkdir'
/usr/lib/ruby/2.3.0/fileutils.rb:182:in `block in mkdir'
/usr/lib/ruby/2.3.0/fileutils.rb:181:in `each'
/usr/lib/ruby/2.3.0/fileutils.rb:181:in `mkdir'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/install_instruction.rb:255: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:114:in `process_command'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/command_poller.rb:96:in `acknowledge_and_process_command'
/opt/codedeploy-agent/lib/instance_agent/plugins/codedeploy/command_poller.rb:75:in `block in perform'
/opt/codedeploy-agent/vendor/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:348:in `run_task'
/opt/codedeploy-agent/vendor/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:337:in `block (3 levels) in create_worker'
/opt/codedeploy-agent/vendor/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `loop'
/opt/codedeploy-agent/vendor/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `block (2 levels) in create_worker'
/opt/codedeploy-agent/vendor/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `catch'
/opt/codedeploy-agent/vendor/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `block in create_worker'
/opt/codedeploy-agent/vendor/gems/logging-1.8.2/lib/logging/diagnostic_context.rb:323:in `block in create_with_logging_context'
2018-12-18 12:17:48 WARN  [codedeploy-agent(2824)]: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller: Calling PutHostCommandComplete: "Code Error"
2018-12-18 12:17:48 INFO  [codedeploy-agent(2824)]: Version file found in /opt/codedeploy-agent/.version with agent version OFFICIAL_1.0-1.1597_deb.

해결방법

symlink 파일을 복사할 때, destination 경로에 동일한 이름의 폴더가 있는 경우, FileUtils.symlink 함수에 force=>true옵션을 추가해도 symlink가 정상적으로 복사되지 않는다. 그래서 CopyCommand의 execute 함수를 호출하기 전에, OverWrite 옵션을 줬는데 동일한 경로에 파일/폴더가 있는 경우 명시적으로 삭제해주도록 처리.

Clone this wiki locally