Skip to content

Commit

Permalink
feat: add cluster db commands, update images on up, add compose cmd (#95
Browse files Browse the repository at this point in the history
)

* feat: add cluster db commands, update images on up, add compose cmd

* chore: make sure we are catching errors at the CLI entrypoints

* fix: use spawn with inherited stdio for local tty

* fix: update help text and fix duplicated aliases
  • Loading branch information
amcgee authored Jul 2, 2019
1 parent 609812b commit 7dd4fc1
Show file tree
Hide file tree
Showing 11 changed files with 314 additions and 82 deletions.
61 changes: 61 additions & 0 deletions packages/cluster/src/commands/compose.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const path = require('path')
const { spawn } = require('child_process')
const { reporter, tryCatchAsync } = require('@dhis2/cli-helpers-engine')
const {
initDockerComposeCache,
makeComposeProject,
makeEnvironment,
resolveConfiguration,
} = require('../common')

const run = async function(argv) {
const { name, _ } = argv
const cfg = await resolveConfiguration(argv)

const args = _.slice(_.findIndex(x => x === 'compose') + 1)
reporter.debug('Passing arguments to docker-compose', args)

const cacheLocation = await initDockerComposeCache({
composeProjectName: name,
cache: argv.getCache(),
dockerComposeRepository: cfg.dockerComposeRepository,
dockerComposeDirectory: cfg.dockerComposeDirectory,
force: false,
})
if (!cacheLocation) {
reporter.error('Failed to initialize cache...')
process.exit(1)
}
const res = await tryCatchAsync(
'exec(docker-compose)',
spawn(
'docker-compose',
[
'-p',
makeComposeProject(name),
'-f',
path.join(cacheLocation, 'docker-compose.yml'),
...args,
],
{
env: {
...process.env,
...makeEnvironment(cfg),
},
stdio: 'inherit',
}
)
)
if (res.err) {
reporter.error('Failed to run docker-compose command')
process.exit(1)
}
}

module.exports = {
command: 'compose <name>',
desc:
'Run arbitrary docker-compose commands against a DHIS2 cluster.\nNOTE: pass -- after <name>',
aliases: 'c',
handler: run,
}
11 changes: 11 additions & 0 deletions packages/cluster/src/commands/db.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const { namespace } = require('@dhis2/cli-helpers-engine')

const command = namespace('db', {
desc: 'Manage the database in a DHIS2 Docker cluster',
builder: yargs =>
yargs.commandDir('db_cmds').parserConfiguration({
'parse-numbers': false,
}),
})

module.exports = command
51 changes: 51 additions & 0 deletions packages/cluster/src/commands/db_cmds/backup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
const { reporter, tryCatchAsync } = require('@dhis2/cli-helpers-engine')
const { initDockerComposeCache, resolveConfiguration } = require('../../common')
const { backup } = require('../../helpers/db')

const run = async function(argv) {
const { name, getCache, path, fat } = argv

const cfg = await resolveConfiguration(argv)

const cacheLocation = await initDockerComposeCache({
composeProjectName: name,
cache: getCache(),
dockerComposeRepository: cfg.dockerComposeRepository,
dockerComposeDirectory: cfg.dockerComposeDirectory,
force: false,
})

if (!cacheLocation) {
reporter.error('Failed to initialize cache...')
process.exit(1)
}

const res = await tryCatchAsync(
'db::backup',
backup({
name,
cacheLocation,
path,
fat,
})
)

if (res.err) {
reporter.error('Failed to backup database')
reporter.debugErr(res.err)
process.exit(1)
}
}

module.exports = {
command: 'backup <name> <path>',
desc: 'Backup the database to a file',
builder: {
fat: {
desc: 'Force re-download of cached files',
type: 'boolean',
default: false,
},
},
handler: run,
}
56 changes: 56 additions & 0 deletions packages/cluster/src/commands/db_cmds/restore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
const { reporter, tryCatchAsync } = require('@dhis2/cli-helpers-engine')
const { initDockerComposeCache, resolveConfiguration } = require('../../common')
const { restore } = require('../../helpers/db')

const run = async function(argv) {
const { name, getCache } = argv

const cfg = await resolveConfiguration(argv)

const cacheLocation = await initDockerComposeCache({
composeProjectName: name,
cache: getCache(),
dockerComposeRepository: cfg.dockerComposeRepository,
dockerComposeDirectory: cfg.dockerComposeDirectory,
force: false,
})

if (!cacheLocation) {
reporter.error('Failed to initialize cache...')
process.exit(1)
}

const rest = await tryCatchAsync(
'db::restore',
restore({
cacheLocation,
dbVersion: cfg.dbVersion,
url: cfg.demoDatabaseURL,
...argv,
})
)

if (res.err) {
reporter.error('Failed to restore database')
reporter.debugErr(res.err)
process.exit(1)
}
}

module.exports = {
command: 'restore <name> [path]',
desc: 'Restore the database from a backup',
builder: {
update: {
alias: 'u',
desc: 'Force re-download of cached files',
type: 'boolean',
default: false,
},
dbVersion: {
desc: 'Version of the Database dump to use',
type: 'string',
},
},
handler: run,
}
2 changes: 1 addition & 1 deletion packages/cluster/src/commands/logs.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,6 @@ const run = async function(argv) {
module.exports = {
command: 'logs <name> [service]',
desc: 'Tail the logs from a given service',
aliases: 'r',
aliases: 'l',
handler: run,
}
6 changes: 3 additions & 3 deletions packages/cluster/src/commands/seed.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { reporter } = require('@dhis2/cli-helpers-engine')
const { initDockerComposeCache, resolveConfiguration } = require('../common')
const { seed } = require('../db')
const { restore } = require('../helpers/db')

const run = async function(argv) {
const { name, getCache } = argv
Expand All @@ -20,7 +20,7 @@ const run = async function(argv) {
process.exit(1)
}

return await seed({
return await restore({
cacheLocation,
dbVersion: cfg.dbVersion,
url: cfg.demoDatabaseURL,
Expand All @@ -30,7 +30,7 @@ const run = async function(argv) {

module.exports = {
command: 'seed <name> [path]',
desc: 'Seed the database from a backup',
desc: false, // Deprecated, so hide from help
builder: {
update: {
alias: '-u',
Expand Down
27 changes: 25 additions & 2 deletions packages/cluster/src/commands/up.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const {
} = require('../common')

const defaults = require('../defaults')
const { seed: doSeed } = require('../db')
const { restore } = require('../helpers/db')

const run = async function(argv) {
const { name, seed, seedFile, update, getCache } = argv
Expand All @@ -29,8 +29,31 @@ const run = async function(argv) {
process.exit(1)
}

if (update) {
reporter.info('Pulling latest Docker images...')
const res = await tryCatchAsync(
'exec(docker-compose)::pull',
exec({
env: makeEnvironment(cfg),
cmd: 'docker-compose',
args: [
'-p',
makeComposeProject(name),
'-f',
path.join(cacheLocation, 'docker-compose.yml'),
'pull',
],
pipe: false,
})
)
if (res.err) {
reporter.error('Failed to pull latest Docker images')
process.exit(1)
}
}

if (seed || seedFile) {
await doSeed({
await restore({
name,
cacheLocation,
dbVersion: cfg.dbVersion,
Expand Down
76 changes: 0 additions & 76 deletions packages/cluster/src/db.js

This file was deleted.

36 changes: 36 additions & 0 deletions packages/cluster/src/helpers/db/backup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const { makeComposeProject } = require('../../common')
const chalk = require('chalk')
const path = require('path')
const { reporter, exec } = require('@dhis2/cli-helpers-engine')

module.exports = async ({ cacheLocation, name, path: dbPath, fat }) => {
const destinationFile = path.resolve(dbPath)
const composeProject = makeComposeProject(name)

reporter.info(`Backing up database (this may take some time)...`)
reporter.debug(`Dumping database to ${chalk.bold(destinationFile)}`)

if (fat) {
reporter.info(
`Performing fat backup, ${chalk.bold(
'including'
)} Analytics and Resource tables`
)
} else {
reporter.info(
`Performing lean backup, ${chalk.bold(
'excluding'
)} Analytics and Resource tables`
)
}

await exec({
cmd: './scripts/backup.sh',
cwd: cacheLocation,
args: [destinationFile, fat ? 'full' : ''],
pipe: false,
env: {
DOCKER_COMPOSE: `docker-compose -p ${composeProject}`,
},
})
}
2 changes: 2 additions & 0 deletions packages/cluster/src/helpers/db/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module.exports.backup = require('./backup')
module.exports.restore = require('./restore')
Loading

0 comments on commit 7dd4fc1

Please sign in to comment.