def serve_build(self): """This is the main function of the ``DeployAgent``. """ log.info('The deploy agent is starting.') if not self._executor: self._executor = Executor(callback=PingServer(self), config=self._config) # start to ping server to get the latest deploy goal response = self._client.send_reports(self._envs) self._response = response if self._response: report = self._update_internal_deploy_goal(self._response) # failed to update if report.status_code != AgentStatus.SUCCEEDED: self._update_ping_reports(deploy_report=report) self._client.send_reports(self._envs) return while self._response and self._response.opCode and self._response.opCode != OpCode.NOOP: try: # update the current deploy goal if self._response.deployGoal: deploy_report = self.process_deploy(self._response) else: log.info('No new deploy goal to get updated') deploy_report = DeployReport(AgentStatus.SUCCEEDED) if deploy_report.status_code == AgentStatus.ABORTED_BY_SERVER: log.info('switch to the new deploy goal: {}'.format( self._response.deployGoal)) continue except Exception: # anything catch-up here should be treated as agent failure deploy_report = DeployReport( status_code=AgentStatus.AGENT_FAILED, error_code=1, output_msg=traceback.format_exc(), retry_times=1) self.update_deploy_status(deploy_report) if deploy_report.status_code in [ AgentStatus.AGENT_FAILED, AgentStatus.TOO_MANY_RETRY, AgentStatus.SCRIPT_TIMEOUT ]: log.error('Unexpeted exceptions: {}, error message {}'.format( deploy_report.status_code, deploy_report.output_msg)) return self.clean_stale_builds() if self._response and self._response.deployGoal: self._update_internal_deploy_goal(self._response) if self._response: log.info('Complete the current deploy with response: {}.'.format( self._response)) else: log.info('Failed to get response from server, exit.')
def test_run_command_with_timeout(self): cmd = ['ls', '-ltr', '/abc'] ping_server = mock.Mock(return_value=True) executor = Executor(callback=ping_server) executor.LOG_FILENAME = self.fdout_fn executor.MAX_RUNNING_TIME = 4 executor.MIN_RUNNING_TIME = 2 executor.DEFAULT_TAIL_LINES = 1 executor.MAX_RETRY = 3 executor.PROCESS_POLL_INTERVAL = 2 executor.MAX_TAIL_BYTES = 10240 deploy_report = executor.run_cmd(cmd=cmd) self.assertEqual(deploy_report.status_code, AgentStatus.ABORTED_BY_SERVER)
def test_run_command_with_timeout_error(self): cmd = ['sleep', '20'] ping_server = mock.Mock(return_value=False) executor = Executor(callback=ping_server) executor.LOG_FILENAME = self.fdout_fn executor.MAX_RUNNING_TIME = 4 executor.MIN_RUNNING_TIME = 2 executor.DEFAULT_TAIL_LINES = 1 executor.MAX_RETRY = 3 executor.PROCESS_POLL_INTERVAL = 2 executor.BACK_OFF = 2 executor.MAX_SLEEP_INTERVAL = 60 executor.MAX_TAIL_BYTES = 10240 deploy_report = executor.run_cmd(cmd=cmd) self.assertTrue(ping_server.called) self.assertEqual(deploy_report.status_code, AgentStatus.SCRIPT_TIMEOUT)
def test_run_command_with_max_retry(self): cmd = ['ls', '-ltr', '/abc'] ping_server = mock.Mock(return_value=False) executor = Executor(callback=ping_server) executor.LOG_FILENAME = self.fdout_fn executor.MAX_RUNNING_TIME = 5 executor.MIN_RUNNING_TIME = 2 executor.MAX_RETRY = 3 executor.DEFAULT_TAIL_LINES = 1 executor.PROCESS_POLL_INTERVAL = 2 executor.BACK_OFF = 2 executor.MAX_SLEEP_INTERVAL = 60 executor.MAX_TAIL_BYTES = 10240 deploy_report = executor.run_cmd(cmd=cmd) self.assertEqual(deploy_report.status_code, AgentStatus.TOO_MANY_RETRY) # in ubuntu: error message is 'ls: cannot access /abc: No such file or directory' # in mac osx: error message is 'ls: /abc: No such file or directory' self.assertEqual(deploy_report.retry_times, 3)
def test_run_bad_script(self): fdout_fn = tempfile.mkstemp()[1] with open(fdout_fn, 'w') as f: f.write('echo hello') os.chmod(fdout_fn, 0755) ping_server = mock.Mock(return_value=True) executor = Executor(callback=ping_server) executor.LOG_FILENAME = self.fdout_fn executor.MAX_RUNNING_TIME = 4 executor.MIN_RUNNING_TIME = 2 executor.DEFAULT_TAIL_LINES = 1 executor.PROCESS_POLL_INTERVAL = 2 executor.MAX_RETRY = 3 deploy_report = executor.run_cmd(cmd=fdout_fn) self.assertTrue(ping_server.called) self.assertEqual(deploy_report.status_code, AgentStatus.ABORTED_BY_SERVER) os.remove(fdout_fn)
def setUpClass(cls): cls.fdout, cls.fdout_fn = tempfile.mkstemp() cls.pingServer = mock.Mock() cls.pingServer.__call__ = mock.Mock(return_value=False) cls.executor = Executor(callback=cls.pingServer) cls.executor.LOG_FILENAME = cls.fdout_fn