@certik/skynet 0.7.20 → 0.8.0
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/CHANGELOG.md +4 -0
- package/app.js +476 -0
- package/cli.js +51 -0
- package/deploy.js +188 -143
- package/examples/consumer +53 -0
- package/examples/indexer +39 -8
- package/examples/{deploy-consumer → legacy-deploy-consumer} +2 -2
- package/examples/{deploy-indexer → legacy-deploy-indexer} +4 -3
- package/examples/{deploy-mode-indexer → legacy-deploy-mode-indexer} +2 -2
- package/examples/{deploy-producer → legacy-deploy-producer} +2 -2
- package/examples/legacy-indexer +25 -0
- package/examples/{kafka-consumer → legacy-kafka-consumer} +1 -1
- package/examples/{kafka-producer → legacy-kafka-producer} +2 -2
- package/examples/legacy-mode-indexer +64 -0
- package/examples/mode-indexer +51 -38
- package/examples/producer +68 -0
- package/indexer.js +10 -7
- package/kafka.js +9 -7
- package/monitor.js +246 -0
- package/package.json +1 -1
- package/selector.js +5 -5
- package/slack.js +47 -31
package/deploy.js
CHANGED
|
@@ -1,27 +1,37 @@
|
|
|
1
1
|
const fs = require("fs/promises");
|
|
2
|
+
const fso = require("fs");
|
|
2
3
|
const execa = require("execa");
|
|
3
|
-
const path = require("path");
|
|
4
4
|
const meow = require("meow");
|
|
5
5
|
const chalk = require("chalk");
|
|
6
6
|
const which = require("which");
|
|
7
7
|
const { getSelectorFlags, getSelectorDesc } = require("./selector");
|
|
8
8
|
const { getEnvOrThrow } = require("./env");
|
|
9
|
+
const { getBinaryName, detectSkynetDirectory } = require("./cli");
|
|
10
|
+
|
|
11
|
+
const INTERVAL_ALIASES = {
|
|
12
|
+
"@secondly": "*/1 * * * * * *",
|
|
13
|
+
"@minutely": "0 * * * * * *",
|
|
14
|
+
"@hourly": "0 0 * * * * *",
|
|
15
|
+
"@daily": "0 0 0 * * * *",
|
|
16
|
+
"@weekly": "0 0 0 * * 0 *",
|
|
17
|
+
};
|
|
9
18
|
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
SKYNET_ENVIRONMENT: isProduction ? "prd" : "dev"
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const obj = { ...defaultEnv, ...additionalEnv };
|
|
19
|
-
|
|
20
|
-
return Object.keys(obj)
|
|
21
|
-
.map(key => `${key} = "${obj[key]}"`)
|
|
19
|
+
function buildEnvTemplate(additionalEnv, isProduction) {
|
|
20
|
+
return Object.keys(additionalEnv)
|
|
21
|
+
.map((key) => {
|
|
22
|
+
return `${key} = "${additionalEnv[key] || getEnvironmentVariableValue(key, isProduction)}"`;
|
|
23
|
+
})
|
|
22
24
|
.join("\n ");
|
|
23
25
|
}
|
|
24
26
|
|
|
27
|
+
function getEnvironmentVariableValue(name, isProduction) {
|
|
28
|
+
if (isProduction) {
|
|
29
|
+
return `{{key "${name}"}}`;
|
|
30
|
+
} else {
|
|
31
|
+
return process.env[name];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
25
35
|
const genConfig = ({
|
|
26
36
|
jobName,
|
|
27
37
|
workingDirectory,
|
|
@@ -31,13 +41,12 @@ const genConfig = ({
|
|
|
31
41
|
cpu,
|
|
32
42
|
mem,
|
|
33
43
|
additionalEnv = [],
|
|
34
|
-
|
|
35
|
-
isProduction
|
|
44
|
+
region = "us-east-1",
|
|
45
|
+
isProduction,
|
|
36
46
|
}) => `
|
|
37
47
|
job "${jobName}" {
|
|
38
|
-
datacenters = ["${
|
|
48
|
+
datacenters = ["${region}"]
|
|
39
49
|
|
|
40
|
-
# Run this job as a "batch" type
|
|
41
50
|
type = "batch"
|
|
42
51
|
|
|
43
52
|
${
|
|
@@ -66,9 +75,7 @@ job "${jobName}" {
|
|
|
66
75
|
unlimited = false
|
|
67
76
|
}
|
|
68
77
|
|
|
69
|
-
|
|
70
|
-
isProduction
|
|
71
|
-
? `task "log-shipper" {
|
|
78
|
+
task "log-shipper" {
|
|
72
79
|
driver = "raw_exec"
|
|
73
80
|
|
|
74
81
|
config {
|
|
@@ -79,16 +86,13 @@ job "${jobName}" {
|
|
|
79
86
|
]
|
|
80
87
|
}
|
|
81
88
|
|
|
82
|
-
# It is possible to set environment variables which will be
|
|
83
|
-
# available to the task when it runs.
|
|
84
89
|
env {
|
|
85
|
-
${
|
|
90
|
+
SKYNET_ENVIRONMENT="${isProduction ? "prd" : "dev"}"
|
|
91
|
+
AWS_REGION="${region}"
|
|
86
92
|
}
|
|
87
93
|
|
|
88
94
|
kill_timeout = "120s"
|
|
89
95
|
|
|
90
|
-
# Specify the maximum resources required to run the task,
|
|
91
|
-
# include CPU and memory.
|
|
92
96
|
resources {
|
|
93
97
|
cpu = 100 # MHz
|
|
94
98
|
memory = 100 # MB
|
|
@@ -98,11 +102,9 @@ job "${jobName}" {
|
|
|
98
102
|
attempts = 3
|
|
99
103
|
mode = "fail"
|
|
100
104
|
}
|
|
101
|
-
}`
|
|
102
|
-
: ""
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
task "
|
|
107
|
+
task "main" {
|
|
106
108
|
driver = "raw_exec"
|
|
107
109
|
|
|
108
110
|
config {
|
|
@@ -113,10 +115,21 @@ job "${jobName}" {
|
|
|
113
115
|
]
|
|
114
116
|
}
|
|
115
117
|
|
|
118
|
+
template {
|
|
119
|
+
change_mode = "restart"
|
|
120
|
+
destination = "secrets/context.env"
|
|
121
|
+
env = true
|
|
122
|
+
|
|
123
|
+
data = <<EOH
|
|
124
|
+
${buildEnvTemplate(additionalEnv, isProduction)}
|
|
125
|
+
EOH
|
|
126
|
+
}
|
|
127
|
+
|
|
116
128
|
# It is possible to set environment variables which will be
|
|
117
129
|
# available to the task when it runs.
|
|
118
130
|
env {
|
|
119
|
-
${
|
|
131
|
+
SKYNET_ENVIRONMENT="${isProduction ? "prd" : "dev"}"
|
|
132
|
+
AWS_REGION="${region}"
|
|
120
133
|
}
|
|
121
134
|
|
|
122
135
|
# Specify the maximum resources required to run the task,
|
|
@@ -152,10 +165,10 @@ job "${jobName}" {
|
|
|
152
165
|
}
|
|
153
166
|
}`;
|
|
154
167
|
|
|
155
|
-
function getJobName(name, selectorFlags, mode = null
|
|
168
|
+
function getJobName(name, selectorFlags, mode = null) {
|
|
156
169
|
const selectorNamePart = Object.keys(selectorFlags)
|
|
157
170
|
.sort()
|
|
158
|
-
.map(name =>
|
|
171
|
+
.map((name) => selectorFlags[name])
|
|
159
172
|
.join("-");
|
|
160
173
|
|
|
161
174
|
let jobName = name;
|
|
@@ -168,14 +181,10 @@ function getJobName(name, selectorFlags, mode = null, periodic = false) {
|
|
|
168
181
|
jobName += `-${selectorNamePart}`;
|
|
169
182
|
}
|
|
170
183
|
|
|
171
|
-
if (periodic) {
|
|
172
|
-
jobName += `-periodic`;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
184
|
return jobName;
|
|
176
185
|
}
|
|
177
186
|
|
|
178
|
-
function getNomadAddr(isProduction) {
|
|
187
|
+
async function getNomadAddr(isProduction) {
|
|
179
188
|
let nomadAddr;
|
|
180
189
|
|
|
181
190
|
if (isProduction) {
|
|
@@ -183,18 +192,16 @@ function getNomadAddr(isProduction) {
|
|
|
183
192
|
|
|
184
193
|
nomadAddr = getEnvOrThrow("SKYNET_NOMAD_PRODUCTION_ADDR");
|
|
185
194
|
} else {
|
|
195
|
+
const skynetDir = detectSkynetDirectory();
|
|
196
|
+
|
|
197
|
+
if (!fso.existsSync("/tmp/skynet")) {
|
|
198
|
+
await execa("ln", ["-s", skynetDir, "/tmp/skynet"]);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
console.log("Deploy locally, please start nomad server in a separate terminal");
|
|
202
|
+
console.log(`You can start nomad server by running ${chalk.inverse(`${skynetDir}/infra-nomad/dev/start.sh`)}`);
|
|
186
203
|
console.log(
|
|
187
|
-
|
|
188
|
-
);
|
|
189
|
-
console.log(
|
|
190
|
-
`You can start nomad server by running ${chalk.inverse(
|
|
191
|
-
"cd <skynet-repo-root> && ln -s . /opt/certik/skynet && infra-nomad/dev/start.sh"
|
|
192
|
-
)}`
|
|
193
|
-
);
|
|
194
|
-
console.log(
|
|
195
|
-
`Then you can visit ${chalk.underline(
|
|
196
|
-
"http://localhost:4646/ui/jobs"
|
|
197
|
-
)} to check submitted dev jobs.\n`
|
|
204
|
+
`Then you can visit ${chalk.underline("http://localhost:4646/ui/jobs")} to check submitted dev jobs.\n`
|
|
198
205
|
);
|
|
199
206
|
|
|
200
207
|
nomadAddr = "http://127.0.0.1:4646";
|
|
@@ -203,31 +210,27 @@ function getNomadAddr(isProduction) {
|
|
|
203
210
|
return nomadAddr;
|
|
204
211
|
}
|
|
205
212
|
|
|
206
|
-
async function
|
|
207
|
-
let nomadPath;
|
|
208
|
-
|
|
213
|
+
async function getNomadPath() {
|
|
209
214
|
try {
|
|
210
|
-
|
|
215
|
+
return await which("nomad");
|
|
211
216
|
} catch (missingNomad) {
|
|
212
217
|
console.log(
|
|
213
|
-
`Deploy requires ${chalk.bold(
|
|
214
|
-
"nomad"
|
|
215
|
-
)} binary, please follow ${chalk.underline(
|
|
218
|
+
`Deploy requires ${chalk.bold("nomad")} binary, please follow ${chalk.underline(
|
|
216
219
|
"https://learn.hashicorp.com/tutorials/nomad/get-started-install"
|
|
217
220
|
)} for installation`
|
|
218
221
|
);
|
|
219
222
|
|
|
220
223
|
throw new Error("missing nomad binary");
|
|
221
224
|
}
|
|
225
|
+
}
|
|
222
226
|
|
|
223
|
-
|
|
224
|
-
|
|
227
|
+
async function runNomadJob(nomadPath, nomadAddr, jobName, nomadJobDefinition, isStop) {
|
|
225
228
|
try {
|
|
226
229
|
if (isStop) {
|
|
227
230
|
const nomad = execa(nomadPath, ["job", "stop", jobName], {
|
|
228
231
|
env: {
|
|
229
|
-
NOMAD_ADDR: nomadAddr
|
|
230
|
-
}
|
|
232
|
+
NOMAD_ADDR: nomadAddr,
|
|
233
|
+
},
|
|
231
234
|
});
|
|
232
235
|
nomad.stdout.pipe(process.stdout);
|
|
233
236
|
await nomad;
|
|
@@ -240,8 +243,8 @@ async function runNomadJob(jobName, nomadJobDefinition, isStop, isProduction) {
|
|
|
240
243
|
|
|
241
244
|
const nomad = execa(nomadPath, ["job", "run", jobFileName], {
|
|
242
245
|
env: {
|
|
243
|
-
NOMAD_ADDR: nomadAddr
|
|
244
|
-
}
|
|
246
|
+
NOMAD_ADDR: nomadAddr,
|
|
247
|
+
},
|
|
245
248
|
});
|
|
246
249
|
nomad.stdout.pipe(process.stdout);
|
|
247
250
|
await nomad;
|
|
@@ -249,10 +252,12 @@ async function runNomadJob(jobName, nomadJobDefinition, isStop, isProduction) {
|
|
|
249
252
|
console.log(chalk.green(`deployed ${jobName}`));
|
|
250
253
|
}
|
|
251
254
|
} catch (nomadExecErr) {
|
|
255
|
+
console.log("Nomad Execution Error:");
|
|
256
|
+
console.log(nomadExecErr.message);
|
|
257
|
+
console.log("");
|
|
258
|
+
|
|
252
259
|
console.log(
|
|
253
|
-
`Failed to run ${chalk.bold(
|
|
254
|
-
"nomad"
|
|
255
|
-
)} commands, please ensure nomad server is accessible at ${chalk.bold(
|
|
260
|
+
`Failed to run ${chalk.bold("nomad")} commands, please ensure nomad server is accessible at ${chalk.bold(
|
|
256
261
|
nomadAddr
|
|
257
262
|
)}`
|
|
258
263
|
);
|
|
@@ -262,106 +267,118 @@ async function runNomadJob(jobName, nomadJobDefinition, isStop, isProduction) {
|
|
|
262
267
|
}
|
|
263
268
|
|
|
264
269
|
function createModeDeploy({
|
|
270
|
+
binaryName,
|
|
265
271
|
name,
|
|
266
272
|
workingDirectory,
|
|
267
273
|
bin = "bin/indexer",
|
|
268
274
|
selector = {},
|
|
269
275
|
env = {},
|
|
276
|
+
region = "us-east-1",
|
|
277
|
+
check,
|
|
270
278
|
deltaSchedule,
|
|
271
279
|
validateSchedule,
|
|
272
280
|
deltaCpu,
|
|
273
281
|
deltaMem,
|
|
274
282
|
rebuildCpu,
|
|
275
|
-
rebuildMem
|
|
283
|
+
rebuildMem,
|
|
284
|
+
validateCpu,
|
|
285
|
+
validateMem,
|
|
276
286
|
}) {
|
|
277
|
-
async function deployMode({
|
|
278
|
-
mode,
|
|
279
|
-
from,
|
|
280
|
-
to,
|
|
281
|
-
stop,
|
|
282
|
-
production,
|
|
283
|
-
verbose,
|
|
284
|
-
...selectorFlags
|
|
285
|
-
}) {
|
|
287
|
+
async function deployMode({ mode, from, to, stop, production, verbose, ...selectorFlags }) {
|
|
286
288
|
if (mode === "delta") {
|
|
287
289
|
// delta mode will ignore from/to flags
|
|
288
290
|
from = 0;
|
|
289
291
|
to = 0;
|
|
290
292
|
}
|
|
291
293
|
|
|
292
|
-
const isPeriodic =
|
|
293
|
-
from === 0 && to === 0 && ["delta", "validate"].includes(mode);
|
|
294
|
+
const isPeriodic = from === 0 && to === 0 && ["delta", "validate"].includes(mode);
|
|
294
295
|
|
|
295
|
-
const jobName = getJobName(name, selectorFlags, mode
|
|
296
|
+
const jobName = getJobName(name, selectorFlags, mode);
|
|
296
297
|
|
|
297
298
|
const selectorCmdPart = Object.keys(selectorFlags)
|
|
298
299
|
.sort()
|
|
299
|
-
.map(name => `--${name} ${selectorFlags[name]}`)
|
|
300
|
+
.map((name) => `--${name} ${selectorFlags[name]}`)
|
|
300
301
|
.join(" ");
|
|
301
|
-
let
|
|
302
|
+
let args = `--mode ${mode} ${selectorCmdPart}`;
|
|
302
303
|
|
|
303
|
-
if (
|
|
304
|
-
|
|
304
|
+
if (verbose) {
|
|
305
|
+
args += ` --verbose`;
|
|
305
306
|
}
|
|
306
307
|
|
|
307
|
-
|
|
308
|
-
|
|
308
|
+
let rangeArgs = "";
|
|
309
|
+
|
|
310
|
+
if (from > 0) {
|
|
311
|
+
rangeArgs += ` --from ${from}`;
|
|
309
312
|
}
|
|
310
313
|
|
|
311
|
-
if (
|
|
312
|
-
|
|
314
|
+
if (to > 0) {
|
|
315
|
+
rangeArgs += ` --to ${to}`;
|
|
313
316
|
}
|
|
314
317
|
|
|
315
318
|
const modeResouces = {
|
|
316
319
|
rebuild: { cpu: rebuildCpu, mem: rebuildMem },
|
|
317
320
|
"resume-rebuild": { cpu: rebuildCpu, mem: rebuildMem },
|
|
318
|
-
validate: { cpu: rebuildCpu, mem: rebuildMem },
|
|
319
|
-
delta: { cpu: deltaCpu, mem: deltaMem }
|
|
321
|
+
validate: { cpu: validateCpu || rebuildCpu, mem: validateMem || rebuildMem },
|
|
322
|
+
delta: { cpu: deltaCpu, mem: deltaMem },
|
|
320
323
|
};
|
|
321
324
|
|
|
322
325
|
// by default use delta cpu/mem settings
|
|
323
326
|
const { cpu, mem } = modeResouces[mode] || modeResouces.delta;
|
|
324
327
|
|
|
325
|
-
const
|
|
326
|
-
"@secondly": "*/1 * * * * * *",
|
|
327
|
-
"@minutely": "0 * * * * * *",
|
|
328
|
-
"@hourly": "0 0 * * * * *",
|
|
329
|
-
"@daily": "0 0 0 * * * *",
|
|
330
|
-
"@weekly": "0 0 0 * * 0 *"
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
const deltaCron =
|
|
334
|
-
typeof deltaSchedule === "function"
|
|
335
|
-
? deltaSchedule(jobName)
|
|
336
|
-
: deltaSchedule;
|
|
328
|
+
const deltaCron = typeof deltaSchedule === "function" ? deltaSchedule(jobName) : deltaSchedule;
|
|
337
329
|
|
|
338
|
-
const validateCron =
|
|
339
|
-
typeof validateSchedule === "function"
|
|
340
|
-
? validateSchedule(jobName)
|
|
341
|
-
: validateSchedule;
|
|
330
|
+
const validateCron = typeof validateSchedule === "function" ? validateSchedule(jobName) : validateSchedule;
|
|
342
331
|
|
|
343
332
|
const modeIntervals = {
|
|
344
|
-
delta:
|
|
345
|
-
validate:
|
|
333
|
+
delta: INTERVAL_ALIASES[deltaCron] || deltaCron,
|
|
334
|
+
validate: INTERVAL_ALIASES[validateCron] || validateCron,
|
|
346
335
|
};
|
|
347
336
|
|
|
348
|
-
const
|
|
337
|
+
const mainJobDefinition = genConfig({
|
|
349
338
|
jobName,
|
|
350
339
|
cron: isPeriodic && modeIntervals[mode],
|
|
351
340
|
workingDirectory,
|
|
352
341
|
additionalEnv: env,
|
|
353
|
-
|
|
342
|
+
region,
|
|
343
|
+
cmd: `${bin} ${args} ${rangeArgs}`,
|
|
354
344
|
cpu,
|
|
355
345
|
mem,
|
|
356
|
-
isProduction: production
|
|
346
|
+
isProduction: production,
|
|
357
347
|
});
|
|
358
348
|
|
|
359
|
-
|
|
349
|
+
const nomadPath = await getNomadPath();
|
|
350
|
+
const nomadAddr = await getNomadAddr(production);
|
|
351
|
+
|
|
352
|
+
await runNomadJob(nomadPath, nomadAddr, jobName, mainJobDefinition, stop);
|
|
353
|
+
|
|
354
|
+
if (check && check.bin) {
|
|
355
|
+
console.log("");
|
|
356
|
+
|
|
357
|
+
const monitorJobName = `${jobName}-monitor`;
|
|
358
|
+
const monitorJobDefinition = genConfig({
|
|
359
|
+
jobName: monitorJobName,
|
|
360
|
+
cron: INTERVAL_ALIASES[check.schedule] || check.schedule,
|
|
361
|
+
workingDirectory,
|
|
362
|
+
additionalEnv: {
|
|
363
|
+
...env,
|
|
364
|
+
SKYNET_SLACK_TOKEN: null,
|
|
365
|
+
SKYNET_NOMAD_URL: null,
|
|
366
|
+
},
|
|
367
|
+
region,
|
|
368
|
+
cmd: `${check.bin} ${args}`,
|
|
369
|
+
cpu: check.cpu || 100,
|
|
370
|
+
mem: check.mem || 100,
|
|
371
|
+
isProduction: production,
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
await runNomadJob(nomadPath, nomadAddr, monitorJobName, monitorJobDefinition, stop);
|
|
375
|
+
}
|
|
360
376
|
}
|
|
361
377
|
|
|
362
378
|
function deploy() {
|
|
363
|
-
|
|
364
|
-
|
|
379
|
+
if (!binaryName) {
|
|
380
|
+
binaryName = getBinaryName();
|
|
381
|
+
}
|
|
365
382
|
|
|
366
383
|
const cli = meow(
|
|
367
384
|
`
|
|
@@ -389,36 +406,36 @@ ${getSelectorDesc(selector)}
|
|
|
389
406
|
...getSelectorFlags(selector),
|
|
390
407
|
mode: {
|
|
391
408
|
type: "string",
|
|
392
|
-
default: "delta"
|
|
409
|
+
default: "delta",
|
|
393
410
|
},
|
|
394
411
|
from: {
|
|
395
412
|
alias: "since",
|
|
396
413
|
type: "number",
|
|
397
|
-
default: 0
|
|
414
|
+
default: 0,
|
|
398
415
|
},
|
|
399
416
|
to: {
|
|
400
417
|
alias: "until",
|
|
401
418
|
type: "number",
|
|
402
|
-
default: 0
|
|
419
|
+
default: 0,
|
|
403
420
|
},
|
|
404
421
|
verbose: {
|
|
405
422
|
type: "boolean",
|
|
406
|
-
default: false
|
|
423
|
+
default: false,
|
|
407
424
|
},
|
|
408
425
|
production: {
|
|
409
426
|
alias: "prd",
|
|
410
427
|
type: "boolean",
|
|
411
|
-
default: false
|
|
428
|
+
default: false,
|
|
412
429
|
},
|
|
413
430
|
stop: {
|
|
414
431
|
type: "boolean",
|
|
415
|
-
default: false
|
|
416
|
-
}
|
|
417
|
-
}
|
|
432
|
+
default: false,
|
|
433
|
+
},
|
|
434
|
+
},
|
|
418
435
|
}
|
|
419
436
|
);
|
|
420
437
|
|
|
421
|
-
deployMode(cli.flags).catch(err => {
|
|
438
|
+
deployMode(cli.flags).catch((err) => {
|
|
422
439
|
console.error(err);
|
|
423
440
|
process.exit(1);
|
|
424
441
|
});
|
|
@@ -428,54 +445,81 @@ ${getSelectorDesc(selector)}
|
|
|
428
445
|
}
|
|
429
446
|
|
|
430
447
|
function createDeploy({
|
|
448
|
+
binaryName,
|
|
431
449
|
name,
|
|
432
450
|
workingDirectory,
|
|
433
451
|
bin = "bin/indexer",
|
|
434
452
|
selector = {},
|
|
453
|
+
region = "us-east-1",
|
|
435
454
|
env = {},
|
|
455
|
+
check,
|
|
436
456
|
schedule,
|
|
437
457
|
restart,
|
|
438
458
|
cpu,
|
|
439
|
-
mem
|
|
459
|
+
mem,
|
|
440
460
|
}) {
|
|
441
|
-
async function deployModeless({
|
|
442
|
-
|
|
443
|
-
stop,
|
|
444
|
-
verbose,
|
|
445
|
-
...selectorFlags
|
|
446
|
-
}) {
|
|
447
|
-
const jobName = getJobName(name, selectorFlags, null, !!schedule);
|
|
461
|
+
async function deployModeless({ production, stop, verbose, ...selectorFlags }) {
|
|
462
|
+
const jobName = getJobName(name, selectorFlags, null);
|
|
448
463
|
|
|
449
464
|
const selectorCmdPart = Object.keys(selectorFlags)
|
|
450
465
|
.sort()
|
|
451
|
-
.map(name => `--${name} ${selectorFlags[name]}`)
|
|
466
|
+
.map((name) => `--${name} ${selectorFlags[name]}`)
|
|
452
467
|
.join(" ");
|
|
453
|
-
let
|
|
468
|
+
let args = `${selectorCmdPart}`;
|
|
454
469
|
|
|
455
470
|
if (verbose) {
|
|
456
|
-
|
|
471
|
+
args += ` --verbose`;
|
|
457
472
|
}
|
|
458
473
|
|
|
459
474
|
const cron = typeof schedule === "function" ? schedule(jobName) : schedule;
|
|
460
475
|
|
|
461
476
|
const nomadJobDefinition = genConfig({
|
|
462
477
|
jobName,
|
|
463
|
-
cron,
|
|
478
|
+
cron: INTERVAL_ALIASES[cron] || cron,
|
|
464
479
|
restart,
|
|
465
480
|
workingDirectory,
|
|
466
481
|
additionalEnv: env,
|
|
467
|
-
|
|
482
|
+
region,
|
|
483
|
+
cmd: `${bin} ${args}`,
|
|
468
484
|
cpu,
|
|
469
485
|
mem,
|
|
470
|
-
|
|
486
|
+
check,
|
|
487
|
+
isProduction: production,
|
|
471
488
|
});
|
|
472
489
|
|
|
473
|
-
|
|
490
|
+
const nomadPath = await getNomadPath();
|
|
491
|
+
const nomadAddr = await getNomadAddr(production);
|
|
492
|
+
|
|
493
|
+
await runNomadJob(nomadPath, nomadAddr, jobName, nomadJobDefinition, stop);
|
|
494
|
+
|
|
495
|
+
if (check && check.bin) {
|
|
496
|
+
console.log("");
|
|
497
|
+
|
|
498
|
+
const monitorJobName = `${jobName}-monitor`;
|
|
499
|
+
const monitorJobDefinition = genConfig({
|
|
500
|
+
jobName: monitorJobName,
|
|
501
|
+
cron: INTERVAL_ALIASES[check.schedule] || check.schedule,
|
|
502
|
+
workingDirectory,
|
|
503
|
+
additionalEnv: {
|
|
504
|
+
...env,
|
|
505
|
+
SKYNET_SLACK_TOKEN: null,
|
|
506
|
+
SKYNET_NOMAD_URL: null,
|
|
507
|
+
},
|
|
508
|
+
region,
|
|
509
|
+
cmd: `${check.bin} ${args}`,
|
|
510
|
+
cpu: check.cpu || 100,
|
|
511
|
+
mem: check.mem || 100,
|
|
512
|
+
isProduction: production,
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
await runNomadJob(nomadPath, nomadAddr, monitorJobName, monitorJobDefinition, stop);
|
|
516
|
+
}
|
|
474
517
|
}
|
|
475
518
|
|
|
476
519
|
function deploy() {
|
|
477
|
-
|
|
478
|
-
|
|
520
|
+
if (!binaryName) {
|
|
521
|
+
binaryName = getBinaryName();
|
|
522
|
+
}
|
|
479
523
|
|
|
480
524
|
const cli = meow(
|
|
481
525
|
`
|
|
@@ -495,22 +539,22 @@ ${getSelectorDesc(selector)}
|
|
|
495
539
|
...getSelectorFlags(selector),
|
|
496
540
|
verbose: {
|
|
497
541
|
type: "boolean",
|
|
498
|
-
default: false
|
|
542
|
+
default: false,
|
|
499
543
|
},
|
|
500
544
|
production: {
|
|
501
545
|
alias: "prd",
|
|
502
546
|
type: "boolean",
|
|
503
|
-
default: false
|
|
547
|
+
default: false,
|
|
504
548
|
},
|
|
505
549
|
stop: {
|
|
506
550
|
type: "boolean",
|
|
507
|
-
default: false
|
|
508
|
-
}
|
|
509
|
-
}
|
|
551
|
+
default: false,
|
|
552
|
+
},
|
|
553
|
+
},
|
|
510
554
|
}
|
|
511
555
|
);
|
|
512
556
|
|
|
513
|
-
deployModeless(cli.flags).catch(err => {
|
|
557
|
+
deployModeless(cli.flags).catch((err) => {
|
|
514
558
|
console.error(err);
|
|
515
559
|
process.exit(1);
|
|
516
560
|
});
|
|
@@ -520,6 +564,7 @@ ${getSelectorDesc(selector)}
|
|
|
520
564
|
}
|
|
521
565
|
|
|
522
566
|
module.exports = {
|
|
567
|
+
getJobName,
|
|
523
568
|
createModeDeploy,
|
|
524
|
-
createDeploy
|
|
569
|
+
createDeploy,
|
|
525
570
|
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// this file is executable and is for kafka producer testing
|
|
4
|
+
// a few test commands to try on
|
|
5
|
+
// $ examples/consumer run --protocol bsc --verbose
|
|
6
|
+
// $ examples/consumer run --protocol eth
|
|
7
|
+
// $ examples/consumer check --protocol eth
|
|
8
|
+
// $ examples/consumer deploy --protocol eth
|
|
9
|
+
// $ examples/consumer --help
|
|
10
|
+
|
|
11
|
+
const { consumer, SENSITIVE_VALUE, ERROR_LEVEL } = require("../app");
|
|
12
|
+
|
|
13
|
+
async function consume({ protocol, messages, verbose }) {
|
|
14
|
+
console.log("consume called with", protocol, messages, verbose);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function check({ protocol, state, verbose }) {
|
|
18
|
+
console.log("check called with", protocol, state, verbose);
|
|
19
|
+
|
|
20
|
+
const errors = [];
|
|
21
|
+
|
|
22
|
+
errors.push({ type: ERROR_LEVEL.CRITICAL, message: "processed height lagged behind" });
|
|
23
|
+
|
|
24
|
+
return errors;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const app = consumer({
|
|
28
|
+
name: "LibSkynetExampleConsumer",
|
|
29
|
+
selector: { protocol: { type: "string" } },
|
|
30
|
+
|
|
31
|
+
env: {
|
|
32
|
+
SKYNET_KAFKA_SERVER: SENSITIVE_VALUE,
|
|
33
|
+
SKYNET_KAFKA_USERNAME: SENSITIVE_VALUE,
|
|
34
|
+
SKYNET_KAFKA_PASSWORD: SENSITIVE_VALUE,
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
consume: {
|
|
38
|
+
func: consume,
|
|
39
|
+
topic: ({ protocol }) => `lib-skynet-test-kafka-${protocol}-dev`,
|
|
40
|
+
maxRetry: 1,
|
|
41
|
+
|
|
42
|
+
cpu: 600,
|
|
43
|
+
mem: 200,
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
check: {
|
|
47
|
+
func: check,
|
|
48
|
+
schedule: "@minutely",
|
|
49
|
+
slackChannel: "skynet-notifications-local-dev",
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
app();
|