Permalink
Browse files

feat(alarms): implement ticket create/update/close

  • Loading branch information...
RangerRick committed Jul 26, 2017
1 parent cbf422e commit 93ff386a986f029c08e88d682064177df6e8d99c
Showing with 188 additions and 29 deletions.
  1. +37 −29 src/CLI.ts
  2. +75 −0 src/dao/AlarmDAO.ts
  3. +27 −0 test/dao/AlarmDAO.spec.ts
  4. +19 −0 test/rest/MockHTTP19.ts
  5. +30 −0 test/rest/MockHTTP21.ts
View
@@ -11,7 +11,7 @@ import {
} from 'typescript-logging';
/** @hidden */
function CLI() {
const CLI = () => {
const catCLI = new Category('cli', catRoot);
// tslint:disable
@@ -25,7 +25,7 @@ function CLI() {
const homedir = process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
const defaultConfigFile = path.join(homedir, '.opennms-cli.config.json');
function readConfig() {
const readConfig = () => {
const configfile = program.config || defaultConfigFile;
let config;
if (fs.existsSync(configfile)) {
@@ -38,7 +38,24 @@ function CLI() {
};
}
return config;
}
};
const handleError = (message, err) => {
let realError: any = new Error(message);
if (err instanceof API.OnmsResult) {
realError = new API.OnmsError(message + ': ' + err.message, err.code);
} else if (err.message) {
realError = new API.OnmsError(message + ': ' + err.message);
} else if (Object.prototype.toString.call(err) === '[object String]') {
realError = new API.OnmsError(message + ': ' + err);
}
if (program.debug) {
log.error(realError.message, realError, catCLI);
} else {
log.error(realError.message, undefined, catCLI);
}
return realError;
};
/* tslint:disable:no-console */
@@ -81,11 +98,7 @@ function CLI() {
}
return true;
}).catch((err) => {
if (program.debug) {
log.error('Connection failed: ' + err.message, err, catCLI);
} else {
log.error('Connection failed: ' + err.message, undefined, catCLI);
}
return handleError('Server check failed', err);
});
});
@@ -121,11 +134,7 @@ function CLI() {
return res;
}).catch((err) => {
if (program.debug) {
log.error('Capabilities check failed: ' + err.message, err, catCLI);
} else {
log.error('Capabilities check failed: ' + err.message, undefined, catCLI);
}
return handleError('Capabilities check failed', err);
});
});
@@ -216,12 +225,9 @@ function CLI() {
return dao.find(filter).then((alarms) => {
const headers = ['id', 'severity', 'node', 'count', 'time', 'log'];
console.log(cliff.stringifyObjectRows(formatAlarms(alarms), headers, ['red']));
}).catch((err) => {
if (err.stack) {
log.error(err.stack, err, catCLI);
}
return err;
});
}).catch((err) => {
return handleError('Alarm list failed', err);
});
});
@@ -232,18 +238,15 @@ function CLI() {
}
p.description(description);
p.action((id) => {
id = parseInt(id, 10);
const config = readConfig();
return new Client().connect('OpenNMS', config.url, config.username, config.password).then((client) => {
return client.alarms()[name](id).then(() => {
console.log('Success!');
return true;
});
}).catch((err) => {
if (program.debug) {
log.error(name + ' failed: ' + err.message, err, catCLI);
} else {
log.error(name + ' failed: ' + err.message, undefined, catCLI);
}
return handleError(name + ' failed', err);
});
});
};
@@ -255,30 +258,35 @@ function CLI() {
.description('Acknowledge an alarm')
.option('-u, --user <user>', 'Which user to acknowledge as (only administrators can do this)')
.action((id, options) => {
id = parseInt(id, 10);
const config = readConfig();
return new Client().connect('OpenNMS', config.url, config.username, config.password).then((client) => {
return client.alarms().acknowledge(id, options.user).then(() => {
console.log('Success!');
return true;
});
}).catch((err) => {
if (program.debug) {
log.error('Acknowledge failed: ' + err.message, err, catCLI);
} else {
log.error('Acknowledge failed: ' + err.message, undefined, catCLI);
}
return handleError('Acknowledge failed', err);
});
});
createAlarmAction('unacknowledge', 'Unacknowledge an alarm', 'unack');
createAlarmAction('escalate', 'Escalate an alarm');
createAlarmAction('clear', 'Clear an alarm');
createAlarmAction('createTicket', 'Create a trouble ticket for an alarm', 'create');
createAlarmAction('triggerTicketUpdate', 'Trigger a trouble ticket update for an alarm', 'update');
createAlarmAction('closeTicket', 'Close a trouble ticket for an alarm', 'close');
program.parse(process.argv);
if (!process.argv.slice(2).length) {
program.outputHelp();
}
}
};
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});
CLI();
View
@@ -169,6 +169,81 @@ export class AlarmDAO extends AbstractDAO<number, OnmsAlarm> {
return this.put(this.pathToAlarmsEndpoint() + '/' + alarmId, parameters);
}
/**
* Create a trouble ticket for the specified alarm.
*
* @version ReST v2
* @param {number|OnmsAlarm} alarm - The [[OnmsAlarm]] or alarm ID.
*/
public async createTicket(alarm: number|OnmsAlarm): Promise<void> {
if (this.getApiVersion() === 1) {
throw new OnmsError('Create/Update/Close ticket is only available in OpenNMS ' +
'versions that support the ReSTv2 API.');
}
const alarmId = (typeof(alarm) === 'number' ? alarm : alarm.id);
const options = new OnmsHTTPOptions();
options.headers.accept = 'text/plain';
return this.http.post(this.pathToAlarmsEndpoint() + '/' + alarmId + '/ticket/create', options).then(() => {
log.debug('Ticket creation pending.', cat);
}).catch((err: OnmsResult<OnmsAlarm>) => {
if (err.code === 501) {
log.warn('Trouble ticketing is not enabled on ' + this.http.server.toString());
}
throw err;
});
}
/**
* Notify OpenNMS it should fetch updated ticket state for an alarm from the remote ticketing system.
*
* @version ReST v2
* @param {number|OnmsAlarm} alarm - The [[OnmsAlarm]] or alarm ID.
*/
public async triggerTicketUpdate(alarm: number|OnmsAlarm): Promise<void> {
if (this.getApiVersion() === 1) {
throw new OnmsError('Create/Update/Close ticket is only available in OpenNMS ' +
'versions that support the ReSTv2 API.');
}
const alarmId = (typeof(alarm) === 'number' ? alarm : alarm.id);
const options = new OnmsHTTPOptions();
options.headers.accept = 'text/plain';
return this.http.post(this.pathToAlarmsEndpoint() + '/' + alarmId + '/ticket/update', options).then(() => {
log.debug('Ticket update pending.', cat);
}).catch((err: OnmsResult<OnmsAlarm>) => {
if (err.code === 501) {
log.warn('Trouble ticketing is not enabled on ' + this.http.server.toString());
}
throw err;
});
}
/**
* Close the ticket associated with the given alarm.
*
* @version ReST v2
* @param {number|OnmsAlarm} alarm - The [[OnmsAlarm]] or alarm ID.
*/
public async closeTicket(alarm: number|OnmsAlarm): Promise<void> {
if (this.getApiVersion() === 1) {
throw new OnmsError('Create/Update/Close ticket is only available in OpenNMS ' +
'versions that support the ReSTv2 API.');
}
const alarmId = (typeof(alarm) === 'number' ? alarm : alarm.id);
const options = new OnmsHTTPOptions();
options.headers.accept = 'text/plain';
return this.http.post(this.pathToAlarmsEndpoint() + '/' + alarmId + '/ticket/close', options).then(() => {
log.debug('Ticket close pending.', cat);
}).catch((err: OnmsResult<OnmsAlarm>) => {
if (err.code === 501) {
log.warn('Trouble ticketing is not enabled on ' + this.http.server.toString());
}
throw err;
});
}
/**
* Generate an alarm object from the given dictionary.
* @hidden
View
@@ -7,6 +7,7 @@ import {Client} from '../../src/Client';
import {OnmsAuthConfig} from '../../src/api/OnmsAuthConfig';
import {OnmsServer} from '../../src/api/OnmsServer';
import {OnmsResult} from '../../src/api/OnmsResult';
import {Comparators} from '../../src/api/Comparator';
import {Filter} from '../../src/api/Filter';
@@ -79,6 +80,16 @@ describe('AlarmDAO with v1 API', () => {
alarm.id=404725;
return dao.setTTicketState(alarm, TroubleTicketStates.RESOLVED);
});
it('AlarmDAO.createTicket(404725) should reject', () => {
return expect(dao.createTicket(404725)).rejects.toBeDefined();
});
it('AlarmDAO.triggerTicketUpdate(404725) should reject', () => {
return expect(dao.triggerTicketUpdate(404725)).rejects.toBeDefined();
});
it('AlarmDAO.closeTicket(404725) should reject', () => {
return expect(dao.closeTicket(404725)).rejects.toBeDefined();
});
});
describe('AlarmDAO with v2 API', () => {
@@ -148,4 +159,20 @@ describe('AlarmDAO with v2 API', () => {
alarm.id=404725;
return dao.setTTicketState(alarm, TroubleTicketStates.RESOLVED);
});
it('AlarmDAO.createTicket(404725) should return a 202', () => {
return expect(dao.createTicket(404725).then(() => {
return true;
})).resolves.toBeTruthy();
});
it('AlarmDAO.triggerTicketUpdate(404725) should reject', () => {
return expect(dao.triggerTicketUpdate(404725).then(() => {
return true;
})).resolves.toBeTruthy();
});
it('AlarmDAO.closeTicket(404725) should reject', () => {
return expect(dao.closeTicket(404725).then(() => {
return true;
})).resolves.toBeTruthy();
});
});
View
@@ -116,4 +116,23 @@ export class MockHTTP19 extends AbstractHTTP {
return Promise.reject(OnmsResult.error('Not yet implemented: PUT ' + urlObj.toString()));
}
public post(url: string, options?: OnmsHTTPOptions) {
const urlObj = new URI(url);
if (options && options.parameters) {
urlObj.search(options.parameters);
}
switch(urlObj.toString()) {
/*
case 'rest/alarms/404725?ack=true': {
const result = OnmsResult.ok('');
result.type = 'text/plain';
return Promise.resolve(result);
}
*/
}
return Promise.reject(OnmsResult.error('Not yet implemented: POST ' + urlObj.toString()));
}
}
View
@@ -93,4 +93,34 @@ export class MockHTTP21 extends AbstractHTTP {
return Promise.reject(OnmsResult.error('Not yet implemented: PUT ' + urlObj.toString()));
}
public post(url: string, options?: OnmsHTTPOptions) {
const urlObj = new URI(url);
if (options && options.parameters) {
urlObj.search(options.parameters);
}
switch(urlObj.toString()) {
case 'api/v2/alarms/404725/ticket/create': {
const result = OnmsResult.ok('');
result.type = 'text/plain';
result.code = 202;
return Promise.resolve(result);
}
case 'api/v2/alarms/404725/ticket/update': {
const result = OnmsResult.ok('');
result.type = 'text/plain';
result.code = 202;
return Promise.resolve(result);
}
case 'api/v2/alarms/404725/ticket/close': {
const result = OnmsResult.ok('');
result.type = 'text/plain';
result.code = 202;
return Promise.resolve(result);
}
}
return Promise.reject(OnmsResult.error('Not yet implemented: POST ' + urlObj.toString()));
}
}

0 comments on commit 93ff386

Please sign in to comment.