Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(spaces): Move command spaces:hosts to oclif #2845

Merged
merged 5 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions packages/cli/src/commands/spaces/hosts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {Command, flags} from '@heroku-cli/command'
import {Args, ux} from '@oclif/core'
import heredoc from 'tsheredoc'
import {displayHostsAsJSON, displayHosts, type Host} from '../../lib/spaces/hosts'

export default class Hosts extends Command {
static topic = 'spaces'
static hidden = true
static description = 'list dedicated hosts for a space'
static flags = {
space: flags.string({char: 's', description: 'space to get host list from'}),
json: flags.boolean({description: 'output in json format'}),
}

static args = {
space: Args.string({hidden: true}),
}

public async run(): Promise<void> {
const {flags, args} = await this.parse(Hosts)
const spaceName = flags.space || args.space
if (!spaceName) {
ux.error(heredoc(`
Error: Missing 1 required arg:
space
See more help with --help
`))
}

const {body: hosts} = await this.heroku.get<Host[]>(
`/spaces/${spaceName}/hosts`, {
headers: {Accept: 'application/vnd.heroku+json; version=3.dogwood'},
})
if (flags.json)
displayHostsAsJSON(hosts)
else
displayHosts(spaceName as string, hosts)
}
}
18 changes: 18 additions & 0 deletions packages/cli/src/lib/spaces/format.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
import color from '@heroku-cli/color'

export function displayCIDR(cidr: string[] | undefined) {
return cidr?.join(', ') ?? ''
}

export function hostStatus(s: string) {
switch (s) {
case 'available':
return `${color.green(s)}`
case 'under-assessment':
return `${color.yellow(s)}`
case 'permanent-failure':
case 'released-permanent-failure':
return `${color.red(s)}`
case 'released':
return `${color.gray(s)}`
default:
return s
}
}
39 changes: 39 additions & 0 deletions packages/cli/src/lib/spaces/hosts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {ux} from '@oclif/core'
import {hostStatus} from './format'

export type Host = {
host_id: string,
state: string,
available_capacity_percentage: number,
allocated_at: string,
released_at: string,
}

export function displayHosts(space: string, hosts: Host[]) {
ux.styledHeader(`${space} Hosts`)
ux.table(hosts, {
host_id: {
header: 'Host ID',
},
state: {
header: 'State',
get: host => hostStatus(host.state),
},
available_capacity_percentage: {
header: 'Available Capacity',
get: host => `${host.available_capacity_percentage}%`,
},
allocated_at: {
header: 'Allocated At',
get: host => host.allocated_at || '',
},
released_at: {
header: 'Released At',
get: host => host.released_at || '',
},
})
}

export function displayHostsAsJSON(hosts: Host[]) {
ux.log(JSON.stringify(hosts, null, 2))
}
64 changes: 64 additions & 0 deletions packages/cli/test/unit/commands/spaces/hosts.unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {stdout} from 'stdout-stderr'
import Cmd from '../../../../src/commands/spaces/hosts'
import runCommand from '../../../helpers/runCommand'
import * as nock from 'nock'
import heredoc from 'tsheredoc'
import expectOutput from '../../../helpers/utils/expectOutput'
import {expect} from 'chai'

describe('spaces:hosts', function () {
const hosts = [
{
host_id: 'h-0f927460a59aac18e',
state: 'available',
available_capacity_percentage: 72,
allocated_at: '2020-05-28T04:15:59Z',
released_at: null,
}, {
host_id: 'h-0e927460a59aac18f',
state: 'released',
available_capacity_percentage: 0,
allocated_at: '2020-03-28T04:15:59Z',
released_at: '2020-04-28T04:15:59Z',
},
]

it('lists space hosts', async function () {
nock('https://api.heroku.com', {
reqheaders: {
Accept: 'application/vnd.heroku+json; version=3.dogwood',
},
})
.get('/spaces/my-space/hosts')
.reply(200, hosts)
await runCommand(Cmd, [
'--space',
'my-space',
])

expectOutput(stdout.output, heredoc(`
=== my-space Hosts
Host ID State Available Capacity Allocated At Released At
─────────────────── ───────── ────────────────── ──────────────────── ────────────────────
h-0f927460a59aac18e available 72% 2020-05-28T04:15:59Z
h-0e927460a59aac18f released 0% 2020-03-28T04:15:59Z 2020-04-28T04:15:59Z
`))
})

it('shows hosts:info --json', async function () {
nock('https://api.heroku.com', {
reqheaders: {
Accept: 'application/vnd.heroku+json; version=3.dogwood',
},
})
.get('/spaces/my-space/hosts')
.reply(200, hosts)

await runCommand(Cmd, [
'--space',
'my-space',
'--json',
])
expect(JSON.parse(stdout.output)).to.eql(hosts)
})
})
17 changes: 13 additions & 4 deletions packages/cli/test/unit/commands/spaces/topology.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,21 @@ import heredoc from 'tsheredoc'
import expectOutput from '../../../helpers/utils/expectOutput'
import * as fixtures from '../../../fixtures/spaces/fixtures'
import {expect} from 'chai'
import type {SpaceTopology} from '../../../../src/commands/spaces/topology'
import {App} from '@heroku-cli/schema'

describe('spaces:topology', function () {
const topo1 = fixtures.topologies['topology-one']
const topo2 = fixtures.topologies['topology-two']
const topo3 = fixtures.topologies['topology-three']
const app = fixtures.apps.www
let topo1: SpaceTopology
let topo2: SpaceTopology
let topo3: SpaceTopology
let app: App

beforeEach(function () {
topo1 = fixtures.topologies['topology-one']
topo2 = fixtures.topologies['topology-two']
topo3 = fixtures.topologies['topology-three']
app = fixtures.apps.www
})

it('shows space topology', async function () {
nock('https://api.heroku.com')
Expand Down
11 changes: 7 additions & 4 deletions packages/cli/test/unit/commands/spaces/wait.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,22 @@ import {expect} from 'chai'
import expectOutput from '../../../helpers/utils/expectOutput'
import * as fixtures from '../../../fixtures/spaces/fixtures'
import * as sinon from 'sinon'
import {Space} from '@heroku-cli/schema'

describe('spaces:wait', function () {
const allocatingSpace = fixtures.spaces['allocating-space']
const allocatedSpace = fixtures.spaces['non-shield-space']
let allocatingSpace: Required<Space>
let allocatedSpace: Required<Space>
let sandbox: sinon.SinonSandbox
let notifySpy: sinon.SinonSpy

beforeEach(() => {
beforeEach(function () {
sandbox = sinon.createSandbox()
notifySpy = sandbox.spy(require('@heroku-cli/notifications'), 'notify')
allocatingSpace = fixtures.spaces['allocating-space']
allocatedSpace = fixtures.spaces['non-shield-space']
})

afterEach(() => {
afterEach(function () {
sandbox.restore()
})

Expand Down
31 changes: 0 additions & 31 deletions packages/spaces/commands/hosts/index.js

This file was deleted.

1 change: 0 additions & 1 deletion packages/spaces/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,4 @@ exports.commands = [
require('./commands/drains/get'),
require('./commands/trusted-ips'),
require('./commands/trusted-ips/remove'),
require('./commands/hosts'),
]
54 changes: 0 additions & 54 deletions packages/spaces/test/unit/commands/hosts/index.unit.test.js

This file was deleted.

Loading