draig-car
Version:
Database REST API interactive generator CLI and REPL OpenAPI3 based JS generator with interactive ORM/ODM REPL
159 lines (151 loc) • 4.49 kB
JavaScript
const chalk = require('chalk')
const { Readable } = require('stream')
const { Docker } = require('node-docker-api')
const docker = new Docker()
const u = require('../../util')
const ccfg = require('../../cfg/container')(u.loadConfig())
async function findImage(client) {
const images = await docker.image.list()
return images.find(i => i.data.RepoTags.find(n => n === ccfg[client].img))
}
async function findContainer(cont) {
const conts = await docker.container.list({ all: true })
return conts.find(c => c.data.Names[0].endsWith(cont))
}
module.exports = {
async runContainer(ctx) {
const client = ctx.argv.dbclient
let dbc = 'draigdb-' + client
let mycont = await findContainer(dbc)
if (mycont) {
console.warn(
chalk`Container {green ${dbc}} already exists - ` +
"Existing user's schema/DB will be discarded"
)
return mycont
}
console.info(
chalk`Creating container {green ${dbc}} with image` +
chalk` {green ${ccfg[client].img}}`
)
mycont = await docker.container.create({
name: dbc,
env: ccfg[client].env,
Image: ccfg[client].img,
HostConfig: {
NetworkMode: 'default',
PortBindings: {
[`${ccfg[client].port}/tcp`]: [ { HostPort: `${ccfg[client].port}` } ]
}
},
Ulimits: [{ Name: 'core', Hard: 0, Soft: 0 }]
})
await mycont.start()
const state = (await mycont.status()).data.State.Status
if (state !== 'running') {
console.error(
chalk`{red ERROR}: Container {green ${dbc}} did not started - ` +
chalk`State: {green ${state}}`
)
} else {
console.log(
chalk`Waiting {green ${ccfg[client].t}} seconds for the DB to start up`
)
await new Promise(r => setTimeout(r, 1000 * ccfg[client].t))
return mycont
}
},
async execInContainer(mycont, ctx) {
const client = ctx.argv.dbclient
const ex = await mycont.exec.create({
Tty: false,
AttachStdin: true,
AttachStdout: true,
AttachStderr: true,
Cmd: ccfg[client].cmd
})
console.log(chalk`(Re)creating {green client} schema/db...`)
const stream = await ex.start({ hijack: true, stdin: true })
const readable = Readable.from(ccfg[client].lines.map(l => l + '\n'))
docker.modem.demuxStream(stream, process.stdout, process.stderr)
readable.pipe(stream)
return new Promise((resolve, reject) => {
stream.on('end', () => {
if (!ctx.argv._.includes('run')) {
require('../../init').initCtx(ctx, ctx.argv)
console.log(
chalk`{yellow WARN}: Now you will need to run ` +
chalk`{green generate, migrate} and {green seed} to ` +
'restore your schema/tables and data !'
)
}
resolve()
})
})
},
async contAction(ctx, reqState, actionLabel) {
let dbc = 'draigdb-' + ctx.argv.dbclient
try {
const mycont = await findContainer(dbc)
if (mycont) {
const state = mycont.data.State
if (state !== reqState) {
console.info(
chalk`${actionLabel} ${state} container {green ${dbc}}`
)
const result =
reqState === 'running'
? await mycont.start().then(c => c.status())
: await mycont.stop().then(c => c.status())
console.log(chalk`New status: {green ${result.data.State.Status}}`)
} else {
console.warn(chalk`Container {green ${dbc}} yet in state ${state}`)
}
} else {
console.error(
chalk`{red ERROR}: Container {green ${dbc}} does not exist - ` +
chalk`Try {green resetdb} command`
)
}
} catch (e) {
console.error(
chalk`{red ERROR}: ${e.message} - ` +
'Please, make sure that docker service is running'
)
}
},
async pullImage(client) {
if (await findImage(client)) return
console.warn(
chalk`Image {green ${ccfg[client].img}} for {green ${client}} not found -` +
' Please, wait while the image is downloaded'
)
let stream = await docker.image.create(
{},
{ fromImage: ccfg[client].img }
)
await new Promise((resolve, reject) => {
docker.modem.followProgress(
stream,
err => {
process.stdout.write('\n')
if (err) {
console.error(
chalk`{red ERROR}: ${ccfg[client].img} failed - ${err}`
)
reject(false)
} else {
console.log(chalk`Image {green ${ccfg[client].img}} pulled OK`)
resolve(true)
}
},
event => {
var outputMessage = event.status
if (event.id) outputMessage += ': ' + event.id
if (event.progress) outputMessage += ' ' + event.progress
process.stdout.write(outputMessage + ' \r')
}
)
})
}
}