@bowtie/cli
Advanced tools
Comparing version 0.0.5 to 0.1.0
{ | ||
"name": "@bowtie/cli", | ||
"version": "0.0.5", | ||
"version": "0.1.0", | ||
"description": "Internal BowTie CLI Tools", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -7,73 +7,68 @@ const http = require('http'); | ||
module.exports = ({ cli, info }) => { | ||
return new Promise((resolve, reject) => { | ||
if (!info.context.dockerCompose) { | ||
return reject(`Current directory: '${info.cwd}' has no 'docker-compose.yml' file`); | ||
} | ||
module.exports = ({ cli, info, args }) => { | ||
if (!info.context.dockerCompose) { | ||
cli.error(`Current directory: '${info.cwd}' has no 'docker-compose.yml' file`); | ||
} | ||
const times = {}; | ||
const times = {}; | ||
cli.log('Begin Benchmark'); | ||
cli.log('Begin Benchmark'); | ||
times.build = {}; | ||
times.build = {}; | ||
times.build.start = Date.now(); | ||
times.build.start = Date.now(); | ||
shell.exec('docker-compose build'); | ||
shell.exec('docker-compose build'); | ||
times.build.end = Date.now(); | ||
times.build.end = Date.now(); | ||
if (info.context.rails) { | ||
times.reset = {}; | ||
times.reset.start = Date.now(); | ||
shell.exec('docker-compose run app bundle exec rake db:reset'); | ||
times.reset.end = Date.now(); | ||
} | ||
if (info.context.rails) { | ||
times.reset = {}; | ||
times.reset.start = Date.now(); | ||
shell.exec('docker-compose run app bundle exec rake db:reset'); | ||
times.up = {}; | ||
times.reset.end = Date.now(); | ||
} | ||
times.up.start = Date.now(); | ||
times.up = {}; | ||
shell.exec('docker-compose up -d'); | ||
times.up.start = Date.now(); | ||
let responseCode; | ||
shell.exec('docker-compose up -d'); | ||
async.whilst( | ||
() => { return responseCode !== 200; }, | ||
(callback) => { | ||
http.get('http://localhost', (res) => { | ||
responseCode = res.statusCode; | ||
let responseCode; | ||
callback(); | ||
}).on('error', (e) => { | ||
callback(); | ||
}); | ||
}, | ||
(err) => { | ||
if (err) { | ||
cli.warn(err); | ||
reject(err); | ||
} else { | ||
times.up.end = Date.now(); | ||
async.whilst( | ||
() => { return responseCode !== 200; }, | ||
(callback) => { | ||
http.get('http://localhost', (res) => { | ||
responseCode = res.statusCode; | ||
let report = 'Benchmark Report:'; | ||
callback(); | ||
}).on('error', (e) => { | ||
callback(); | ||
}); | ||
}, | ||
(err) => { | ||
if (err) { | ||
cli.error(err); | ||
} else { | ||
times.up.end = Date.now(); | ||
Object.keys(times).forEach(partName => { | ||
const partTimes = times[partName]; | ||
let report = 'Benchmark Report:'; | ||
const duration = (partTimes.end -partTimes.start) / 1000; | ||
Object.keys(times).forEach(partName => { | ||
const partTimes = times[partName]; | ||
report += `\n${partName} time => ${duration}s`; | ||
}); | ||
const duration = (partTimes.end -partTimes.start) / 1000; | ||
cli.success(report); | ||
resolve(); | ||
} | ||
report += `\n${partName} time => ${duration}s`; | ||
}); | ||
cli.success(report); | ||
} | ||
); | ||
}); | ||
} | ||
); | ||
}; |
@@ -1,13 +0,9 @@ | ||
const shell = require('shelljs'); | ||
const dockerCompose = require('./dockerCompose') | ||
module.exports = ({ cli, info }) => { | ||
return new Promise((resolve, reject) => { | ||
if (!info.context.dockerCompose) { | ||
return reject(`Current directory: '${info.cwd}' has no 'docker-compose.yml' file`); | ||
} | ||
module.exports = (opts) => { | ||
opts.args.unshift('build') | ||
shell.exec('docker-compose build'); | ||
dockerCompose(opts) | ||
resolve(); | ||
}); | ||
opts.args.shift() | ||
}; |
const shell = require('shelljs'); | ||
const path = require('path'); | ||
module.exports = ({ cli, info }) => { | ||
return new Promise((resolve, reject) => { | ||
let keyword = false; | ||
let response = ''; | ||
module.exports = ({ cli, info, args }) => { | ||
let keyword = false; | ||
let response = ''; | ||
if (info.context.dockerCompose) { | ||
cli.log(`Current directory: ${info.cwd} is a docker project.`); | ||
keyword = path.basename(info.cwd).replace(/[^0-9a-z]/gi, ''); | ||
cli.log(`Clean commands filtering for "${keyword}"`); | ||
} else { | ||
cli.log(`Current directory: ${info.cwd} is not a docker project.`); | ||
keyword = cli.prompt('Enter a filter for cleanup: (blank for full clean)'); | ||
if (info.context.dockerCompose) { | ||
cli.log(`Current directory: ${info.cwd} is a docker project.`); | ||
keyword = path.basename(info.cwd).replace(/[^0-9a-z]/gi, ''); | ||
cli.log(`Clean commands filtering for "${keyword}"`); | ||
} else { | ||
cli.log(`Current directory: ${info.cwd} is not a docker project.`); | ||
keyword = cli.prompt('Enter a filter for cleanup: (blank for full clean)'); | ||
if (keyword.trim() === '') { | ||
keyword = false; | ||
} | ||
if (keyword.trim() === '') { | ||
keyword = false; | ||
} | ||
} | ||
if (!cli.confirm(`Clean with filter: ${keyword ? keyword : '[NO FILTER]'}`)) { | ||
return reject('Aborted.'); | ||
} | ||
if (!cli.confirm(`Clean with filter: ${keyword ? keyword : '[NO FILTER]'}`)) { | ||
cli.error('Aborted.'); | ||
} | ||
/** | ||
* Stop running containers | ||
*/ | ||
cli.log('Cleaning: Running docker container(s):'); | ||
/** | ||
* Stop running containers | ||
*/ | ||
cli.log('Cleaning: Running docker container(s):'); | ||
if (keyword) { | ||
response = shell.exec(`docker ps | grep "${keyword}"`).stdout; | ||
} else { | ||
response = shell.exec('docker ps | grep -v "CONTAINER ID"').stdout; | ||
} | ||
if (response.trim() !== '' && cli.confirm('Stop running container(s)?')) { | ||
if (keyword) { | ||
response = shell.exec(`docker ps | grep "${keyword}"`).stdout; | ||
shell.exec(`docker stop $(docker ps | grep ${keyword} | awk '{ print $1 }')`); | ||
} else { | ||
response = shell.exec('docker ps | grep -v "CONTAINER ID"').stdout; | ||
shell.exec('docker stop $(docker ps -q)'); | ||
} | ||
} | ||
if (response.trim() !== '' && cli.confirm('Stop running container(s)?')) { | ||
if (keyword) { | ||
shell.exec(`docker stop $(docker ps | grep ${keyword} | awk '{ print $1 }')`); | ||
} else { | ||
shell.exec('docker stop $(docker ps -q)'); | ||
} | ||
} | ||
/** | ||
* Remove stopped containers | ||
*/ | ||
cli.log('Cleaning: Stopped docker container(s):'); | ||
/** | ||
* Remove stopped containers | ||
*/ | ||
cli.log('Cleaning: Stopped docker container(s):'); | ||
if (keyword) { | ||
response = shell.exec(`docker ps -a | grep "${keyword}"`).stdout; | ||
} else { | ||
response = shell.exec('docker ps -a | grep -v "CONTAINER ID"').stdout; | ||
} | ||
if (response.trim() !== '' && cli.confirm('Remove stopped container(s)?')) { | ||
if (keyword) { | ||
response = shell.exec(`docker ps -a | grep "${keyword}"`).stdout; | ||
shell.exec(`docker rm $(docker ps -a | grep ${keyword} | awk '{ print $1 }')`); | ||
} else { | ||
response = shell.exec('docker ps -a | grep -v "CONTAINER ID"').stdout; | ||
shell.exec('docker rm $(docker ps -aq)'); | ||
} | ||
} | ||
if (response.trim() !== '' && cli.confirm('Remove stopped container(s)?')) { | ||
if (keyword) { | ||
shell.exec(`docker rm $(docker ps -a | grep ${keyword} | awk '{ print $1 }')`); | ||
} else { | ||
shell.exec('docker rm $(docker ps -aq)'); | ||
} | ||
} | ||
/** | ||
* Remove images | ||
*/ | ||
cli.log('Cleaning: Docker image(s)'); | ||
/** | ||
* Remove images | ||
*/ | ||
cli.log('Cleaning: Docker image(s)'); | ||
if (keyword) { | ||
response = shell.exec(`docker images | grep "${keyword}"`).stdout; | ||
} else { | ||
response = shell.exec('docker images | grep -v "IMAGE ID"').stdout; | ||
} | ||
if (response.trim() !== '' && cli.confirm('Remove docker images(s)?')) { | ||
if (keyword) { | ||
response = shell.exec(`docker images | grep "${keyword}"`).stdout; | ||
shell.exec(`docker rmi -f $(docker images | grep ${keyword} | awk '{ print $3 }' | uniq)`); | ||
} else { | ||
response = shell.exec('docker images | grep -v "IMAGE ID"').stdout; | ||
shell.exec('docker rmi -f $(docker images -q)'); | ||
} | ||
} | ||
if (response.trim() !== '' && cli.confirm('Remove docker images(s)?')) { | ||
if (keyword) { | ||
shell.exec(`docker rmi -f $(docker images | grep ${keyword} | awk '{ print $3 }' | uniq)`); | ||
} else { | ||
shell.exec('docker rmi -f $(docker images -q)'); | ||
} | ||
} | ||
/** | ||
* Remove volumes | ||
*/ | ||
cli.log('Cleaning: Docker volume(s):'); | ||
/** | ||
* Remove volumes | ||
*/ | ||
cli.log('Cleaning: Docker volume(s):'); | ||
if (keyword) { | ||
response = shell.exec(`docker volume ls | grep "${keyword}"`).stdout; | ||
} else { | ||
response = shell.exec('docker volume ls').stdout; | ||
} | ||
if (response.trim() !== '' && cli.confirm('Remove docker volume(s)?')) { | ||
if (keyword) { | ||
response = shell.exec(`docker volume ls | grep "${keyword}"`).stdout; | ||
shell.exec(`docker volume rm $(docker volume ls | grep ${keyword} | awk '{ print $2 }')`); | ||
} else { | ||
response = shell.exec('docker volume ls').stdout; | ||
shell.exec('docker volume rm $(docker volume ls -q)'); | ||
} | ||
} | ||
if (response.trim() !== '' && cli.confirm('Remove docker volume(s)?')) { | ||
if (keyword) { | ||
shell.exec(`docker volume rm $(docker volume ls | grep ${keyword} | awk '{ print $2 }')`); | ||
} else { | ||
shell.exec('docker volume rm $(docker volume ls -q)'); | ||
} | ||
} | ||
/** | ||
* Remove untagged images | ||
*/ | ||
cli.log('Cleaning: Untagged image(s):'); | ||
response = shell.exec('docker images | grep "^<none>"').stdout; | ||
if (response.trim() !== '' && cli.confirm('Remove untagged image(s)?')) { | ||
shell.exec("docker rmi $(docker images | grep '^<none>' | awk '{print $3}')"); | ||
} | ||
/** | ||
* Remove untagged images | ||
*/ | ||
cli.log('Cleaning: Untagged image(s):'); | ||
response = shell.exec('docker images | grep "^<none>"').stdout; | ||
if (response.trim() !== '' && cli.confirm('Remove untagged image(s)?')) { | ||
shell.exec("docker rmi $(docker images | grep '^<none>' | awk '{print $3}')"); | ||
} | ||
/** | ||
* Remove dangling images | ||
*/ | ||
cli.log('Cleaning: Dangling image(s):'); | ||
response = shell.exec('docker images -f dangling=true | grep -v "IMAGE ID"').stdout; | ||
if (response.trim() !== '' && cli.confirm('Remove dangling image(s)?')) { | ||
shell.exec("docker rmi $(docker images -f dangling=true -q)"); | ||
} | ||
}); | ||
/** | ||
* Remove dangling images | ||
*/ | ||
cli.log('Cleaning: Dangling image(s):'); | ||
response = shell.exec('docker images -f dangling=true | grep -v "IMAGE ID"').stdout; | ||
if (response.trim() !== '' && cli.confirm('Remove dangling image(s)?')) { | ||
shell.exec("docker rmi $(docker images -f dangling=true -q)"); | ||
} | ||
}; |
@@ -1,12 +0,8 @@ | ||
module.exports = { | ||
clean: require('./clean'), | ||
build: require('./build'), | ||
migrate: require('./migrate'), | ||
rollback: require('./rollback'), | ||
reset: require('./reset'), | ||
// run: require('./run'), | ||
stop: require('./stop'), | ||
up: require('./up'), | ||
rebuild: require('./rebuild'), | ||
benchmark: require('./benchmark') | ||
}; | ||
const fs = require('fs'); | ||
const path = require('path') | ||
fs.readdirSync(__dirname).forEach(fileName => { | ||
if (fileName.substr(-3) === '.js' && fileName !== 'index.js') { | ||
module.exports[fileName.split('.')[0]] = require(path.join(__dirname, fileName)); | ||
} | ||
}); |
@@ -1,13 +0,7 @@ | ||
const shell = require('shelljs'); | ||
const bundleExec = require('./bundleExec') | ||
module.exports = ({ cli, info }) => { | ||
return new Promise((resolve, reject) => { | ||
if (!info.context.dockerCompose) { | ||
return reject(`Current directory: '${info.cwd}' has no 'docker-compose.yml' file`); | ||
} | ||
module.exports = (opts) => { | ||
opts.args.unshift('rake', 'db:migrate') | ||
shell.exec('docker-compose run app bundle exec rake db:migrate'); | ||
resolve(); | ||
}); | ||
bundleExec(opts) | ||
}; |
@@ -7,14 +7,10 @@ const shell = require('shelljs'); | ||
module.exports = ({ cli, info }) => { | ||
return new Promise((resolve, reject) => { | ||
if (!info.context.dockerCompose) { | ||
return reject(`Current directory: '${info.cwd}' has no 'docker-compose.yml' file`); | ||
} | ||
module.exports = ({ cli, info, args }) => { | ||
if (!info.context.dockerCompose) { | ||
cli.error(`Current directory: '${info.cwd}' has no 'docker-compose.yml' file`); | ||
} | ||
stop({ cli, info }) | ||
.then(() => build({ cli, info })) | ||
.then(() => reset({ cli, info })) | ||
.then(resolve) | ||
.catch(reject); | ||
}); | ||
stop({ cli, info, args }) | ||
build({ cli, info, args }) | ||
reset({ cli, info, args }) | ||
}; |
@@ -1,13 +0,10 @@ | ||
const shell = require('shelljs'); | ||
const bundleExec = require('./bundleExec') | ||
module.exports = ({ cli, info }) => { | ||
return new Promise((resolve, reject) => { | ||
if (!info.context.dockerCompose) { | ||
return reject(`Current directory: '${info.cwd}' has no 'docker-compose.yml' file`); | ||
} | ||
module.exports = (opts) => { | ||
opts.args.unshift('rake', 'db:reset') | ||
shell.exec('docker-compose run app bundle exec rake db:reset'); | ||
bundleExec(opts) | ||
resolve(); | ||
}); | ||
opts.args.shift() | ||
opts.args.shift() | ||
}; |
@@ -1,13 +0,7 @@ | ||
const shell = require('shelljs'); | ||
const bundleExec = require('./bundleExec') | ||
module.exports = ({ cli, info }) => { | ||
return new Promise((resolve, reject) => { | ||
if (!info.context.dockerCompose) { | ||
return reject(`Current directory: '${info.cwd}' has no 'docker-compose.yml' file`); | ||
} | ||
module.exports = (opts) => { | ||
opts.args.unshift('rake', 'db:rollback') | ||
shell.exec('docker-compose run app bundle exec rake db:rollback'); | ||
resolve(); | ||
}); | ||
bundleExec(opts) | ||
}; |
@@ -1,13 +0,7 @@ | ||
const shell = require('shelljs'); | ||
const dockerCompose = require('./dockerCompose') | ||
module.exports = ({ cli, info }) => { | ||
return new Promise((resolve, reject) => { | ||
if (!info.context.dockerCompose) { | ||
return reject(`Current directory: '${info.cwd}' has no 'docker-compose.yml' file`); | ||
} | ||
module.exports = (opts) => { | ||
opts.args.unshift('run') | ||
shell.exec('docker-compose run app bash'); | ||
resolve(); | ||
}); | ||
dockerCompose(opts) | ||
}; |
@@ -1,13 +0,9 @@ | ||
const shell = require('shelljs'); | ||
const dockerCompose = require('./dockerCompose') | ||
module.exports = ({ cli, info }) => { | ||
return new Promise((resolve, reject) => { | ||
if (!info.context.dockerCompose) { | ||
return reject(`Current directory: '${info.cwd}' has no 'docker-compose.yml' file`); | ||
} | ||
module.exports = (opts) => { | ||
opts.args.unshift('stop') | ||
shell.exec('docker-compose stop'); | ||
dockerCompose(opts) | ||
resolve(); | ||
}); | ||
opts.args.shift() | ||
}; |
@@ -1,13 +0,7 @@ | ||
const shell = require('shelljs'); | ||
const dockerCompose = require('./dockerCompose') | ||
module.exports = ({ cli, info }) => { | ||
return new Promise((resolve, reject) => { | ||
if (!info.context.dockerCompose) { | ||
return reject(`Current directory: '${info.cwd}' has no 'docker-compose.yml' file`); | ||
} | ||
module.exports = (opts) => { | ||
opts.args.unshift('up') | ||
shell.exec('docker-compose up'); | ||
resolve(); | ||
}); | ||
dockerCompose(opts) | ||
}; |
@@ -15,2 +15,10 @@ const Cmr1Cli = require('cmr1-cli'); | ||
typeLabel: Object.keys(actions).map(a => `[underline]{${a}}`).join('|') | ||
}, | ||
{ | ||
name: 'service', | ||
alias: 's', | ||
type: String, | ||
defaultValue: 'app', | ||
description: 'docker-compose service name', | ||
typeLabel: '[underline]{service} (default="app")' | ||
} | ||
@@ -26,5 +34,5 @@ ]; | ||
usage: [ | ||
'bt [underline]{action} [[underline]{action}] [[underline]{options}]', | ||
'bt -a [underline]{action} [[underline]{action}] [[underline]{options}]', | ||
'bt --action [underline]{action} [[underline]{action}] [[underline]{options}]', | ||
'bt [underline]{action} [[italic]{args}...] [[italic]{options}...]', | ||
'bt -a [underline]{action} [[italic]{args}...] [[italic]{options}...]', | ||
'bt --action [underline]{action} [[italic]{args}...] [[italic]{options}...]', | ||
], | ||
@@ -43,3 +51,5 @@ examples: [ | ||
const handleAction = (action) => { | ||
const handleAction = (args) => { | ||
const action = args.shift() | ||
cli.debug(`Finding action: ${action}`); | ||
@@ -57,9 +67,5 @@ cli.debug('Available actions:', JSON.stringify(Object.keys(actions), null, 2)); | ||
cli, | ||
info | ||
}).then(() => { | ||
cli.success(`Completed action: ${action}`) | ||
}).catch(e => { | ||
cli.warn(`Failed to complete action: ${action}`); | ||
cli.warn(e); | ||
}); | ||
info, | ||
args | ||
}) | ||
} else { | ||
@@ -76,5 +82,7 @@ cli.warn(`Action: '${action}' is invalid`); | ||
cli.debug(JSON.stringify(cli.options, null, 2)); | ||
cli.debug('System Information:') | ||
cli.debug(JSON.stringify(info, null, 2)) | ||
if (cli.options.action) { | ||
cli.options.action.forEach(handleAction); | ||
if (cli.options.action.length > 0) { | ||
handleAction(cli.options.action) | ||
} else { | ||
@@ -81,0 +89,0 @@ cli.warn('Missing action!'); |
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
13313
27
412
4
2