1 | 'use strict'
|
2 |
|
3 | const cli = require('heroku-cli-util')
|
4 | const co = require('co')
|
5 |
|
6 | const getProcessType = (s) => s.split('-', 2)[0].split('.', 2)[0]
|
7 | const getProcessNum = (s) => parseInt(s.split('-', 2)[0].split('.', 2)[1])
|
8 |
|
9 | function * run (context, heroku) {
|
10 | let spaceName = context.flags.space || context.args.space
|
11 | if (!spaceName) throw new Error('Space name required.\nUSAGE: heroku spaces:topology my-space')
|
12 |
|
13 | let topology = yield heroku.get(`/spaces/${spaceName}/topology`)
|
14 | let appInfo = []
|
15 | if (topology.apps) {
|
16 | appInfo = yield topology.apps.map((app) => heroku.get(`/apps/${app.id}`))
|
17 | }
|
18 |
|
19 | render(spaceName, topology, appInfo, context.flags)
|
20 | }
|
21 |
|
22 | function render (spaceName, topology, appInfo, flags) {
|
23 | if (flags.json) {
|
24 | cli.styledJSON(topology)
|
25 | } else {
|
26 | if (topology.apps) {
|
27 | topology.apps.forEach((app) => {
|
28 | let formations = []
|
29 | let dynos = []
|
30 |
|
31 | if (app.formations) {
|
32 | app.formations.forEach((formation) => {
|
33 | formations.push(formation.process_type)
|
34 |
|
35 | if (formation.dynos) {
|
36 | formation.dynos.forEach((dyno) => {
|
37 | let dynoS = [`${formation.process_type}.${dyno.number}`, dyno.private_ip, dyno.hostname].filter(Boolean)
|
38 | dynos.push(dynoS.join(' - '))
|
39 | })
|
40 | }
|
41 | })
|
42 | }
|
43 |
|
44 | let domains = app.domains.sort()
|
45 | formations = formations.sort()
|
46 | dynos = dynos.sort((a, b) => {
|
47 | let apt = getProcessType(a)
|
48 | let bpt = getProcessType(b)
|
49 | if (apt > bpt) {
|
50 | return 1
|
51 | } else if (apt < bpt) {
|
52 | return -1
|
53 | }
|
54 |
|
55 | return getProcessNum(a) - getProcessNum(b)
|
56 | })
|
57 |
|
58 | let info = appInfo.find((info) => info.id === app.id)
|
59 | let header = info.name
|
60 | if (formations.length > 0) {
|
61 | header += ` (${cli.color.cyan(formations.join(', '))})`
|
62 | }
|
63 |
|
64 | cli.styledHeader(header)
|
65 | cli.styledObject({
|
66 | Domains: domains,
|
67 | Dynos: dynos
|
68 | }, ['Domains', 'Dynos'])
|
69 | cli.log()
|
70 | })
|
71 | }
|
72 | }
|
73 | }
|
74 |
|
75 | module.exports = {
|
76 | topic: 'spaces',
|
77 | command: 'topology',
|
78 | description: 'show space topology',
|
79 | needsAuth: true,
|
80 | args: [{ name: 'space', optional: true, hidden: true }],
|
81 | flags: [
|
82 | { name: 'space', char: 's', hasValue: true, description: 'space to get topology of' },
|
83 | { name: 'json', description: 'output in json format' }
|
84 | ],
|
85 | render: render,
|
86 | run: cli.command(co.wrap(run))
|
87 | }
|