@heroku-cli/plugin-spaces
Version:
Heroku plugin to manage Heroku Private Spaces
91 lines (78 loc) • 2.98 kB
JavaScript
const cli = require('heroku-cli-util')
const strftime = require('strftime')
const _ = require('lodash')
const getProcessNum = s => Number.parseInt(s.split('.', 2)[1])
function timeAgo(since) {
let elapsed = Math.floor((Date.now() - since) / 1000)
let message = strftime('%Y/%m/%d %H:%M:%S %z', since)
if (elapsed < 60) return `${message} (~ ${Math.floor(elapsed)}s ago)`
if (elapsed < 60 * 60) return `${message} (~ ${Math.floor(elapsed / 60)}m ago)`
if (elapsed < 60 * 60 * 25) return `${message} (~ ${Math.floor(elapsed / 60 / 60)}h ago)`
return message
}
async function run(context, heroku) {
const spaceName = context.flags.space || context.args.space
if (!spaceName) throw new Error('Space name required.\nUSAGE: heroku spaces:ps my-space')
const [spaceDynos, space] = await Promise.all([
heroku.get(`/spaces/${spaceName}/dynos`),
heroku.get(`/spaces/${spaceName}`),
])
if (space.shield) {
spaceDynos.forEach(spaceDyno => {
spaceDyno.dynos.forEach(d => {
// eslint-disable-next-line unicorn/explicit-length-check
if (d.size) {
d.size = d.size.replace('Private-', 'Shield-')
}
})
})
}
if (context.flags.json) {
cli.styledJSON(spaceDynos)
} else {
render(spaceDynos)
}
}
function render(spaceDynos) {
_.forEach(spaceDynos, spaceDyno => {
printDynos(spaceDyno.app_name, spaceDyno.dynos)
})
}
function printDynos(appName, dynos) {
let dynosByCommand = _.reduce(dynos, function (dynosByCommand, dyno) {
let since = timeAgo(new Date(dyno.updated_at))
// eslint-disable-next-line unicorn/explicit-length-check
let size = dyno.size || '1X'
if (dyno.type === 'run') {
let key = 'run: one-off processes'
if (dynosByCommand[key] === undefined) dynosByCommand[key] = []
dynosByCommand[key].push(`${dyno.name} (${size}): ${dyno.state} ${since}: ${dyno.command}`)
} else {
let key = `${cli.color.green(dyno.type)} (${cli.color.cyan(size)}): ${dyno.command}`
if (dynosByCommand[key] === undefined) dynosByCommand[key] = []
let state = dyno.state === 'up' ? cli.color.green(dyno.state) : cli.color.yellow(dyno.state)
let item = `${dyno.name}: ${cli.color.green(state)} ${cli.color.dim(since)}`
dynosByCommand[key].push(item)
}
return dynosByCommand
}, {})
_.forEach(dynosByCommand, function (dynos, key) {
cli.styledHeader(`${appName} ${key} (${cli.color.yellow(dynos.length)})`)
dynos = dynos.sort((a, b) => getProcessNum(a) - getProcessNum(b))
for (let dyno of dynos) cli.log(dyno)
cli.log()
})
}
module.exports = {
topic: 'spaces',
command: 'ps',
description: 'list dynos for a space',
needsAuth: true,
args: [{name: 'space', optional: true, hidden: true}],
flags: [
{name: 'space', char: 's', hasValue: true, description: 'space to get dynos of'},
{name: 'json', description: 'output in json format'},
],
run: cli.command(run),
}