@certik/skynet 0.10.4 → 0.10.7
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/.editorconfig +5 -5
- package/.eslintrc.js +13 -13
- package/.prettierrc.js +3 -3
- package/CHANGELOG.md +372 -364
- package/README.md +23 -23
- package/abi.js +353 -353
- package/ably.js +29 -0
- package/address.js +18 -18
- package/api.js +105 -105
- package/app.js +709 -695
- package/availability.js +58 -58
- package/block.js +83 -83
- package/cli.js +53 -53
- package/const.js +92 -92
- package/deploy.js +676 -673
- package/dynamodb.js +444 -444
- package/env.js +90 -90
- package/examples/api +73 -73
- package/examples/consumer +47 -47
- package/examples/indexer +65 -65
- package/examples/mode-indexer +82 -82
- package/examples/producer +80 -80
- package/indexer.js +595 -595
- package/inquiry.js +14 -14
- package/kafka.js +443 -442
- package/labelling.js +90 -90
- package/log.js +29 -29
- package/metric.js +65 -65
- package/monitor.js +191 -192
- package/opsgenie.js +55 -60
- package/package.json +37 -34
- package/price.js +48 -48
- package/primitive.js +77 -77
- package/proxy.js +157 -157
- package/rateLimit.js +21 -21
- package/s3.js +122 -122
- package/scan.js +74 -74
- package/selector.js +53 -53
- package/slack.js +87 -87
- package/snowflake.js +36 -36
- package/sqs.js +12 -12
- package/token.js +46 -46
- package/transaction.js +41 -41
- package/util.js +67 -67
- package/web3.js +117 -117
package/monitor.js
CHANGED
|
@@ -1,192 +1,191 @@
|
|
|
1
|
-
const meow = require("meow");
|
|
2
|
-
const fetch = require("node-fetch");
|
|
3
|
-
const { getSelectorFlags, getSelectorDesc, toSelectorString } = require("./selector");
|
|
4
|
-
const { getBinaryName } = require("./cli");
|
|
5
|
-
const { exponentialRetry } = require("./availability");
|
|
6
|
-
const {
|
|
7
|
-
const {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
function
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
--
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
...
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
module.exports = { createMonitor, ERROR_LEVEL, LEVEL_EMOJI };
|
|
1
|
+
const meow = require("meow");
|
|
2
|
+
const fetch = require("node-fetch");
|
|
3
|
+
const { getSelectorFlags, getSelectorDesc, toSelectorString } = require("./selector");
|
|
4
|
+
const { getBinaryName } = require("./cli");
|
|
5
|
+
const { exponentialRetry } = require("./availability");
|
|
6
|
+
const { postGenieMessage } = require("./opsgenie");
|
|
7
|
+
const { getJobName } = require("./deploy");
|
|
8
|
+
|
|
9
|
+
const ERROR_LEVEL = {
|
|
10
|
+
INFO: "Info",
|
|
11
|
+
CRITICAL: "Critical",
|
|
12
|
+
WARNING: "Warning",
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const LEVEL_EMOJI = {
|
|
16
|
+
Critical: ":exclamation:",
|
|
17
|
+
Warning: ":warning:",
|
|
18
|
+
Info: "",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const LEVEL_PRIORITY = {
|
|
22
|
+
Critical: 3,
|
|
23
|
+
Warning: 2,
|
|
24
|
+
Info: 1,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
function sortErrors(errors) {
|
|
28
|
+
return errors.sort((e1, e2) => (LEVEL_PRIORITY[e2.type] || 0) - (LEVEL_PRIORITY[e1.type] || 0));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function getMostRecentJobLaunch(name) {
|
|
32
|
+
try {
|
|
33
|
+
const jobsRes = await fetch(`http://localhost:4646/v1/jobs?prefix=${name}`);
|
|
34
|
+
|
|
35
|
+
if (!jobsRes.ok) {
|
|
36
|
+
console.log(`[MONITOR] request local nomad API failed`);
|
|
37
|
+
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const jobs = await jobsRes.json();
|
|
42
|
+
|
|
43
|
+
if (jobs.length === 0) {
|
|
44
|
+
console.log(`[MONITOR] did not see any jobs prefixed with ${name}`);
|
|
45
|
+
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const recentFinishedJob = jobs.reverse().find((job) => {
|
|
50
|
+
// filter out monitor job
|
|
51
|
+
return job.ID.indexOf("-monitor") === -1 && job.Status === "dead";
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (!recentFinishedJob) {
|
|
55
|
+
console.log(`[MONITOR] did not see any dead jobs`);
|
|
56
|
+
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
console.log("[MONITOR]", "most recent job info", recentFinishedJob.ID, recentFinishedJob.JobSummary.Summary);
|
|
61
|
+
|
|
62
|
+
return recentFinishedJob;
|
|
63
|
+
} catch (getJobError) {
|
|
64
|
+
console.log("[MONITOR]", "cannot get most recent job", getJobError.message);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function createMonitor({ binaryName, name, getState = null, mode = false, selector = {}, check, maxRetry = 2 }) {
|
|
70
|
+
function monitor() {
|
|
71
|
+
if (!binaryName) {
|
|
72
|
+
binaryName = getBinaryName();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const cli = meow(
|
|
76
|
+
`
|
|
77
|
+
Usage
|
|
78
|
+
|
|
79
|
+
$ ${binaryName} <options>
|
|
80
|
+
|
|
81
|
+
Options
|
|
82
|
+
${
|
|
83
|
+
mode ? " --mode could be delta/rebuild/resume-rebuild/validate/one/range/reset\n" : ""
|
|
84
|
+
}${getSelectorDesc(selector)}
|
|
85
|
+
--production run in production mode
|
|
86
|
+
--verbose Output debug messages
|
|
87
|
+
`,
|
|
88
|
+
{
|
|
89
|
+
description: false,
|
|
90
|
+
version: false,
|
|
91
|
+
flags: {
|
|
92
|
+
...getSelectorFlags(selector),
|
|
93
|
+
...(mode && {
|
|
94
|
+
mode: {
|
|
95
|
+
type: "string",
|
|
96
|
+
default: "delta",
|
|
97
|
+
},
|
|
98
|
+
}),
|
|
99
|
+
verbose: {
|
|
100
|
+
type: "boolean",
|
|
101
|
+
default: false,
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
async function runCheck({ verbose, production, mode, ...selectorFlags }) {
|
|
108
|
+
const startTime = Date.now();
|
|
109
|
+
console.log(`[MONITOR] starting check, ${toSelectorString(selectorFlags, ", ")}`);
|
|
110
|
+
|
|
111
|
+
let checkState = {};
|
|
112
|
+
|
|
113
|
+
if (getState) {
|
|
114
|
+
checkState = await getState(name, selectorFlags);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
let result = await exponentialRetry(
|
|
118
|
+
async () => {
|
|
119
|
+
try {
|
|
120
|
+
const errors = await check({ verbose, state: checkState, mode, ...selectorFlags });
|
|
121
|
+
|
|
122
|
+
if (!Array.isArray(errors)) {
|
|
123
|
+
throw new Error(`check function must return array of error messages`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return errors;
|
|
127
|
+
} catch (err) {
|
|
128
|
+
console.log(`[MONITOR] got error in check`, err);
|
|
129
|
+
|
|
130
|
+
return [`${err.message}`];
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
maxRetry,
|
|
135
|
+
initialDuration: 10000,
|
|
136
|
+
growFactor: 3,
|
|
137
|
+
test: (r) => r.length === 0,
|
|
138
|
+
verbose,
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
const jobName = getJobName(name, selectorFlags, mode);
|
|
143
|
+
const mostRecentJob = await getMostRecentJobLaunch(jobName);
|
|
144
|
+
|
|
145
|
+
if (result.length > 0) {
|
|
146
|
+
console.log("Found Errors", result);
|
|
147
|
+
|
|
148
|
+
if (production) {
|
|
149
|
+
const nomadAddr = process.env.SKYNET_NOMAD_PRODUCTION_ADDR;
|
|
150
|
+
|
|
151
|
+
// alert on opsgenie
|
|
152
|
+
await postGenieMessage(
|
|
153
|
+
{
|
|
154
|
+
message: `Failed Service Check: ${jobName}`,
|
|
155
|
+
description: `<p><b>Service:</b><a href="${nomadAddr}/ui/jobs/${jobName}" target="_blank">${jobName}</a></p><p><b>Issues</b></p><ul>${sortErrors(
|
|
156
|
+
result
|
|
157
|
+
)
|
|
158
|
+
.map((m) => `<li><b>${m.type}:</b> ${m.message}</li>`)
|
|
159
|
+
.join("")}</ul>`,
|
|
160
|
+
},
|
|
161
|
+
verbose
|
|
162
|
+
);
|
|
163
|
+
} else {
|
|
164
|
+
console.log("skip sending messages to opsgenie in dev env");
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
console.log(`[MONITOR] check successfully in ${Date.now() - startTime}ms`);
|
|
169
|
+
|
|
170
|
+
if (mostRecentJob && mostRecentJob.ParentID === "" && mostRecentJob.Periodic === false) {
|
|
171
|
+
// stop monitor job if the main job was a one time job and completed
|
|
172
|
+
const stopRes = await fetch(`http://localhost:4646/v1/job/${jobName}-monitor`, { method: "DELETE" });
|
|
173
|
+
|
|
174
|
+
if (stopRes.ok) {
|
|
175
|
+
console.log(`[MONITOR] monitor job stopped since the completed main job was a one time job`);
|
|
176
|
+
} else {
|
|
177
|
+
console.log(`[MONITOR] error stopping monitor job`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
runCheck(cli.flags).catch((err) => {
|
|
183
|
+
console.log("[MONITOR]", err);
|
|
184
|
+
process.exit(1);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return { monitor };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
module.exports = { createMonitor, ERROR_LEVEL, LEVEL_EMOJI };
|
package/opsgenie.js
CHANGED
|
@@ -1,60 +1,55 @@
|
|
|
1
|
-
const fetch = require("node-fetch");
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
function getGenieKey() {
|
|
5
|
-
return process.env.OPSGENIE_API_KEY;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function getGenieEndPoint() {
|
|
9
|
-
const key = getGenieKey();
|
|
10
|
-
|
|
11
|
-
if (!key) {
|
|
12
|
-
throw new Error("Cannot communicate with opsgenie due to missing API key: process.env.OPSGENIE_API_KEY");
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return process.env.OPSGENIE_END_POINT;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async function postGenieMessage(
|
|
19
|
-
try {
|
|
20
|
-
const genieKey = getGenieKey();
|
|
21
|
-
const genieEndPoint = getGenieEndPoint();
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
throw error;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
module.exports = { postGenieMessage };
|
|
1
|
+
const fetch = require("node-fetch");
|
|
2
|
+
const md5 = require("md5");
|
|
3
|
+
|
|
4
|
+
function getGenieKey() {
|
|
5
|
+
return process.env.OPSGENIE_API_KEY;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function getGenieEndPoint() {
|
|
9
|
+
const key = getGenieKey();
|
|
10
|
+
|
|
11
|
+
if (!key) {
|
|
12
|
+
throw new Error("Cannot communicate with opsgenie due to missing API key: process.env.OPSGENIE_API_KEY");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return process.env.OPSGENIE_END_POINT;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function postGenieMessage(body, verbose) {
|
|
19
|
+
try {
|
|
20
|
+
const genieKey = getGenieKey();
|
|
21
|
+
const genieEndPoint = getGenieEndPoint();
|
|
22
|
+
|
|
23
|
+
// Prevents duplicate alerts (See Opsgenie doc about alias)
|
|
24
|
+
if (!body.alias) {
|
|
25
|
+
body.alias = md5(body.message);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (verbose) {
|
|
29
|
+
console.log(`Making API call to Opsgenie`, JSON.stringify(body, null, 2));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Makes the call using fetch and ENV variables
|
|
33
|
+
const response = await fetch(genieEndPoint, {
|
|
34
|
+
method: "POST",
|
|
35
|
+
headers: {
|
|
36
|
+
"Content-Type": "application/json",
|
|
37
|
+
Authorization: `GenieKey ${genieKey}`,
|
|
38
|
+
},
|
|
39
|
+
body: JSON.stringify(body),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const result = await response.json();
|
|
43
|
+
if (verbose) {
|
|
44
|
+
console.log(`Result of API call to Opsgenie... ${result}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return result;
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error("Failed to make opsgenie API call", error);
|
|
50
|
+
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = { postGenieMessage };
|
package/package.json
CHANGED
|
@@ -1,34 +1,37 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@certik/skynet",
|
|
3
|
-
"version": "0.10.
|
|
4
|
-
"description": "Skynet Shared JS library",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"author": "CertiK Engineering",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"lint": "eslint
|
|
9
|
-
"test": "ava"
|
|
10
|
-
},
|
|
11
|
-
"engines": {
|
|
12
|
-
"node": ">= 14"
|
|
13
|
-
},
|
|
14
|
-
"dependencies": {
|
|
15
|
-
"@slack/web-api": "^6.4.0",
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@certik/skynet",
|
|
3
|
+
"version": "0.10.7",
|
|
4
|
+
"description": "Skynet Shared JS library",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"author": "CertiK Engineering",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"lint": "eslint *.js test",
|
|
9
|
+
"test": "ava"
|
|
10
|
+
},
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">= 14"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@slack/web-api": "^6.4.0",
|
|
16
|
+
"ably": "^1.2.22",
|
|
17
|
+
"aws-sdk": "^2.932.0",
|
|
18
|
+
"bottleneck": "^2.19.5",
|
|
19
|
+
"chalk": "^4.1.1",
|
|
20
|
+
"execa": "^5.0.0",
|
|
21
|
+
"express": "^4.18.1",
|
|
22
|
+
"kafkajs": "^1.15.0",
|
|
23
|
+
"md5": "^2.3.0",
|
|
24
|
+
"meow": "^7.0.1",
|
|
25
|
+
"node-fetch": "^2.6.1",
|
|
26
|
+
"snowflake-sdk": "^1.6.3",
|
|
27
|
+
"web3": "^1.3.5",
|
|
28
|
+
"which": "^2.0.2"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"ava": "^3.13.0",
|
|
32
|
+
"eslint": "^7.22.0",
|
|
33
|
+
"eslint-plugin-import": "^2.26.0",
|
|
34
|
+
"sinon": "^11.1.2"
|
|
35
|
+
},
|
|
36
|
+
"license": "MIT"
|
|
37
|
+
}
|