mirror of
https://github.com/nttgin/BGPalerter.git
synced 2024-05-19 06:50:08 +00:00
introduced software updates checks (#17)
* check for update feature + converting to standard npm versioning
This commit is contained in:
@@ -89,3 +89,5 @@ logging:
|
||||
zippedArchive: true
|
||||
maxSize: 20m
|
||||
maxFiles: 14d
|
||||
|
||||
checkForUpdatesAtBoot: true
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
export default class Connector {
|
||||
|
||||
constructor(name, params, env){
|
||||
this.version = env.version;
|
||||
this.config = env.config;
|
||||
this.logger = env.logger;
|
||||
this.pubSub = env.pubSub;
|
||||
|
||||
@@ -87,7 +87,6 @@ export default class ConnectorRIS extends Connector{
|
||||
};
|
||||
|
||||
_subscribeToAll = (input) => {
|
||||
console.log("Subscribing to everything");
|
||||
this.ws.send(JSON.stringify({
|
||||
type: "ris_subscribe",
|
||||
data: this.params.subscription
|
||||
@@ -99,8 +98,8 @@ export default class ConnectorRIS extends Connector{
|
||||
const monitoredPrefixes = input.getMonitoredLessSpecifics().map(item => item.prefix);
|
||||
const params = JSON.parse(JSON.stringify(this.params.subscription));
|
||||
for (let prefix of monitoredPrefixes){
|
||||
console.log("Monitoring", prefix);
|
||||
params.prefix = prefix;
|
||||
console.log("Subscribing to:", prefix);
|
||||
this.ws.send(JSON.stringify({
|
||||
type: "ris_subscribe",
|
||||
data: params
|
||||
|
||||
83
connectors/connectorSwUpdates.js
Normal file
83
connectors/connectorSwUpdates.js
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* BSD 3-Clause License
|
||||
*
|
||||
* Copyright (c) 2019, NTT Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import Connector from "./connector";
|
||||
import axios from "axios";
|
||||
|
||||
export default class ConnectorSwUpdates extends Connector{
|
||||
|
||||
constructor(name, params, env) {
|
||||
super(name, params, env);
|
||||
this.timer = null;
|
||||
}
|
||||
|
||||
connect = () =>
|
||||
new Promise((resolve, reject) => {
|
||||
resolve(true);
|
||||
});
|
||||
|
||||
_checkForUpdates = () => {
|
||||
return axios({
|
||||
responseType: "json",
|
||||
url: "https://raw.githubusercontent.com/nttgin/BGPalerter/master/package.json"
|
||||
})
|
||||
.then(data => {
|
||||
if (data && data.data && data.data.version && data.data.version !== this.version){
|
||||
this._message(JSON.stringify({
|
||||
type: "software-update",
|
||||
currentVersion: this.version,
|
||||
newVersion: data.data.version,
|
||||
repo: "https://github.com/nttgin/BGPalerter"
|
||||
}));
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.logger.log({
|
||||
level: 'error',
|
||||
message: "It was not possible to check for software updates"
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
subscribe = (input) =>
|
||||
new Promise((resolve, reject) => {
|
||||
if (this.config.checkForUpdatesAtBoot){
|
||||
this._checkForUpdates();
|
||||
}
|
||||
this.timer = setInterval(this._checkForUpdates, 1000 * 3600 * 24 * 5); // Check every 5 days
|
||||
resolve(true);
|
||||
});
|
||||
|
||||
static transform = (message) => {
|
||||
return [ message ];
|
||||
}
|
||||
};
|
||||
@@ -39,11 +39,9 @@ export default class ConnectorTest extends Connector{
|
||||
|
||||
constructor(name, params, env) {
|
||||
super(name, params, env);
|
||||
console.log("Test connector running");
|
||||
this.pubSub.subscribe("test-type", (type, message) => {
|
||||
clearInterval(this.timer);
|
||||
this.subscribe({type: message});
|
||||
console.log("switching to", message);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ export default class Consumer {
|
||||
} catch (error) {
|
||||
env.logger.log({
|
||||
level: 'error',
|
||||
message: error
|
||||
message: "Error in parsing data, dispatch method of consumer.js: " + error
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
47
env.js
47
env.js
@@ -100,8 +100,8 @@ let config = {
|
||||
zippedArchive: true,
|
||||
maxSize: "20m",
|
||||
maxFiles: "14d",
|
||||
}
|
||||
|
||||
},
|
||||
checkForUpdatesAtBoot: true
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -120,7 +120,7 @@ const transportError = new (winston.transports.DailyRotateFile)({
|
||||
zippedArchive: config.logging.zippedArchive,
|
||||
maxSize: config.logging.maxSize,
|
||||
maxFiles: config.logging.maxFiles,
|
||||
level: 'error',
|
||||
level: 'info',
|
||||
timestamp: true,
|
||||
eol: '\n',
|
||||
json: false,
|
||||
@@ -130,6 +130,7 @@ const transportError = new (winston.transports.DailyRotateFile)({
|
||||
formatLine
|
||||
)
|
||||
});
|
||||
|
||||
const transportReports = new (winston.transports.DailyRotateFile)({
|
||||
filename: config.logging.directory + '/reports-%DATE%.log',
|
||||
datePattern: config.logging.logRotatePattern,
|
||||
@@ -148,22 +149,29 @@ const transportReports = new (winston.transports.DailyRotateFile)({
|
||||
)
|
||||
});
|
||||
|
||||
const wlogger = winston.createLogger({
|
||||
level: 'info',
|
||||
transports: [
|
||||
transportError,
|
||||
transportReports,
|
||||
new winston.transports.Console({
|
||||
format: winston.format.simple()
|
||||
})
|
||||
]
|
||||
});
|
||||
const winstonTransports = [
|
||||
transportError,
|
||||
transportReports
|
||||
];
|
||||
|
||||
if (config.environment === 'production') {
|
||||
wlogger.remove(wlogger.transports.Console);
|
||||
if (config.environment !== 'production') {
|
||||
const consoleTransport = new winston.transports.Console({
|
||||
format: winston.format.simple()
|
||||
});
|
||||
winstonTransports.push(consoleTransport);
|
||||
}
|
||||
|
||||
config.monitors = (config.monitors || [])
|
||||
const wlogger = winston.createLogger({ transports: winstonTransports });
|
||||
|
||||
config.monitors = (config.monitors || []);
|
||||
config.monitors.push({
|
||||
file: "monitorSwUpdates",
|
||||
channel: "software-update",
|
||||
name: "software-update",
|
||||
});
|
||||
|
||||
|
||||
config.monitors = config.monitors
|
||||
.map(item => {
|
||||
return {
|
||||
class: require("./monitors/" + item.file).default,
|
||||
@@ -178,13 +186,18 @@ config.reports = (config.reports || [])
|
||||
|
||||
return {
|
||||
class: require("./reports/" + item.file).default,
|
||||
channels: item.channels,
|
||||
channels: [...item.channels, "software-update"],
|
||||
params: item.params
|
||||
};
|
||||
|
||||
});
|
||||
config.connectors = config.connectors || [];
|
||||
|
||||
config.connectors.push( {
|
||||
file: "connectorSwUpdates",
|
||||
name: "upd"
|
||||
});
|
||||
|
||||
if ([...new Set(config.connectors)].length !== config.connectors.length) {
|
||||
throw new Error('Connectors names MUST be unique');
|
||||
}
|
||||
|
||||
4
index.js
4
index.js
@@ -79,6 +79,6 @@ switch(params._[0]) {
|
||||
break;
|
||||
|
||||
default: // Run monitor
|
||||
const Monitor = require("./monitor").default;
|
||||
module.exports = new Monitor(params.c).pubSub;
|
||||
const Worker = require("./worker").default;
|
||||
module.exports = new Worker(params.c).pubSub;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
*/
|
||||
|
||||
import Monitor from "./monitor";
|
||||
import ipUtils from "../ipUtils";
|
||||
|
||||
export default class MonitorHijack extends Monitor {
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
*/
|
||||
|
||||
import Monitor from "./monitor";
|
||||
import ipUtils from "../ipUtils";
|
||||
|
||||
export default class MonitorNewPrefix extends Monitor {
|
||||
|
||||
|
||||
62
monitors/monitorSwUpdates.js
Normal file
62
monitors/monitorSwUpdates.js
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* BSD 3-Clause License
|
||||
*
|
||||
* Copyright (c) 2019, NTT Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import Monitor from "./monitor";
|
||||
|
||||
export default class MonitorSwUpdates extends Monitor {
|
||||
|
||||
constructor(name, channel, params, env){
|
||||
super(name, channel, params, env);
|
||||
};
|
||||
|
||||
filter = (message) => {
|
||||
return message.type === 'software-update';
|
||||
};
|
||||
|
||||
squashAlerts = (alerts) => {
|
||||
return alerts[0].message;
|
||||
};
|
||||
|
||||
monitor = (message) =>
|
||||
new Promise((resolve, reject) => {
|
||||
|
||||
this.publishAlert("software-update",
|
||||
`A new version of BGPalerter is available. Current version: ${message.currentVersion} new version: ${message.newVersion}. Please, go to: ${message.repo}`,
|
||||
"bgpalerter",
|
||||
{},
|
||||
message,
|
||||
{});
|
||||
|
||||
resolve(true);
|
||||
});
|
||||
|
||||
}
|
||||
@@ -31,7 +31,6 @@
|
||||
*/
|
||||
|
||||
import Monitor from "./monitor";
|
||||
import ipUtils from "../ipUtils";
|
||||
|
||||
export default class MonitorVisibility extends Monitor {
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "bgpalerter",
|
||||
"version": "19.9.19.2",
|
||||
"version": "1.19.1",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"bin": "index.js",
|
||||
|
||||
@@ -39,7 +39,6 @@ export default class ReportFile extends Report {
|
||||
}
|
||||
|
||||
report = (message, content) => {
|
||||
|
||||
this.logger.log({
|
||||
level: 'verbose',
|
||||
message: content.message
|
||||
|
||||
@@ -51,6 +51,11 @@ export default class ReportSlack extends Report {
|
||||
}
|
||||
|
||||
_sendSlackMessage = (url, message, content) => {
|
||||
|
||||
const color = (this.params && this.params.colors && this.params.colors[message])
|
||||
? this.params.colors[message]
|
||||
: '#4287f5';
|
||||
|
||||
axios({
|
||||
url: url,
|
||||
method: "POST",
|
||||
@@ -58,7 +63,7 @@ export default class ReportSlack extends Report {
|
||||
data: {
|
||||
attachments: [
|
||||
{
|
||||
color: this.params.colors[message],
|
||||
color: color,
|
||||
title: message,
|
||||
text: content.message
|
||||
}
|
||||
@@ -75,7 +80,8 @@ export default class ReportSlack extends Report {
|
||||
|
||||
report = (message, content) => {
|
||||
if (this.enabled){
|
||||
const groups = [...new Set(content.data.map(i => i.matchedRule.group))];
|
||||
let groups = content.data.map(i => i.matchedRule.group).filter(i => i != null);
|
||||
groups = (groups.length) ? [...new Set(groups)] : Object.keys(this.params.hooks); // If there are no groups defined, send to all of them
|
||||
|
||||
for (let group of groups) {
|
||||
if (this.params.hooks[group]) {
|
||||
|
||||
@@ -43,3 +43,5 @@ logging:
|
||||
zippedArchive: true
|
||||
maxSize: 20m
|
||||
maxFiles: 14d
|
||||
|
||||
checkForUpdatesAtBoot: true
|
||||
|
||||
@@ -40,11 +40,13 @@ chai.use(chaiSubset);
|
||||
var expect = chai.expect;
|
||||
var AS = model.AS;
|
||||
|
||||
process.env.npm_package_version = "0.0.1";
|
||||
global.EXTERNAL_CONFIG_FILE = "tests/config.test.yml";
|
||||
|
||||
describe("Tests", function() {
|
||||
beforeEach(resetCache);
|
||||
|
||||
describe("Configuration loader", function () {
|
||||
global.EXTERNAL_CONFIG_FILE = "tests/config.test.yml";
|
||||
var env = require("../env");
|
||||
|
||||
it("config structure", function () {
|
||||
@@ -58,7 +60,8 @@ describe("Tests", function() {
|
||||
"notificationIntervalSeconds",
|
||||
"clearNotificationQueueAfterSeconds",
|
||||
"monitoredPrefixesFiles",
|
||||
"logging"
|
||||
"logging",
|
||||
"checkForUpdatesAtBoot"
|
||||
]);
|
||||
expect(env.config.connectors[0]).to.have
|
||||
.property('class')
|
||||
@@ -122,7 +125,6 @@ describe("Tests", function() {
|
||||
|
||||
|
||||
describe("Input loader", function () {
|
||||
process.argv[2] = "tests/config.test.yml";
|
||||
var env = require("../env");
|
||||
|
||||
|
||||
@@ -197,7 +199,6 @@ describe("Tests", function() {
|
||||
|
||||
|
||||
describe("Logging", function () {
|
||||
process.argv[2] = "tests/config.test.yml";
|
||||
var env = require("../env");
|
||||
|
||||
it("errors logging on the right file", function (done) {
|
||||
@@ -243,8 +244,22 @@ describe("Tests", function() {
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe("Software updates check", function () {
|
||||
var pubSub = require("../index");
|
||||
|
||||
it("new version detected", function (done) {
|
||||
|
||||
pubSub.subscribe("software-update", function (type, message) {
|
||||
expect(type).to.equal("software-update");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe("Alerting", function () {
|
||||
process.argv[2] = "tests/config.test.yml";
|
||||
var pubSub = require("../index");
|
||||
var env = require("../env");
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ import Consumer from "./consumer";
|
||||
import ConnectorFactory from "./connectorFactory";
|
||||
import cluster from "cluster";
|
||||
|
||||
export default class Monitor {
|
||||
export default class Worker {
|
||||
constructor(configFile) {
|
||||
global.EXTERNAL_CONFIG_FILE = configFile;
|
||||
|
||||
Reference in New Issue
Block a user