Skip to content

Commit

Permalink
refactor(spaces): Move command spaces:peering:info to oclif (#2854)
Browse files Browse the repository at this point in the history
* Convert peering info to oclif

* Update example to reflect whitespace

* Rename to satisfy eslint

* Update packages/cli/src/lib/spaces/format.ts

Co-authored-by: Justin Wilaby <jwilaby@gmail.com>

* Fix linting for pg:info test

---------

Co-authored-by: Justin Wilaby <jwilaby@gmail.com>
  • Loading branch information
eablack and justinwilaby committed May 1, 2024
1 parent 90caefe commit aab717c
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 110 deletions.
62 changes: 62 additions & 0 deletions packages/cli/src/commands/spaces/peering/info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {Command, flags} from '@heroku-cli/command'
import {Args, ux} from '@oclif/core'
import * as Heroku from '@heroku-cli/schema'
import heredoc from 'tsheredoc'
import {displayPeeringInfo} from '../../../lib/spaces/peering'

export default class Info extends Command {
static topic = 'spaces'
static description = heredoc(`
display the information necessary to initiate a peering connection
You will use the information provided by this command to establish a peering connection request from your AWS VPC to your private space.
To start the peering process, go into your AWS console for the VPC you would like peered with your Private Space,
navigate to the VPC service, choose the "Peering Connections" option and click the "Create peering connection" button.
- The AWS Account ID and VPC ID are necessary for the AWS VPC Peering connection wizard.
- You will also need to configure your VPC route table to route the Dyno CIDRs through the peering connection.
Once you've established the peering connection request, you can use the spaces:peerings:accept command to accept and
configure the peering connection for the space.
`)

static flags = {
space: flags.string({char: 's', description: 'space to get peering info from'}),
json: flags.boolean({description: 'output in json format'}),
}

static examples = [heredoc(`
$ heroku spaces:peering:info example-space
=== example-space Peering Info
AWS Account ID: 012345678910
AWS Region: us-west-2
AWS VPC ID: vpc-baadf00d
AWS VPC CIDR: 10.0.0.0/16
Space CIDRs: 10.0.128.0/20, 10.0.144.0/20
Unavailable CIDRs: 10.1.0.0/16
`)]

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

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

const {body: pInfo} = await this.heroku.get<Heroku.PeeringInfo>(`/spaces/${spaceName}/peering-info`)
if (flags.json)
ux.log(JSON.stringify(pInfo, null, 2))
else
displayPeeringInfo(spaceName as string, pInfo)
}
}
3 changes: 3 additions & 0 deletions packages/cli/src/lib/spaces/format.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function displayCIDR(cidr: string[] | undefined) {
return cidr?.join(', ') ?? ''
}
15 changes: 15 additions & 0 deletions packages/cli/src/lib/spaces/peering.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {ux} from '@oclif/core'
import {displayCIDR} from './format'
import {PeeringInfo} from '@heroku-cli/schema'

export function displayPeeringInfo(space: string, info: PeeringInfo) {
ux.styledHeader(`${space} Peering Info`)
ux.styledObject({
'AWS Account ID': info.aws_account_id,
'AWS Region': info.aws_region,
'AWS VPC ID': info.vpc_id,
'AWS VPC CIDR': info.vpc_cidr,
'Space CIDRs': displayCIDR(info.space_cidr_blocks),
'Unavailable CIDRs': displayCIDR(info.unavailable_cidr_blocks),
}, ['AWS Account ID', 'AWS Region', 'AWS VPC ID', 'AWS VPC CIDR', 'Space CIDRs', 'Unavailable CIDRs'])
}
22 changes: 12 additions & 10 deletions packages/cli/test/unit/commands/pg/info.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,24 @@ const getCmd = (resultsObject: {allResult: any, addonResult: any}) => {
return Cmd
}

describe('pg', () => {
describe('pg', function () {
let api: nock.Scope
let pg: nock.Scope
beforeEach(() => {

beforeEach(function () {
api = nock('https://api.heroku.com:443')
pg = nock('https://api.data.heroku.com:443')
})
afterEach(() => {

afterEach(function () {
nock.cleanAll()
api.done()
pg.done()
allSinonStub.restore()
addonSinonStub.restore()
})
context('with 0 dbs', () => {
it('shows empty state', async () => {
context('with 0 dbs', function () {
it('shows empty state', async function () {
const Cmd = getCmd({allResult: [], addonResult: {}})
api.get('/apps/myapp/config-vars')
.reply(200, {})
Expand All @@ -51,7 +53,7 @@ describe('pg', () => {
expect(stderr.output).to.equal('')
})
})
context('with 2 dbs', () => {
context('with 2 dbs', function () {
const plan = {name: 'heroku-postgresql:hobby-dev'}
const config = {
DATABASE_URL: 'postgres://uxxxxxxxxx:pxxxxxxxx@ec2-54-111-111-1.compute-1.amazonaws.com:5452/dxxxxxxxxxxxx', HEROKU_POSTGRESQL_COBALT_URL: 'postgres://uxxxxxxxxx:pxxxxxxxx@ec2-54-111-111-1.compute-1.amazonaws.com:5452/dxxxxxxxxxxxx', HEROKU_POSTGRESQL_PURPLE_URL: 'postgres://uxxxxxxxxx:pxxxxxxxx@ec3-54-111-111-1.compute-1.amazonaws.com:5452/dxxxxxxxxxxxx',
Expand All @@ -65,7 +67,7 @@ describe('pg', () => {
const dbB = {info: [
{name: 'Plan', values: ['Hobby-dev']}, {name: 'Following', resolve_db_name: true, values: ['postgres://ec2-55-111-111-1.compute-1.amazonaws.com/dxxxxxxxxxxxx']},
], resource_url: config.HEROKU_POSTGRESQL_PURPLE_URL}
it('shows postgres info', async () => {
it('shows postgres info', async function () {
const Cmd = getCmd({allResult: addons, addonResult: {}})
api.get('/apps/myapp/config-vars')
.reply(200, config)
Expand All @@ -80,7 +82,7 @@ describe('pg', () => {
expect(stdout.output).to.equal('=== HEROKU_POSTGRESQL_COBALT_URL, DATABASE_URL\n\nPlan: Hobby-dev\nFollowing: HEROKU_POSTGRESQL_COBALT\nBilling App: myapp2\nAdd-on: postgres-1\n\n=== HEROKU_POSTGRESQL_PURPLE_URL\n\nPlan: Hobby-dev\nFollowing: ec2-55-111-111-1.compute-1.amazonaws.com:5432/dxxxxxxxxxxxx\nAdd-on: postgres-2\n\n')
expect(stderr.output).to.equal('')
})
it('shows postgres info using attachment names', async () => {
it('shows postgres info using attachment names', async function () {
all = [
{
id: 1,
Expand All @@ -104,7 +106,7 @@ describe('pg', () => {
])
expect(stdout.output).to.equal('=== DATABASE_URL, ATTACHMENT_NAME_URL\n\nPlan: Hobby-dev\nFollowing: HEROKU_POSTGRESQL_COBALT\nBilling App: myapp2\nAdd-on: postgres-1\n\n=== HEROKU_POSTGRESQL_PURPLE_URL\n\nPlan: Hobby-dev\nFollowing: ec2-55-111-111-1.compute-1.amazonaws.com:5432/dxxxxxxxxxxxx\nAdd-on: postgres-2\n\n')
})
it('shows postgres info for single database when arg sent in', async () => {
it('shows postgres info for single database when arg sent in', async function () {
addon = addons[1]
api.get('/apps/myapp/config-vars')
.reply(200, config)
Expand All @@ -120,7 +122,7 @@ describe('pg', () => {
expect(stdout.output).to.equal('=== HEROKU_POSTGRESQL_PURPLE_URL\n\nPlan: Hobby-dev\nFollowing: ec2-55-111-111-1.compute-1.amazonaws.com:5432/dxxxxxxxxxxxx\nAdd-on: postgres-2\n\n')
expect(stderr.output).to.equal('')
})
it('shows warning for 404', async () => {
it('shows warning for 404', async function () {
all = addons
api.get('/apps/myapp/config-vars')
.reply(200, config)
Expand Down
55 changes: 55 additions & 0 deletions packages/cli/test/unit/commands/spaces/peering/info.unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {stdout} from 'stdout-stderr'
import Cmd from '../../../../../src/commands/spaces/peering/info'
import runCommand from '../../../../helpers/runCommand'
import * as nock from 'nock'
import heredoc from 'tsheredoc'
import expectOutput from '../../../../helpers/utils/expectOutput'
import {expect} from 'chai'
import * as Heroku from '@heroku-cli/schema'

describe('spaces:peering:info', function () {
let peeringInfo: Heroku.PeeringInfo

beforeEach(function () {
peeringInfo = {
aws_account_id: '012345678900',
aws_region: 'us-west-2',
vpc_id: 'vpc-1234568a',
vpc_cidr: '10.0.0.0/16',
space_cidr_blocks: ['10.0.128.0/20', '10.0.144.0/20'],
unavailable_cidr_blocks: ['192.168.2.0/30']}
})

it('shows space peering info', async function () {
nock('https://api.heroku.com')
.get('/spaces/my-space/peering-info')
.reply(200, peeringInfo)

await runCommand(Cmd, [
'--space',
'my-space',
])
expectOutput(stdout.output, heredoc(`
=== my-space Peering Info
AWS Account ID: ${peeringInfo.aws_account_id}
AWS Region: ${peeringInfo.aws_region}
AWS VPC ID: ${peeringInfo.vpc_id}
AWS VPC CIDR: ${peeringInfo.vpc_cidr}
Space CIDRs: 10.0.128.0/20, 10.0.144.0/20
Unavailable CIDRs: 192.168.2.0/30
`))
})

it('shows peering:info --json', async function () {
nock('https://api.heroku.com')
.get('/spaces/my-space/peering-info')
.reply(200, peeringInfo)

await runCommand(Cmd, [
'--space',
'my-space',
'--json',
])
expect(JSON.parse(stdout.output)).to.eql(peeringInfo)
})
})
52 changes: 0 additions & 52 deletions packages/spaces/commands/peering/info.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 @@ -6,7 +6,6 @@ exports.topics = [
]

exports.commands = [
require('./commands/peering/info'),
require('./commands/peering/index'),
require('./commands/peering/accept'),
require('./commands/peering/destroy'),
Expand Down
47 changes: 0 additions & 47 deletions packages/spaces/test/unit/commands/peering/info.unit.test.js

This file was deleted.

0 comments on commit aab717c

Please sign in to comment.