class InstanceAgent::Plugins::CodeDeployPlugin::HookExecutor
Constants
- CURRENT
- LAST_SUCCESSFUL_DEPLOYMENT
Public Class Methods
new(arguments = {})
click to toggle source
# File lib/instance_agent/plugins/codedeploy/hook_executor.rb, line 64 def initialize(arguments = {}) #check arguments raise "Lifecycle Event Required " if arguments[:lifecycle_event].nil? raise "Deployment ID required " if arguments[:deployment_id].nil? raise "Deployment Root Directory Required " if arguments[:deployment_root_dir].nil? raise "App Spec Path Required " if arguments[:app_spec_path].nil? raise "Application name required" if arguments[:application_name].nil? raise "Deployment Group name required" if arguments[:deployment_group_name].nil? @lifecycle_event = arguments[:lifecycle_event] @deployment_id = arguments[:deployment_id] @application_name = arguments[:application_name] @deployment_group_name = arguments[:deployment_group_name] @deployment_group_id = arguments[:deployment_group_id] @current_deployment_root_dir = arguments[:deployment_root_dir] select_correct_deployment_root_dir(arguments[:deployment_root_dir], arguments[:last_successful_deployment_dir]) return if @deployment_root_dir.nil? @deployment_archive_dir = File.join(@deployment_root_dir, 'deployment-archive') @app_spec_path = arguments[:app_spec_path] parse_app_spec @hook_logging_mutex = Mutex.new @script_log = ScriptLog.new @child_envs={'LIFECYCLE_EVENT' => @lifecycle_event.to_s, 'DEPLOYMENT_ID' => @deployment_id.to_s, 'APPLICATION_NAME' => @application_name, 'DEPLOYMENT_GROUP_NAME' => @deployment_group_name, 'DEPLOYMENT_GROUP_ID' => @deployment_group_id} end
Public Instance Methods
execute()
click to toggle source
# File lib/instance_agent/plugins/codedeploy/hook_executor.rb, line 92 def execute return if @app_spec.nil? if (hooks = @app_spec.hooks[@lifecycle_event]) && !hooks.empty? create_script_log_file_if_needed do |script_log_file| log_script("LifecycleEvent - " + @lifecycle_event + "\n", script_log_file) hooks.each do |script| if(!File.exist?(script_absolute_path(script))) raise ScriptError.new(ScriptError::SCRIPT_MISSING_CODE, script.location, @script_log), 'Script does not exist at specified location: ' + File.expand_path(script_absolute_path(script)) elsif(!InstanceAgent::Platform.util.script_executable?(script_absolute_path(script))) log :warn, 'Script at specified location: ' + script.location + ' is not executable. Trying to make it executable.' begin FileUtils.chmod("+x", script_absolute_path(script)) rescue raise ScriptError.new(ScriptError::SCRIPT_EXECUTABILITY_CODE, script.location, @script_log), 'Unable to set script at specified location: ' + script.location + ' as executable' end end begin execute_script(script, script_log_file) rescue Timeout::Error raise ScriptError.new(ScriptError::SCRIPT_TIMED_OUT_CODE, script.location, @script_log), 'Script at specified location: ' +script.location + ' failed to complete in '+script.timeout.to_s+' seconds' end end end end @script_log.log end
Private Instance Methods
create_script_log_file_if_needed() { |script_log_file| ... }
click to toggle source
# File lib/instance_agent/plugins/codedeploy/hook_executor.rb, line 158 def create_script_log_file_if_needed script_log_file_location = File.join(@current_deployment_root_dir, 'logs/scripts.log') if(!File.exists?(script_log_file_location)) unless File.directory?(File.dirname(script_log_file_location)) FileUtils.mkdir_p(File.dirname(script_log_file_location)) end script_log_file = File.open(script_log_file_location, 'w') else script_log_file = File.open(script_log_file_location, 'a') end yield(script_log_file) ensure script_log_file.close unless script_log_file.nil? end
description()
click to toggle source
# File lib/instance_agent/plugins/codedeploy/hook_executor.rb, line 208 def description self.class.to_s end
execute_script(script, script_log_file)
click to toggle source
# File lib/instance_agent/plugins/codedeploy/hook_executor.rb, line 121 def execute_script(script, script_log_file) script_command = InstanceAgent::Platform.util.prepare_script_command(script, script_absolute_path(script)) log_script("Script - " + script.location + "\n", script_log_file) exit_status = 1 signal = nil if !InstanceAgent::Platform.util.supports_process_groups? # The Windows port doesn't emulate process groups so don't try to use them here open3_options = {} signal = 'KILL' #It is up to the script to handle killing child processes it spawns. else open3_options = {:pgroup => true} signal = '-TERM' #kill the process group instead of pid end Open3.popen3(@child_envs, script_command, open3_options) do |stdin, stdout, stderr, wait_thr| stdin.close stdout_thread = Thread.new{stdout.each_line { |line| log_script("[stdout]" + line.to_s, script_log_file)}} stderr_thread = Thread.new{stderr.each_line { |line| log_script("[stderr]" + line.to_s, script_log_file)}} if !wait_thr.join(script.timeout) Process.kill(signal, wait_thr.pid) raise Timeout::Error end stdout_thread.join stderr_thread.join exit_status = wait_thr.value.exitstatus end if(exit_status != 0) script_error = 'Script at specified location: ' + script.location + ' failed with exit code ' + exit_status.to_s if(!script.runas.nil?) script_error = 'Script at specified location: ' + script.location + ' run as user ' + script.runas + ' failed with exit code ' + exit_status.to_s end raise ScriptError.new(ScriptError::SCRIPT_FAILED_CODE, script.location, @script_log), script_error end end
log(severity, message)
click to toggle source
# File lib/instance_agent/plugins/codedeploy/hook_executor.rb, line 213 def log(severity, message) raise ArgumentError, "Unknown severity #{severity.inspect}" unless InstanceAgent::Log::SEVERITIES.include?(severity.to_s) InstanceAgent::Log.send(severity.to_sym, "#{description}: #{message}") end
log_script(message, script_log_file)
click to toggle source
# File lib/instance_agent/plugins/codedeploy/hook_executor.rb, line 219 def log_script(message, script_log_file) @hook_logging_mutex.synchronize do @script_log.append_to_log(message) script_log_file.write(Time.now.to_s[0..-7] + ' ' + message) InstanceAgent::DeploymentLog.instance.log("[#{@deployment_id}]#{message.strip}") if InstanceAgent::Config.config[:enable_deployments_log] script_log_file.flush end end
mapping_between_hooks_and_deployments()
click to toggle source
# File lib/instance_agent/plugins/codedeploy/hook_executor.rb, line 195 def mapping_between_hooks_and_deployments {"BeforeELBRemove"=>LAST_SUCCESSFUL_DEPLOYMENT, "AfterELBRemove"=>LAST_SUCCESSFUL_DEPLOYMENT, "ApplicationStop"=>LAST_SUCCESSFUL_DEPLOYMENT, "BeforeInstall"=>CURRENT, "AfterInstall"=>CURRENT, "ApplicationStart"=>CURRENT, "BeforeELBAdd"=>CURRENT, "AfterELBAdd"=>CURRENT, "ValidateService"=>CURRENT} end
parse_app_spec()
click to toggle source
# File lib/instance_agent/plugins/codedeploy/hook_executor.rb, line 179 def parse_app_spec app_spec_location = File.join(@deployment_archive_dir, @app_spec_path) log(:debug, "Checking for app spec in #{app_spec_location}") @app_spec = ApplicationSpecification::ApplicationSpecification.parse(File.read(app_spec_location)) end
script_absolute_path(script)
click to toggle source
# File lib/instance_agent/plugins/codedeploy/hook_executor.rb, line 174 def script_absolute_path(script) File.join(@deployment_archive_dir, script.location) end
select_correct_deployment_root_dir(current_deployment_root_dir, last_successful_deployment_root_dir)
click to toggle source
# File lib/instance_agent/plugins/codedeploy/hook_executor.rb, line 186 def select_correct_deployment_root_dir(current_deployment_root_dir, last_successful_deployment_root_dir) @deployment_root_dir = current_deployment_root_dir hook_deployment_mapping = mapping_between_hooks_and_deployments if(hook_deployment_mapping[@lifecycle_event] == LAST_SUCCESSFUL_DEPLOYMENT && !File.exist?(File.join(@deployment_root_dir, 'deployment-archive'))) @deployment_root_dir = last_successful_deployment_root_dir end end