Skip to content

Commit fb1973c

Browse files
committed
Plugin API: Two new APIs: test_monitor_plugin, and test_scheduler_plugin.
- These APIs care called from the Edit Plugin page, and can test monitor/schedule plugins on demand, reporting results back to the client.
1 parent 3d6b2f6 commit fb1973c

1 file changed

Lines changed: 123 additions & 0 deletions

File tree

lib/api/plugins.js

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,129 @@ class Plugins {
172172
} ); // loadSession
173173
}
174174

175+
api_test_monitor_plugin(args, callback) {
176+
// test existing monitor plugin
177+
var self = this;
178+
var params = args.params;
179+
if (!this.requireMaster(args, callback)) return;
180+
181+
if (!this.requireParams(params, {
182+
id: /^\w+$/,
183+
server: /^\w+$/
184+
}, callback)) return;
185+
186+
this.loadSession(args, function(err, session, user) {
187+
if (err) return self.doError('session', err.message, callback);
188+
if (!self.requireValidUser(session, user, callback)) return;
189+
if (!self.requirePrivilege(user, 'edit_plugins', callback)) return;
190+
191+
args.user = user;
192+
args.session = session;
193+
194+
var plugin = Tools.findObject( self.plugins, { id: params.id, type: 'monitor' } );
195+
if (!plugin) return self.doError('api', "Monitor Plugin not found: " + params.id, callback);
196+
197+
var server = self.servers[ params.server ];
198+
if (!server) return self.doError('api', "Server not found: " + params.server, callback);
199+
200+
if (!server.info.features || !server.info.features.testMonitorPlugin) {
201+
return self.doError('api', "Server does not support testing monitor plugins (please upgrade xySat)", callback);
202+
}
203+
204+
self.logDebug(5, "Testing remote monitor plugin", params);
205+
206+
args._xy_remote_timer = setTimeout( function() {
207+
if (!callback) return; // sanity
208+
callback({ code: 0, result: "Error: Remote plugin test has timed out (10 seconds)." });
209+
callback = null;
210+
delete args._xy_remote_timer;
211+
delete args._xy_finish;
212+
}, 10 * 1000 );
213+
214+
args._xy_finish = function(data) {
215+
// called by handleMonitorPluginTestResult in comm.js
216+
if (!callback) return; // sanity
217+
if (args._xy_remote_timer) {
218+
clearTimeout(args._xy_remote_timer);
219+
delete args._xy_remote_timer;
220+
}
221+
callback({ code: 0, ...data });
222+
callback = null;
223+
delete args._xy_finish;
224+
};
225+
226+
self.doServerBroadcast( server.id, 'testMonitorPlugin', { plugin_id: plugin.id, request_id: args.id } );
227+
} ); // loadSession
228+
}
229+
230+
api_test_scheduler_plugin(args, callback) {
231+
// test existing scheduler plugin
232+
var self = this;
233+
var params = args.params;
234+
if (!this.requireMaster(args, callback)) return;
235+
236+
if (!this.requireParams(params, {
237+
id: /^\w+$/
238+
}, callback)) return;
239+
240+
this.loadSession(args, function(err, session, user) {
241+
if (err) return self.doError('session', err.message, callback);
242+
if (!self.requireValidUser(session, user, callback)) return;
243+
if (!self.requirePrivilege(user, 'edit_plugins', callback)) return;
244+
245+
args.user = user;
246+
args.session = session;
247+
248+
var plugin = Tools.findObject( self.plugins, { id: params.id, type: 'scheduler' } );
249+
if (!plugin) return self.doError('api', "Scheduler Plugin not found: " + params.id, callback);
250+
251+
self.logDebug(5, "Testing scheduler plugin", params);
252+
253+
// prep timezone and time stuff
254+
var now = Tools.normalizeTime( params.epoch || Tools.timeNow(true), { sec: 0 } );
255+
var date = new Date( now * 1000 );
256+
var tz = params.timezone || self.config.get('tz') || Intl.DateTimeFormat().resolvedOptions().timeZone;
257+
var days = { Sunday: 0, Monday: 1, Tuesday: 2, Wednesday: 3, Thursday: 4, Friday: 5, Saturday: 6 };
258+
var formatter = new Intl.DateTimeFormat('en-US',
259+
{ year: 'numeric', month: '2-digit', day: 'numeric', weekday: 'long', hour: 'numeric', minute: '2-digit', hourCycle: 'h23', timeZone: tz }
260+
);
261+
262+
var tzargs = {};
263+
formatter.formatToParts(date).forEach( function(part) {
264+
if (part.type == 'literal') return;
265+
if (part.type == 'weekday') tzargs[ part.type ] = days[ part.value ];
266+
else tzargs[ part.type ] = parseInt( part.value );
267+
} );
268+
269+
// include reverse-month-day (rday): -1 is last day of month, -2 is 2nd-to-last day, etc.
270+
tzargs.rday = (tzargs.day - self.getLastDayInMonth( tzargs.year, tzargs.month )) - 1;
271+
272+
// items: [{ plugin_id, params, timezone, dargs, now, job }]
273+
var items = [
274+
{
275+
plugin_id: plugin.id,
276+
params: params.params || {},
277+
timezone: tz,
278+
dargs: tzargs,
279+
now: now,
280+
job: {
281+
id: "1234567890",
282+
label: "Test"
283+
}
284+
}
285+
];
286+
287+
self.execSchedulerPlugin(plugin, items, false, function(resp) {
288+
// massage results for test API
289+
// resp: { code, description? data?, stdout?, stderr?, child_cmd? }
290+
if (resp.code) resp.err = true;
291+
resp.code = 0;
292+
callback(resp);
293+
});
294+
295+
} ); // loadSession
296+
}
297+
175298
api_delete_plugin(args, callback) {
176299
// delete existing plugin
177300
var self = this;

0 commit comments

Comments
 (0)