def assertTimeCloseToCurrent( self, time, msg='Creation time is more than 3 seconds adrift'): if (isinstance(time, str)): time = from_iso8601(time) curTime = datetime.datetime.now(pytz.timezone("UTC")) time_diff = (curTime - time).total_seconds() self.assertTrue(time_diff < 3, msg=msg)
def test_jobExecutionFillsInJobLastRunDateAndReturnCode(self): result = self.testClient.post( '/api/jobs/', data=json.dumps(data_simpleManualJobCreateParams), content_type='application/json') self.assertEqual(result.status_code, 200) resultJSON = json.loads(result.get_data(as_text=True)) jobGUID = resultJSON['guid'] resultJSON2 = self.addExecution(jobGUID, 'TestExecutionName') executionGUID = resultJSON2['guid'] appObj.jobExecutor.loopIteration( datetime.datetime(2016, 1, 5, 14, 3, 55, 0, pytz.timezone('UTC'))) # Check Job info queryJobResult = self.testClient.get('/api/jobs/' + jobGUID) self.assertEqual(queryJobResult.status_code, 200) queryJobResultJSON = json.loads(queryJobResult.get_data(as_text=True)) self.assertNotEqual(queryJobResultJSON['lastRunDate'], None, msg='last Run Date not set against job') tim = from_iso8601(queryJobResultJSON['lastRunDate']) self.assertTimeCloseToCurrent(tim, msg='last Run date not recently set') self.assertEqual(queryJobResultJSON['lastRunReturnCode'], 0, msg='last Run return code not sucess') self.assertEqual(queryJobResultJSON['lastRunExecutionGUID'], executionGUID, msg='last run Execution GUID not correct')
def test_Create(self): jobObj = self.createJobObj() a = self._getJobExecutionObj(jobObj) tim = from_iso8601(a.dateCreated) self.assertTimeCloseToCurrent(tim) self.assertEqual(a.stage, 'Pending') self.assertEqual(a.jobGUID, jobObj.guid) self.assertEqual(a.jobCommand, jobObj.command)
def loopIteration(self, curDatetime): #Run next pending job only the next one, other jobs are run on subsequent loop iterations # this will block this thread until the execution is complete if not self.pendingExecutions.empty(): executionGUID = self.pendingExecutions.get() jobExecutionObj = None try: jobExecutionObj = self.JobExecutions[executionGUID] except KeyError: jobExecutionObj = None # if we get a key error it just means this job was deleted while it had a pending execution if jobExecutionObj is not None: print(curDatetime.isoformat() + ' Executing (Execution name = ' + jobExecutionObj.executionName + ')') jobExecutionObj.execute( self.appObj.jobExecutor, self.aquireJobExecutionLock, self.releaseJobExecutionLock, self.appObj.appData['jobsData'].registerRunDetails, self.appObj #Passing in so execution time stamps are simulated in testing ) #schedule any new jobs that are due to be automatically run # no lock acquire required here as it is inside submitJobForExecution nextJob = self.appObj.appData['jobsData'].getNextJobToExecute() if nextJob is not None: if curDatetime.isoformat() > nextJob.nextScheduledRun: # print('Submitting job ' + nextJob.name + ' for scheduled execution') self.submitJobForExecution(nextJob.guid, '', False) nextJob.setNextScheduledRun(curDatetime) self.appObj.appData['jobsData'].nextJobToExecuteCalcRequired = True #purge old runs from list timeToPurgeBefore = curDatetime - datetime.timedelta(days=7) toPurge = queue.Queue() try: self.aquireJobExecutionLock() for curJobExecution in self.JobExecutions: if self.JobExecutions[curJobExecution].dateCompleted is not None: try: tim = from_iso8601(self.JobExecutions[curJobExecution].dateCompleted) except: print('Error converting dateCompleted value: ' + self.JobExecutions[curJobExecution].dateCompleted) print('Job execution: ' + self.JobExecutions[curJobExecution].guid) raise if tim < timeToPurgeBefore: print('Purging Execution ' + self.JobExecutions[curJobExecution].executionName) print(' - date completed ' + self.JobExecutions[curJobExecution].dateCompleted) print(' - time to purge before (7 days before current) ' + str(timeToPurgeBefore)) toPurge.put(curJobExecution) while not toPurge.empty(): toDel = toPurge.get() self.JobExecutions.pop(toDel) finally: self.JobExecutionLock.release() self.appObj.appData['jobsData'].loopIteration(self.appObj, curDatetime)
def test_dictOut(self): jobObj = self.createJobObj() expPending = { 'guid': 'OVERRIDE', 'stage': 'Pending', 'jobGUID': jobObj.guid, 'jobName': jobObj.name, 'jobCommand': jobObj.command, 'dateCreated': 'OVERRIDE', 'dateStarted': None, 'dateCompleted': None, 'resultReturnCode': None, 'resultSTDOUT': None, 'executionName': 'TestExecutionName', 'manual': False } expCompleted = dict(expPending) expCompleted['resultSTDOUT'] = 'This is a test' expCompleted['stage'] = 'Completed' expCompleted['dateStarted'] = 'OVERRIDE' expCompleted['dateCompleted'] = 'OVERRIDE' expCompleted['resultReturnCode'] = 0 a = self._getJobExecutionObj(jobObj) resDict = dict(a._caculatedDict()) tim = from_iso8601(a.dateCreated) resDict['dateCreated'] = 'OVERRIDE' resDict['guid'] = 'OVERRIDE' self.assertJSONStringsEqual(resDict, expPending) a.execute(appObj.jobExecutor, self.aquireJobExecutionLock, self.releaseJobExecutionLock, self.registerRunDetails, appObj) self.assertEqual(a.stage, 'Completed') resDict = dict(a._caculatedDict()) resDict['dateCreated'] = 'OVERRIDE' resDict['dateStarted'] = 'OVERRIDE' resDict['dateCompleted'] = 'OVERRIDE' resDict['guid'] = 'OVERRIDE' tim = from_iso8601(a.dateStarted) self.assertTimeCloseToCurrent(tim) tim = from_iso8601(a.dateCompleted) self.assertTimeCloseToCurrent(tim) self.assertJSONStringsEqual(resDict, expCompleted)
def test_JobCreate(self): result = self.testClient.post( '/api/jobs/', data=json.dumps(data_simpleJobCreateParams), content_type='application/json') self.assertEqual(result.status_code, 200) resultJSON = json.loads(result.get_data(as_text=True)) self.assertEqual(len(resultJSON['guid']), 36, msg='Invalid GUID - must be 36 chars') self.assertEqual(resultJSON['creationDate'], resultJSON['lastUpdateDate'], msg='Creation date dosen' 't match last update') tim = from_iso8601(resultJSON['creationDate']) self.assertTimeCloseToCurrent(tim) self.assertJSONJobStringsEqual(resultJSON, data_simpleJobCreateExpRes) self.assertCorrectTotalJobs(1)
def test_oldRunLogsArePurgedAfter1Week(self): #This will add a job, manually run it check it has a execution log then run loop iteration after purge interval later and then recheck execution log to make sure it has gone result = self.testClient.post( '/api/jobs/', data=json.dumps(data_simpleManualJobCreateParams), content_type='application/json') self.assertEqual(result.status_code, 200, msg='Wrong status ' + str(result)) resultJSON = json.loads(result.get_data(as_text=True)) jobGUID = resultJSON['guid'] resultJSON2 = self.addExecution(jobGUID, 'TestExecutionName') appObj.jobExecutor.loopIteration( datetime.datetime(2016, 1, 5, 14, 3, 59, 0, pytz.timezone('UTC'))) # Check we have an execution log queryJobExecutionsResult = self.testClient.get('/api/jobs/' + jobGUID + '/execution') self.assertEqual(queryJobExecutionsResult.status_code, 200) queryJobExecutionsResultJSON = json.loads( queryJobExecutionsResult.get_data(as_text=True)) self.assertEqual(queryJobExecutionsResultJSON['pagination']['total'], 1, msg='Didn' 't find execution for job') self.assertEqual(queryJobExecutionsResultJSON["result"][0]['stage'], 'Completed', msg='Job not completed') self.assertNotEqual( queryJobExecutionsResultJSON["result"][0]['dateCompleted'], None, msg='Job execution didn' 't complete') dateCompleted = from_iso8601( queryJobExecutionsResultJSON["result"][0]['dateCompleted']) self.assertEqual(str(dateCompleted.tzinfo), 'tzutc()', msg='date completed not returned in UTC') # Test we still have execution in one days time (from date completed) timeToTest = dateCompleted + datetime.timedelta(days=1) appObj.jobExecutor.loopIteration(timeToTest) queryJobExecutionsResult = self.testClient.get('/api/jobs/' + jobGUID + '/execution') self.assertEqual(queryJobExecutionsResult.status_code, 200) queryJobExecutionsResultJSON = json.loads( queryJobExecutionsResult.get_data(as_text=True)) self.assertEqual(queryJobExecutionsResultJSON['pagination']['total'], 1, msg='Didn' 't find execution for job') self.assertEqual(queryJobExecutionsResultJSON["result"][0]['stage'], 'Completed', msg='Job not completed') self.assertNotEqual( queryJobExecutionsResultJSON["result"][0]['dateCompleted'], None, msg='Job execution didn' 't complete') # Test we do not have execution in eight days time timeToTest = dateCompleted + datetime.timedelta(days=8) appObj.jobExecutor.loopIteration(timeToTest) queryJobExecutionsResult = self.testClient.get('/api/jobs/' + jobGUID + '/execution') self.assertEqual(queryJobExecutionsResult.status_code, 200) queryJobExecutionsResultJSON = json.loads( queryJobExecutionsResult.get_data(as_text=True)) self.assertEqual(queryJobExecutionsResultJSON['pagination']['total'], 0, msg='Found execution but it should have been purged')