feat: insert stress testing machines into DB
This commit is contained in:
parent
0a120203be
commit
99dd90d51a
5 changed files with 74 additions and 41 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
const cp = require('node:child_process')
|
const { spawnSync } = require('node:child_process')
|
||||||
const path = require('node:path')
|
const { join } = require('node:path')
|
||||||
|
|
||||||
require('../../lib/environment-helper')
|
require('../../lib/environment-helper')
|
||||||
const db = require('../../lib/db')
|
const db = require('../../lib/db')
|
||||||
|
|
@ -23,8 +23,8 @@ const help = (exit_code) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const migrate = async () => {
|
const migrate = async () => {
|
||||||
const lamassu_migrate_path = path.join(__dirname, "../../bin/lamassu-migrate")
|
const lamassu_migrate_path = join(__dirname, "../../bin/lamassu-migrate")
|
||||||
const { stdout, stderr, status, signal, error } = cp.spawnSync(lamassu_migrate_path, [], {
|
const { stdout, stderr, status, signal, error } = spawnSync(lamassu_migrate_path, [], {
|
||||||
cwd: process.cwd(),
|
cwd: process.cwd(),
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
const fs = require('node:fs')
|
const { readFileSync, writeFileSync } = require('node:fs')
|
||||||
const os = require('node:os')
|
const { EOL } = require('node:os')
|
||||||
const path = require('node:path')
|
const { resolve } = require('node:path')
|
||||||
|
|
||||||
const dotenv = require('dotenv')
|
const dotenv = require('dotenv')
|
||||||
|
|
||||||
|
|
@ -30,10 +30,10 @@ const help = (exit_code) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const env_read = (path) => {
|
const env_read = (path) => {
|
||||||
const envstr = fs.readFileSync(path, { encoding: 'utf8' })
|
const envstr = readFileSync(path, { encoding: 'utf8' })
|
||||||
return dotenv.parse(envstr)
|
return dotenv.parse(envstr)
|
||||||
//const entries = envstr
|
//const entries = envstr
|
||||||
// .split(os.EOL)
|
// .split(EOL)
|
||||||
// .flatMap((line) => {
|
// .flatMap((line) => {
|
||||||
// line = line.trimStart()
|
// line = line.trimStart()
|
||||||
// const i = line.indexOf('=')
|
// const i = line.indexOf('=')
|
||||||
|
|
@ -51,8 +51,8 @@ const env_read = (path) => {
|
||||||
const env_write = (envvars, path) => {
|
const env_write = (envvars, path) => {
|
||||||
const envcontent = Object.entries(envvars)
|
const envcontent = Object.entries(envvars)
|
||||||
.map(([varname, value]) => [varname, value].join('='))
|
.map(([varname, value]) => [varname, value].join('='))
|
||||||
.join(os.EOL) + os.EOL
|
.join(EOL) + EOL
|
||||||
fs.writeFileSync(path, envcontent)
|
writeFileSync(path, envcontent)
|
||||||
}
|
}
|
||||||
|
|
||||||
const run = async (args) => {
|
const run = async (args) => {
|
||||||
|
|
@ -70,10 +70,10 @@ const run = async (args) => {
|
||||||
return help(EXIT.BADARGS)
|
return help(EXIT.BADARGS)
|
||||||
}
|
}
|
||||||
|
|
||||||
const inenvpath = path.resolve(process.cwd(), options.inenv ?? ".env")
|
const inenvpath = resolve(process.cwd(), options.inenv ?? ".env")
|
||||||
const inenvvars = env_read(inenvpath)
|
const inenvvars = env_read(inenvpath)
|
||||||
|
|
||||||
const outenvpath = path.resolve(process.cwd(), options.outenv ?? ".stress.env")
|
const outenvpath = resolve(process.cwd(), options.outenv ?? ".stress.env")
|
||||||
const outenvvars = {
|
const outenvvars = {
|
||||||
...inenvvars,
|
...inenvvars,
|
||||||
POSTGRES_USER: options.dbuser ?? "postgres",
|
POSTGRES_USER: options.dbuser ?? "postgres",
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,14 @@ on each subcommand.
|
||||||
|
|
||||||
First of all, you need to create a suitable .env file. With the following
|
First of all, you need to create a suitable .env file. With the following
|
||||||
commands, .env.bak will be used as a starting point, and the result will be
|
commands, .env.bak will be used as a starting point, and the result will be
|
||||||
saved in .env. This is to avoid losing the real configurations.
|
saved in .env. This helps to avoid losing the real configurations.
|
||||||
|
|
||||||
$ cp .env .env.bak
|
$ cp .env .env.bak
|
||||||
$ lamassu-server-stress-testing env --inenv .env.bak --outenv .env
|
$ lamassu-server-stress-testing env --inenv .env.bak --outenv .env
|
||||||
|
|
||||||
The database chosen in the command above (by default lamassu_stress)
|
The database chosen in the command above (by default 'lamassu_stress') must be
|
||||||
must be initialized, and must have a bare-bones configuration. The following
|
initialized, and must have a bare-bones configuration. The following command
|
||||||
command does that:
|
takes care of it:
|
||||||
|
|
||||||
$ lamassu-server-stress-testing db
|
$ lamassu-server-stress-testing db
|
||||||
|
|
||||||
|
|
@ -34,15 +34,22 @@ following command creates 10 fake machines, and saves their data in
|
||||||
path/to/stress/data/. path/to/real/machine/code/ is the path to the root of the
|
path/to/stress/data/. path/to/real/machine/code/ is the path to the root of the
|
||||||
machine's code.
|
machine's code.
|
||||||
|
|
||||||
$ lamassu-server-stress-testing machines -n 10 --fake_data_dir path/to/stress/data/ --machine path/to/real/machine/code/
|
$ lamassu-server-stress-testing machines -n 10 --fake_data_dir path/to/stress/data/ --machine path/to/real/machine/code/ --replace_existing
|
||||||
|
|
||||||
|
Finally, use the following to start the lamassu-server in stress-testing mode:
|
||||||
|
|
||||||
|
$ lamassu-server-stress-testing server
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const rightpad = (s, w, c) => s + c.repeat(Math.max(w-s.length, 0))
|
||||||
|
|
||||||
const help = (exit_code) => {
|
const help = (exit_code) => {
|
||||||
console.log("Usage: lamassu-server-stress-testing SUBCMD ARGS...",)
|
console.log("Usage: lamassu-server-stress-testing SUBCMD ARGS...")
|
||||||
console.log("Where SUBCMD is one of the following:")
|
console.log("Where SUBCMD is one of the following:")
|
||||||
|
const max_subcmd_length = Math.max(...Object.keys(SUBCMDS).map(subcmd => subcmd.length))
|
||||||
Object.entries(SUBCMDS).forEach(
|
Object.entries(SUBCMDS).forEach(
|
||||||
([subcmd, { help_message }]) => {
|
([subcmd, { help_message }]) => {
|
||||||
console.log(`\t${subcmd}\t${help_message ?? ''}`)
|
console.log(`\t${rightpad(subcmd, max_subcmd_length, ' ')}\t${help_message ?? ''}`)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,16 @@
|
||||||
const cp = require('node:child_process')
|
const { fork } = require('node:child_process')
|
||||||
const fs = require('node:fs')
|
const { createHash } = require('node:crypto')
|
||||||
const path = require('node:path')
|
const { mkdirSync, rmSync } = require('node:fs')
|
||||||
|
const { readFile } = require('node:fs/promises')
|
||||||
|
const { join } = require('node:path')
|
||||||
|
|
||||||
|
require('../../lib/environment-helper')
|
||||||
|
const db = require('../../lib/db')
|
||||||
|
|
||||||
const { EXIT } = require('./consts')
|
const { EXIT } = require('./consts')
|
||||||
const CLI = require('./cli')
|
const CLI = require('./cli')
|
||||||
|
|
||||||
const help_message = "Setup fake machines to be used as stress test clients."
|
const help_message = "Create and insert fake machines into the DB."
|
||||||
|
|
||||||
const cli = CLI({
|
const cli = CLI({
|
||||||
grammar: [
|
grammar: [
|
||||||
|
|
@ -13,6 +18,7 @@ const cli = CLI({
|
||||||
[["--machine", "PATH"], "Path to the machine's source code root"],
|
[["--machine", "PATH"], "Path to the machine's source code root"],
|
||||||
[["--fake_data_dir", "PATH"], "Where to save the fake machines' data"],
|
[["--fake_data_dir", "PATH"], "Where to save the fake machines' data"],
|
||||||
[["-n", "NUMBER"], "Number of fake machines to create"],
|
[["-n", "NUMBER"], "Number of fake machines to create"],
|
||||||
|
[["--replace_existing"], "Remove machines of previous runs"],
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -23,13 +29,19 @@ const help = (exit_code) => {
|
||||||
return exit_code
|
return exit_code
|
||||||
}
|
}
|
||||||
|
|
||||||
const create_fake_machine = async (gencerts_path, fake_data_dir, i) =>
|
const compute_machine_id = pem_path => (
|
||||||
|
readFile(pem_path, { encoding: 'utf8' })
|
||||||
|
.then(cert => cert.split('\r\n'))
|
||||||
|
.then(cert => Buffer.from(cert.slice(1, cert.length-2).join(''), 'base64'))
|
||||||
|
.then(raw => createHash('sha256').update(raw).digest('hex'))
|
||||||
|
)
|
||||||
|
|
||||||
|
const create_fake_machine = async (gencerts_path, machine_data_dir, i) => (
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
const machine_data_dir = path.join(fake_data_dir, i.toString())
|
mkdirSync(machine_data_dir, { recursive: true, mode: 0o750 })
|
||||||
fs.mkdirSync(machine_data_dir, { recursive: true, mode: 0o750 })
|
|
||||||
|
|
||||||
console.log("Creating fake machine number", i)
|
console.log("Creating fake machine number", i)
|
||||||
const gc = cp.fork(gencerts_path, [machine_data_dir], {
|
const gc = fork(gencerts_path, [machine_data_dir], {
|
||||||
cwd: process.cwd(),
|
cwd: process.cwd(),
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
})
|
})
|
||||||
|
|
@ -45,26 +57,40 @@ const create_fake_machine = async (gencerts_path, fake_data_dir, i) =>
|
||||||
resolve(typeof(code) === 'number' ? code : EXIT.EXCEPTION)
|
resolve(typeof(code) === 'number' ? code : EXIT.EXCEPTION)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
)
|
||||||
|
|
||||||
const create_fake_machines = async ({ machine, fake_data_dir, n }) => {
|
const create_fake_machines = async ({ machine, fake_data_dir, n, replace_existing }) => {
|
||||||
n = parseInt(n)
|
n = parseInt(n)
|
||||||
if (Number.isNaN(n) || n <= 0) {
|
if (Number.isNaN(n) || n <= 0) {
|
||||||
console.error("Expected n to be a positive number, got", n)
|
console.error("Expected n to be a positive number, got", n)
|
||||||
return help(EXIT.BADARGS)
|
return help(EXIT.BADARGS)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Remove all data of previous machines? */
|
if (replace_existing) {
|
||||||
//fs.rmSync(fake_data_dir, { recursive: true, force: true })
|
rmSync(fake_data_dir, { recursive: true, force: true })
|
||||||
|
await db.none("DELETE FROM devices")
|
||||||
|
}
|
||||||
|
|
||||||
/* Create the root data directory */
|
/* Create the root data directory */
|
||||||
fs.mkdirSync(fake_data_dir, { recursive: true, mode: 0o750 })
|
mkdirSync(fake_data_dir, { recursive: true, mode: 0o750 })
|
||||||
|
|
||||||
const gencerts_path = path.join(machine, "tools", "generate-certificates")
|
const gencerts_path = join(machine, "tools", "generate-certificates")
|
||||||
let exit_code = EXIT.OK
|
for (let i = 0; i < n; i++) {
|
||||||
for (let i = 0; i < n && exit_code === EXIT.OK; i++)
|
const machine_data_dir = join(fake_data_dir, i.toString())
|
||||||
exit_code = await create_fake_machine(gencerts_path, fake_data_dir, i)
|
const exit_code = await create_fake_machine(gencerts_path, machine_data_dir, i)
|
||||||
|
if (exit_code !== EXIT.OK)
|
||||||
|
return exit_code
|
||||||
|
|
||||||
return exit_code
|
const device_id = await compute_machine_id(join(machine_data_dir, "client.pem"))
|
||||||
|
|
||||||
|
await db.none(
|
||||||
|
`INSERT INTO devices (device_id, cassette1, cassette2, paired, display, created, name, last_online, location)
|
||||||
|
VALUES ($1, 0, 0, 't', 't', now(), $2, now(), '{}'::json)`,
|
||||||
|
[device_id, `machine_${i}`]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT.OK
|
||||||
}
|
}
|
||||||
|
|
||||||
const run = async (args) => {
|
const run = async (args) => {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
const cp = require('node:child_process')
|
const { fork } = require('node:child_process')
|
||||||
const path = require('node:path')
|
const { join } = require('node:path')
|
||||||
|
|
||||||
const { EXIT } = require('./consts')
|
const { EXIT } = require('./consts')
|
||||||
const CLI = require('./cli')
|
const CLI = require('./cli')
|
||||||
|
|
@ -21,8 +21,8 @@ const help = (exit_code) => {
|
||||||
|
|
||||||
const start_server = (args) =>
|
const start_server = (args) =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
const lamassu_server = path.join(__dirname, "../../bin/lamassu-server")
|
const lamassu_server = join(__dirname, "../../bin/lamassu-server")
|
||||||
const ls = cp.fork(lamassu_server, args, {
|
const ls = fork(lamassu_server, args, {
|
||||||
cwd: process.cwd(),
|
cwd: process.cwd(),
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
env: { LAMASSU_STRESS_TESTING: "YES" },
|
env: { LAMASSU_STRESS_TESTING: "YES" },
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue