1 /* Copyright (c) 2019 AT&T Intellectual Property. #
\r
3 # Licensed under the Apache License, Version 2.0 (the "License"); #
\r
4 # you may not use this file except in compliance with the License. #
\r
5 # You may obtain a copy of the License at #
\r
7 # http://www.apache.org/licenses/LICENSE-2.0 #
\r
9 # Unless required by applicable law or agreed to in writing, software #
\r
10 # distributed under the License is distributed on an "AS IS" BASIS, #
\r
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
\r
12 # See the License for the specific language governing permissions and #
\r
13 # limitations under the License. #
\r
14 ##############################################################################*/
\r
17 const logger = require('../../lib/logger');
\r
18 const agenda = require('../agenda').agenda;
\r
19 const emitter = require('../result-emitter').emitter;
\r
20 const utils = require('../../lib/otf-util');
\r
21 const nodeUtil = require('util');
\r
23 const ObjectId = require('mongoose').Types.ObjectId;
\r
25 const TestSchedule = require('../models/test-schedule');
\r
27 const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
\r
29 module.exports = function (app) {
\r
30 let scheduleTestResponse = { status: '', message: '' };
\r
31 let cancelTestResponse = { status: '', message: '' };
\r
33 // Main endpoint for scheduling
\r
34 app.use('/' + app.get('base-path') + 'schedule-test', (req, res, next) => {
\r
35 const authorizationHeader = req.headers.authorization;
\r
37 const testInstanceId = req.body.testInstanceId;
\r
38 const testInstanceStartDate = req.body.testInstanceStartDate;
\r
39 const testInstanceExecFreqInSeconds = req.body.testInstanceExecFreqInSeconds;
\r
40 const testInstanceEndDate = req.body.testInstanceEndDate;
\r
41 const async = req.body.async;
\r
42 const asyncTopic = req.body.asyncTopic;
\r
43 const asyncMode = req.body.asyncMode;
\r
44 const executorId = req.body.executorId;
\r
46 let testSchedule = null;
\r
49 testSchedule = new TestSchedule(testInstanceId, testInstanceStartDate, testInstanceExecFreqInSeconds,
\r
50 testInstanceEndDate, async, asyncTopic, asyncMode, executorId);
\r
52 scheduleTestResponse.status = 400;
\r
53 scheduleTestResponse.message = error.toString();
\r
59 // The presence of this parameter indicates that we will be executing either job definition 2/3.
\r
60 if (testSchedule.testInstanceStartDate) {
\r
61 if (testSchedule.testInstanceExecFreqInSeconds) {
\r
62 const job = agenda.create(
\r
64 { testSchedule, authorizationHeader });
\r
65 job.schedule(testSchedule.testInstanceStartDate).repeatEvery(testSchedule.testInstanceExecFreqInSeconds + ' seconds', {
\r
68 job.save().then(function onJobCreated (result) {
\r
69 logger.debug(JSON.stringify(result));
\r
70 scheduleTestResponse.status = 200;
\r
71 scheduleTestResponse.message = 'Successfully scheduled job.';
\r
74 .catch(function onError (error) {
\r
75 logger.error(error);
\r
76 scheduleTestResponse.status = 500;
\r
77 scheduleTestResponse.message = 'Unable to schedule job.';
\r
80 } else if (!testSchedule.testInstanceExecFreqInSeconds && !testSchedule.testInstanceEndDate) {
\r
82 testSchedule._testInstanceStartDate,
\r
84 { testSchedule, authorizationHeader })
\r
85 .then(function onJobCreated (result) {
\r
86 scheduleTestResponse.status = 200;
\r
87 scheduleTestResponse.message = 'Successfully scheduled job.';
\r
90 .catch(function onError (error) {
\r
91 logger.error('error: ' + error);
\r
92 scheduleTestResponse.status = 500;
\r
93 scheduleTestResponse.message = 'Unable to schedule job.';
\r
97 } else if (testSchedule.testInstanceEndDate && !testSchedule.testInstanceExecFreqInSeconds) {
\r
98 scheduleTestResponse.status = 400;
\r
99 scheduleTestResponse.message = 'Must specify \'testInstanceExecFreqInSeconds\' to use \'testInstanceEndDate\'';
\r
105 if (!testSchedule.testInstanceStartDate &&
\r
106 !testSchedule.testInstanceExecFreqInSeconds &&
\r
107 !testSchedule.testInstanceExecFreqInSeconds) {
\r
110 { testSchedule, authorizationHeader })
\r
111 .then(function onJobCreated (result) {
\r
112 emitter.once(result.attrs._id + '_error', (res) => {
\r
114 scheduleTestResponse.message = res.message;
\r
115 scheduleTestResponse.status = res.statusCode;
\r
119 emitter.once(result.attrs._id + '_ok', (res) => {
\r
121 scheduleTestResponse.message = res;
\r
122 scheduleTestResponse.status = 200;
\r
126 .catch(function onError (err) {
\r
129 if (!Object.keys(scheduleTestResponse).includes('message')) {
\r
130 scheduleTestResponse.message = 'Unknown error.';
\r
133 if (!Object.keys(scheduleTestResponse).includes('status')) {
\r
134 scheduleTestResponse.status = 500;
\r
140 res.status(scheduleTestResponse.status).send(scheduleTestResponse);
\r
141 logger.debug('Sent response with status %d and body %s', scheduleTestResponse.status, scheduleTestResponse.message);
\r
145 app.use('/' + app.get('base-path') + 'cancel-test', (req, res, next) => {
\r
146 // validate the request parameters
\r
147 if (req.body === null) {
\r
148 cancelTestResponse.status = 400;
\r
149 cancelTestResponse.message = 'Request data is invalid.';
\r
155 let requestBody = req.body;
\r
157 if (!requestBody.jobId) {
\r
158 cancelTestResponse.status = 400;
\r
159 cancelTestResponse.message = 'jobId is required.';
\r
165 if (!utils.isValidObjectId(requestBody.jobId)) {
\r
166 cancelTestResponse.status = 400;
\r
167 cancelTestResponse.message = 'jobId must be a valid ObjectId.';
\r
173 if (!requestBody.executorId) {
\r
174 cancelTestResponse.status = 400;
\r
175 cancelTestResponse.message = 'executorId is required.';
\r
181 if (!utils.isValidObjectId(requestBody.executorId)) {
\r
182 cancelTestResponse.status = 400;
\r
183 cancelTestResponse.message = 'executorId must be a valid ObjectId.';
\r
189 const jobId = new ObjectId(requestBody.jobId);
\r
190 const executorId = new ObjectId(requestBody.executorId);
\r
192 agenda.cancel({ _id: jobId, 'data.testSchedule._executorId': executorId })
\r
193 .then(function onJobRemoved (numJobsRemoved) {
\r
194 logger.info('Number of jobs removed: %s', numJobsRemoved);
\r
196 cancelTestResponse.status = 200;
\r
197 cancelTestResponse.message = nodeUtil.format('Successfully removed job with Id %s', jobId);
\r
199 if (numJobsRemoved === 0) {
\r
200 cancelTestResponse.status = 500;
\r
201 cancelTestResponse.message =
\r
202 nodeUtil.format('Unable to find job with Id %s, belonging to user with Id %s.', jobId, executorId);
\r
207 .catch(function onError (error) {
\r
208 logger.error(error.toString());
\r
210 cancelTestResponse.status = 500;
\r
211 cancelTestResponse.message = 'Unable to cancel the job due to an unexpected error.';
\r
217 res.status(cancelTestResponse.status).send(cancelTestResponse);
\r
218 logger.debug('Sent response with status %d and body %s', cancelTestResponse.status, cancelTestResponse.message);
\r