jetcheck 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.js +20 -0
- package/bin/run.js +25 -0
- package/bin/systemd.conf +15 -0
- package/bin/systemd.js +63 -0
- package/config-example.js +31 -0
- package/config-wan.js +21 -0
- package/index.js +72 -0
- package/lib/aevent.js +18 -0
- package/lib/exec.js +61 -0
- package/lib/index.js +4 -0
- package/package.json +24 -0
- package/services/builtin/cmd.js +13 -0
- package/services/builtin/http.js +25 -0
- package/services/builtin/ping.js +17 -0
- package/services/tests.js +146 -0
- package/version.js +34 -0
package/bin/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const path = require("path")
|
|
4
|
+
const sc = require('subcommander');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const crypto = require('crypto');
|
|
8
|
+
const netcheck = require("../index")
|
|
9
|
+
|
|
10
|
+
// Early loading configuration file
|
|
11
|
+
const configFile = path.resolve(
|
|
12
|
+
process.cwd(),
|
|
13
|
+
process.env.CONFIG || `${os.homedir()}/.netcheck/config.js`
|
|
14
|
+
)
|
|
15
|
+
require("./systemd")(netcheck, sc, configFile)
|
|
16
|
+
require("./run")(netcheck, sc, configFile)
|
|
17
|
+
|
|
18
|
+
sc.parse()
|
|
19
|
+
|
|
20
|
+
|
package/bin/run.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const path = require("path")
|
|
5
|
+
|
|
6
|
+
module.exports = (netcheck, sc, configFile) => {
|
|
7
|
+
sc.command('run', {
|
|
8
|
+
desc: 'Run the monitoring',
|
|
9
|
+
callback: async function (options) {
|
|
10
|
+
const kernel = new netcheck({ configFile })
|
|
11
|
+
await kernel.start()
|
|
12
|
+
}
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
sc.command('test', {
|
|
16
|
+
desc: 'Run the monitoring',
|
|
17
|
+
callback: async function (options) {
|
|
18
|
+
const kernel = new netcheck({ headless: true, configFile })
|
|
19
|
+
await kernel.start()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
package/bin/systemd.conf
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
[Unit]
|
|
2
|
+
Description=Netcheck
|
|
3
|
+
After=network-online.target
|
|
4
|
+
|
|
5
|
+
[Service]
|
|
6
|
+
Type=simple
|
|
7
|
+
WorkingDirectory=<%- cwd %>
|
|
8
|
+
ExecStart=<%- runCmd %>
|
|
9
|
+
Restart=always
|
|
10
|
+
TimeoutStopSec=300
|
|
11
|
+
RestartSec=5s
|
|
12
|
+
Environment="<%- config %>"
|
|
13
|
+
|
|
14
|
+
[Install]
|
|
15
|
+
WantedBy=multi-user.target
|
package/bin/systemd.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const path = require("path")
|
|
5
|
+
const ejs = require("ejs")
|
|
6
|
+
|
|
7
|
+
module.exports = (netcheck, sc, configFile) => {
|
|
8
|
+
|
|
9
|
+
const systemd = sc.command('systemd', {
|
|
10
|
+
desc: 'Linux systemd service management'
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
systemd.command('install', {
|
|
14
|
+
desc: 'Run the monitoring',
|
|
15
|
+
callback: async function (options) {
|
|
16
|
+
var installed = false
|
|
17
|
+
try {
|
|
18
|
+
fs.statSync("/etc/systemd/system/netcheck.service")
|
|
19
|
+
installed = true
|
|
20
|
+
} catch (e) { }
|
|
21
|
+
|
|
22
|
+
if (installed === true) {
|
|
23
|
+
console.log("Netcheck is already installed")
|
|
24
|
+
process.exit(-1)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const kernel = new netcheck({ configFile })
|
|
28
|
+
|
|
29
|
+
const runCmd = `${process.argv[0]} ${process.argv[1]} run`
|
|
30
|
+
const content = fs.readFileSync(__dirname + "/systemd.conf").toString()
|
|
31
|
+
const render = ejs.render(content, { configFile, runCmd, cwd: process.cwd(), config: `CONFIG=${configFile}` })
|
|
32
|
+
fs.writeFileSync("/etc/systemd/system/netcheck.service", render)
|
|
33
|
+
|
|
34
|
+
await kernel.lib.exec("systemctl daemon-reload", false)
|
|
35
|
+
await kernel.lib.exec("systemctl enable netcheck", false)
|
|
36
|
+
console.log("To start type: systemctl start netcheck")
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
systemd.command('deinstall', {
|
|
41
|
+
desc: 'Run the monitoring',
|
|
42
|
+
callback: async function (options) {
|
|
43
|
+
var installed = false
|
|
44
|
+
try {
|
|
45
|
+
fs.statSync("/etc/systemd/system/netcheck.service")
|
|
46
|
+
installed = true
|
|
47
|
+
} catch (e) { }
|
|
48
|
+
|
|
49
|
+
if (installed === false) {
|
|
50
|
+
console.log("Netcheck is not installed")
|
|
51
|
+
process.exit(-1)
|
|
52
|
+
}
|
|
53
|
+
const kernel = new netcheck({ configFile })
|
|
54
|
+
|
|
55
|
+
await kernel.lib.exec("systemctl stop netcheck", false)
|
|
56
|
+
await kernel.lib.exec("systemctl disable netcheck", false)
|
|
57
|
+
fs.unlinkSync("/etc/systemd/system/netcheck.service")
|
|
58
|
+
await kernel.lib.exec("systemctl daemon-reload", false)
|
|
59
|
+
console.log("Netcheck deinstalled")
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
tests: {
|
|
3
|
+
myCheck: {
|
|
4
|
+
// start from degraded mode
|
|
5
|
+
init: "DEGRADED",
|
|
6
|
+
|
|
7
|
+
// test every 15 seconds
|
|
8
|
+
interval: 15,
|
|
9
|
+
|
|
10
|
+
// checker tasks
|
|
11
|
+
tasks: [
|
|
12
|
+
{ type: "ping", host: "8.8.8.8", count: 2 },
|
|
13
|
+
// { type: "ping", host: "54.43.5.5" },
|
|
14
|
+
{ type: "http", url: "https://8.8.8.8" },
|
|
15
|
+
{ type: "http", url: "https://1.1.1.1" },
|
|
16
|
+
{ type: "http", url: "https://1.2.4.1" },
|
|
17
|
+
],
|
|
18
|
+
|
|
19
|
+
// when system fails
|
|
20
|
+
failed: [
|
|
21
|
+
{ type: "cmd", cmd: `logger "TEST: Disconnected from HTTP"` }
|
|
22
|
+
],
|
|
23
|
+
|
|
24
|
+
// when system succeed
|
|
25
|
+
succeed: [
|
|
26
|
+
{ type: "cmd", cmd: `logger "TEST: Connected from HTTP"` },
|
|
27
|
+
{ type: "cmd", cmd: `logger "TEST: secondary command"` }
|
|
28
|
+
],
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
package/config-wan.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
tests: {
|
|
3
|
+
wan: {
|
|
4
|
+
init: "WORKING",
|
|
5
|
+
interval: 5,
|
|
6
|
+
tasks: [
|
|
7
|
+
{ type: "ping", host: "8.8.8.8", count: 3 },
|
|
8
|
+
{ type: "http", url: "https://8.8.8.8" },
|
|
9
|
+
{ type: "http", url: "https://1.1.1.1" },
|
|
10
|
+
],
|
|
11
|
+
|
|
12
|
+
failed: [
|
|
13
|
+
{ type: "cmd", cmd: `systemctl stop frr` }
|
|
14
|
+
],
|
|
15
|
+
succeed: [
|
|
16
|
+
{ type: "cmd", cmd: `systemctl start frr` },
|
|
17
|
+
],
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const path = require("path")
|
|
2
|
+
|
|
3
|
+
// internal requires
|
|
4
|
+
const pack = require("./package.json")
|
|
5
|
+
const aevent = require("./lib/aevent")
|
|
6
|
+
|
|
7
|
+
class netcheck {
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.options = options || {}
|
|
10
|
+
this.events = new aevent()
|
|
11
|
+
this.lib = require("./lib")
|
|
12
|
+
this.packages = {}
|
|
13
|
+
|
|
14
|
+
this.packageInfo(pack, ["service"])
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
packageInfo(pkg, log) {
|
|
18
|
+
var buffer = [`version=${pkg.version} -`]
|
|
19
|
+
for (var key in pkg.dependencies)
|
|
20
|
+
buffer.push(`${key}=${pkg.dependencies[key]}`)
|
|
21
|
+
this.packages[pkg.name] = pkg
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async sleep(ms) {
|
|
25
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async start(overwrite) {
|
|
29
|
+
this.version = pack.version
|
|
30
|
+
|
|
31
|
+
// load configuration
|
|
32
|
+
if (this.options.configFile) {
|
|
33
|
+
this.configFile = path.resolve(process.cwd(), this.options.configFile);
|
|
34
|
+
try {
|
|
35
|
+
this.config = require(this.configFile)
|
|
36
|
+
} catch (e) {
|
|
37
|
+
console.log(`Can not read configuration ${this.configFile}`)
|
|
38
|
+
process.exit(-1)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else
|
|
42
|
+
this.config = {}
|
|
43
|
+
|
|
44
|
+
// overwrite feature
|
|
45
|
+
if (overwrite)
|
|
46
|
+
this.config = { ...this.config, ...overwrite }
|
|
47
|
+
|
|
48
|
+
if (!Array.isArray(this.config.modules))
|
|
49
|
+
this.config.modules = []
|
|
50
|
+
|
|
51
|
+
// load basic services
|
|
52
|
+
await (require("./services/tests"))(this)
|
|
53
|
+
|
|
54
|
+
// load modules
|
|
55
|
+
if (this.config.modules) {
|
|
56
|
+
for (var module of this.config.modules) {
|
|
57
|
+
await require(module)(this)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
await this.events.emit("kernel.init", this)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async stop() {
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = netcheck
|
|
71
|
+
|
|
72
|
+
|
package/lib/aevent.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class asEventEmitter {
|
|
2
|
+
constructor() {
|
|
3
|
+
this._acall = {}
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
async emit(ev, ...argv) {
|
|
7
|
+
if (!this._acall[ev]) return;
|
|
8
|
+
const list = this._acall[ev];
|
|
9
|
+
for (let call of list) await call(...argv);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
on(ev, cb) {
|
|
13
|
+
if (!this._acall[ev]) this._acall[ev] = []
|
|
14
|
+
this._acall[ev].push(cb)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = asEventEmitter;
|
package/lib/exec.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const { spawn } = require('child_process');
|
|
2
|
+
|
|
3
|
+
async function detachedExec(cmd, detached = true) {
|
|
4
|
+
return new Promise((resolve) => {
|
|
5
|
+
// Split the command into the executable and its arguments
|
|
6
|
+
const [command, ...args] = cmd.split(' ')
|
|
7
|
+
|
|
8
|
+
// Launch the detached process
|
|
9
|
+
const child = spawn(command, args, {
|
|
10
|
+
detached, // Detach the child process from the parent
|
|
11
|
+
stdio: ['ignore', 'pipe', 'pipe'], // Ignore stdin and stderr, capture stdout
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
let stdout = ''
|
|
15
|
+
let stderr = ''
|
|
16
|
+
|
|
17
|
+
// Capture stdout
|
|
18
|
+
child.stdout.on('data', (data) => {
|
|
19
|
+
stdout += data.toString();
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
child.stderr.on('data', (data) => {
|
|
23
|
+
stderr += data.toString();
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
// Handle process completion
|
|
27
|
+
child.on('close', (code) => {
|
|
28
|
+
resolve({
|
|
29
|
+
stdout: stdout.trim(),
|
|
30
|
+
stderr: stderr.trim(),
|
|
31
|
+
error: code, // If code is 0, no error; otherwise, return the error code
|
|
32
|
+
})
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
// Handle process errors
|
|
36
|
+
child.on('error', (err) => {
|
|
37
|
+
resolve({
|
|
38
|
+
stdout: '',
|
|
39
|
+
stderr: stderr.trim(),
|
|
40
|
+
error: err, // Default error code for execution failure
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
// Actually detach the process
|
|
45
|
+
if (detached === true)
|
|
46
|
+
child.unref()
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = detachedExec
|
|
51
|
+
|
|
52
|
+
// async function init() {
|
|
53
|
+
// async function para() {
|
|
54
|
+
// const ret = await detachedExec("ping -c 5 9.9.9.9")
|
|
55
|
+
// console.log(ret)
|
|
56
|
+
// }
|
|
57
|
+
// para()
|
|
58
|
+
// para()
|
|
59
|
+
// }
|
|
60
|
+
|
|
61
|
+
// init()
|
package/lib/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jetcheck",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Javascript based Network & System checker",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"bin": {
|
|
10
|
+
"jetcheck": "bin/index.js"
|
|
11
|
+
},
|
|
12
|
+
"repository": "https://github.com/mykiimike/jetcheck",
|
|
13
|
+
"author": "Michael VERGOZ",
|
|
14
|
+
"license": "GPL-3.0",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"axios": "^1.7.9",
|
|
17
|
+
"ejs": "^3.1.10",
|
|
18
|
+
"mkdirp": "^3.0.1",
|
|
19
|
+
"subcommander": "^1.0.0"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"semver": "^7.6.3"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const axios = require('axios')
|
|
2
|
+
|
|
3
|
+
module.exports = async function (kernel) {
|
|
4
|
+
kernel.tests.plugins.cmd = {
|
|
5
|
+
toString: function (options) {
|
|
6
|
+
return (`cmd(${options.cmd})`)
|
|
7
|
+
},
|
|
8
|
+
trigger: async function (task, state) {
|
|
9
|
+
await kernel.lib.exec(task.cmd)
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
console.log("Loading CMD plugin")
|
|
13
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
|
|
3
|
+
module.exports = async function (kernel) {
|
|
4
|
+
kernel.tests.plugins.http = {
|
|
5
|
+
toString: function (options) {
|
|
6
|
+
return (`http(${options.url})`)
|
|
7
|
+
},
|
|
8
|
+
run: async function (options, task, state) {
|
|
9
|
+
async function check(url) {
|
|
10
|
+
try {
|
|
11
|
+
await axios.get(url, {
|
|
12
|
+
timeout: options.timeout ? options.timeout : 5000,
|
|
13
|
+
validateStatus: () => true,
|
|
14
|
+
});
|
|
15
|
+
return null;
|
|
16
|
+
} catch (error) {
|
|
17
|
+
return error.message;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return (await check(options.url))
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
console.log("Loading HTTP plugin")
|
|
25
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
|
|
3
|
+
module.exports = async function (kernel) {
|
|
4
|
+
kernel.tests.plugins.ping = {
|
|
5
|
+
toString: function (options) {
|
|
6
|
+
return (`ping(${options.host})`)
|
|
7
|
+
},
|
|
8
|
+
run: async function (options, task, state) {
|
|
9
|
+
const count = options.count ? options.count : 5
|
|
10
|
+
const ret = await kernel.lib.exec(`ping -c ${count} ${options.host}`)
|
|
11
|
+
if(ret.error > 0)
|
|
12
|
+
return("Host down")
|
|
13
|
+
return(null)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
console.log("Loading PING plugin")
|
|
17
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
const path = require("path")
|
|
2
|
+
const { start } = require("repl")
|
|
3
|
+
|
|
4
|
+
module.exports = async function (kernel) {
|
|
5
|
+
kernel.tests = {
|
|
6
|
+
plugins: {},
|
|
7
|
+
states: {}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// tester
|
|
11
|
+
kernel.config.modules.push(__dirname + "/builtin/http.js")
|
|
12
|
+
kernel.config.modules.push(__dirname + "/builtin/ping.js")
|
|
13
|
+
|
|
14
|
+
// triggers
|
|
15
|
+
kernel.config.modules.push(__dirname + "/builtin/cmd.js")
|
|
16
|
+
|
|
17
|
+
kernel.events.on("kernel.init", async function () {
|
|
18
|
+
|
|
19
|
+
if (kernel.options.headless === true)
|
|
20
|
+
return
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
// prepare initial states
|
|
25
|
+
for (var testName in kernel.config.tests) {
|
|
26
|
+
const test = kernel.config.tests[testName]
|
|
27
|
+
|
|
28
|
+
if (!test.interval)
|
|
29
|
+
test.interval = 5
|
|
30
|
+
test.interval = test.interval * 1000
|
|
31
|
+
|
|
32
|
+
kernel.tests.states[testName] = {
|
|
33
|
+
status: "INIT",
|
|
34
|
+
mode: "INIT",
|
|
35
|
+
startTime: Date.now(),
|
|
36
|
+
lastTime: 0,
|
|
37
|
+
original: [],
|
|
38
|
+
lastSucceed: [],
|
|
39
|
+
lastFailed: [],
|
|
40
|
+
succeed: [],
|
|
41
|
+
failed: []
|
|
42
|
+
}
|
|
43
|
+
const state = kernel.tests.states[testName]
|
|
44
|
+
|
|
45
|
+
if(test.init.toLowerCase() === "working")
|
|
46
|
+
state.mode = "WORKING"
|
|
47
|
+
else if(test.init.toLowerCase() === "degraded")
|
|
48
|
+
state.mode = "DEGRADED"
|
|
49
|
+
else
|
|
50
|
+
state.mode = "WORKING"
|
|
51
|
+
|
|
52
|
+
// prepare test pipelines
|
|
53
|
+
for (var task of test.tasks) {
|
|
54
|
+
if (!kernel.tests.plugins[task.type]) {
|
|
55
|
+
console.log(`Test plugin not found "${task.type}"`)
|
|
56
|
+
continue
|
|
57
|
+
}
|
|
58
|
+
if (!kernel.tests.plugins[task.type].run) {
|
|
59
|
+
console.log(`Plugin "${task.type}" cannot run test`)
|
|
60
|
+
continue
|
|
61
|
+
}
|
|
62
|
+
state.original.push(task)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
console.log(`Test "${testName}" loaded`)
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function check() {
|
|
70
|
+
for (let testName in kernel.config.tests) {
|
|
71
|
+
const test = kernel.config.tests[testName]
|
|
72
|
+
const state = kernel.tests.states[testName]
|
|
73
|
+
|
|
74
|
+
// console.log(`name=${testName} status=${state.status} mode=${state.mode} elapsed=${test.interval - (Date.now() - state.startTime)}ms succeed=${state.lastSucceed.length} failed=${state.lastFailed.length}`)
|
|
75
|
+
|
|
76
|
+
if (state.status === "RUNNING")
|
|
77
|
+
continue;
|
|
78
|
+
|
|
79
|
+
if (Date.now() - state.lastTime < test.interval)
|
|
80
|
+
continue;
|
|
81
|
+
|
|
82
|
+
state.startTime = Date.now()
|
|
83
|
+
state.status = "RUNNING"
|
|
84
|
+
state.current = [...state.original]
|
|
85
|
+
state.lastSucceed = state.succeed
|
|
86
|
+
state.lastFailed = state.failed
|
|
87
|
+
state.succeed = []
|
|
88
|
+
state.failed = []
|
|
89
|
+
|
|
90
|
+
async function pop() {
|
|
91
|
+
const task = state.current.pop()
|
|
92
|
+
if (!task) {
|
|
93
|
+
|
|
94
|
+
if(state.succeed.length === 0) {
|
|
95
|
+
if(state.mode === "WORKING") {
|
|
96
|
+
console.log(`System "${testName}" is degraded`)
|
|
97
|
+
if(test.failed) {
|
|
98
|
+
for(var item of test.failed) {
|
|
99
|
+
const module = kernel.tests.plugins[item.type]
|
|
100
|
+
if(module && module.trigger)
|
|
101
|
+
await module.trigger(item, state)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
state.mode = "DEGRADED"
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
if(state.mode === "DEGRADED") {
|
|
109
|
+
console.log(`System ${testName} is restored`)
|
|
110
|
+
if(test.succeed) {
|
|
111
|
+
for(var item of test.succeed) {
|
|
112
|
+
const module = kernel.tests.plugins[item.type]
|
|
113
|
+
if(module && module.trigger)
|
|
114
|
+
await module.trigger(item, state)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
state.mode = "WORKING"
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
state.lastSucceed = state.succeed
|
|
122
|
+
state.lastFailed = state.failed
|
|
123
|
+
|
|
124
|
+
state.startTime = Date.now()
|
|
125
|
+
state.lastTime = Date.now()
|
|
126
|
+
state.status = "PENDING"
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const module = kernel.tests.plugins[task.type]
|
|
131
|
+
// console.log(`Executing ${testName} > ${module.toString(task)}`)
|
|
132
|
+
const error = await module.run(task, test, state)
|
|
133
|
+
if (!error)
|
|
134
|
+
state.succeed.push(task)
|
|
135
|
+
else
|
|
136
|
+
state.failed.push({ ...task, error })
|
|
137
|
+
|
|
138
|
+
setTimeout(pop, 10)
|
|
139
|
+
}
|
|
140
|
+
setTimeout(pop, 10)
|
|
141
|
+
}
|
|
142
|
+
setTimeout(check, 1000)
|
|
143
|
+
}
|
|
144
|
+
check()
|
|
145
|
+
})
|
|
146
|
+
}
|
package/version.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const fs = require("fs")
|
|
2
|
+
const util = require('util')
|
|
3
|
+
const semver = require('semver');
|
|
4
|
+
const exec = util.promisify(require('child_process').exec)
|
|
5
|
+
|
|
6
|
+
const gitRepo = "./"
|
|
7
|
+
|
|
8
|
+
const isoDate = new Date().toISOString().slice(0, 10);
|
|
9
|
+
|
|
10
|
+
async function safeExec(cmd, ignore) {
|
|
11
|
+
console.log(cmd)
|
|
12
|
+
try {
|
|
13
|
+
const ret = await exec(cmd)
|
|
14
|
+
if (ret.stderr.length > 0) return ({ error: ret.stderr.split("\n")[0] })
|
|
15
|
+
if (ret.stdout.length === 0) return ({})
|
|
16
|
+
return ({ data: JSON.parse(ret.stdout) })
|
|
17
|
+
} catch (e) {
|
|
18
|
+
if (ignore !== true) return ({ error: e.message })
|
|
19
|
+
return ({})
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
(async () => {
|
|
24
|
+
const packageData = require(gitRepo + '/package.json');
|
|
25
|
+
packageData.version = semver.inc(packageData.version, 'patch');
|
|
26
|
+
fs.writeFileSync(gitRepo + '/package.json', JSON.stringify(packageData, null, " "));
|
|
27
|
+
|
|
28
|
+
await safeExec(`cd ${gitRepo} && git commit -m "Release ${packageData.version}" -a`)
|
|
29
|
+
|
|
30
|
+
await safeExec(`cd ${gitRepo} && git push`)
|
|
31
|
+
await safeExec(`cd ${gitRepo} && git tag ${packageData.version}`)
|
|
32
|
+
await safeExec(`cd ${gitRepo} && git push --tags`)
|
|
33
|
+
await safeExec(`cd ${gitRepo} && npm publish`)
|
|
34
|
+
})();
|