Skip to content

Commit

Permalink
Revert "feat(domains): add multiple SNI endpoint support to `domains:…
Browse files Browse the repository at this point in the history
…add` (#1412)"

This reverts commit 5d87d99.
  • Loading branch information
Chase McCarthy committed Jan 21, 2020
1 parent 9f30e7a commit d095a5d
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 219 deletions.
1 change: 0 additions & 1 deletion packages/apps/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"@oclif/command": "^1",
"@oclif/config": "^1",
"cli-ux": "^5.3.2",
"inquirer": "^7.0.1",
"shell-escape": "^0.2.0",
"tslib": "^1",
"urijs": "^1.19.1"
Expand Down
123 changes: 18 additions & 105 deletions packages/apps/src/commands/domains/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,10 @@ import {color} from '@heroku-cli/color'
import {Command, flags} from '@heroku-cli/command'
import * as Heroku from '@heroku-cli/schema'
import cli from 'cli-ux'
import {prompt} from 'inquirer'
import * as shellescape from 'shell-escape'

import waitForDomain from '../../lib/wait-for-domain'

interface DomainCreatePayload {
hostname: string
sni_endpoint?: string
}

const MULTIPLE_SNI_ENDPOINT_FLAG = 'allow-multiple-sni-endpoints'

export default class DomainsAdd extends Command {
static description = 'add a domain to an app'

Expand All @@ -22,114 +14,35 @@ export default class DomainsAdd extends Command {
static flags = {
help: flags.help({char: 'h'}),
app: flags.app({required: true}),
cert: flags.string({description: 'the name of the SSL cert you want to use for this domain', char: 'c'}),
json: flags.boolean({description: 'output in json format', char: 'j'}),
wait: flags.boolean()
}

static args = [{name: 'hostname'}]

createDomain = async (appName: string, payload: DomainCreatePayload): Promise<Heroku.Domain> => {
cli.action.start(`Adding ${color.green(payload.hostname)} to ${color.app(appName)}`)
try {
const response = await this.heroku.post<Heroku.Domain>(`/apps/${appName}/domains`, {
headers: {Accept: 'application/vnd.heroku+json; version=3.allow_multiple_sni_endpoints'},
body: payload
})
return response.body
} catch (err) {
// If the error indicates that the app has multiple certs needs the user to specify which one
// to use, we ask them which cert to use, otherwise we rethrow the error and handle it like usual
if (err.body.id === 'invalid_params' && err.body.message.includes('sni_endpoint')) {
cli.action.stop('resolving SNI endpoint')
const {body: certs} = await this.heroku.get<Heroku.SniEndpoint>(`/apps/${appName}/sni-endpoints`, {
headers: {Accept: 'application/vnd.heroku+json; version=3.allow_multiple_sni_endpoints'}
})

const certChoices = certs.map((cert: Heroku.SniEndpoint) => {
const certName = cert.displayName || cert.name
const domainsLength = cert.ssl_cert.cert_domains.length

if (domainsLength) {
let domainsList = cert.ssl_cert.cert_domains.slice(0, 4).join(', ')

if (domainsLength > 5) {
domainsList = `${domainsList} (...and ${domainsLength - 4} more)`
}

domainsList = `${certName} -> ${domainsList}`

return {
name: domainsList,
value: cert.name
}
}

return {
name: certName,
value: cert.name
}
})

const selection = await prompt<{cert: string}>([
{
type: 'list',
name: 'cert',
message: 'Choose an SNI endpoint to associate with this domain',
choices: certChoices
}
])

payload.sni_endpoint = selection.cert

return this.createDomain(appName, payload)
} else {
throw err
}
}
}

async run() {
const {args, flags} = this.parse(DomainsAdd)
const {hostname} = args

const {body: featureFlag} = await this.heroku.get<Heroku.AppFeature>(
`/apps/${flags.app}/features/${MULTIPLE_SNI_ENDPOINT_FLAG}`
)

const domainCreatePayload: DomainCreatePayload = {
hostname
}

if (featureFlag.enabled) {
// multiple SNI endpoints is enabled
if (flags.cert) {
domainCreatePayload.sni_endpoint = flags.cert
}
}

try {
const domain = await this.createDomain(flags.app, domainCreatePayload)
if (flags.json) {
cli.styledJSON(domain)
} else {
cli.log(`Configure your app's DNS provider to point to the DNS Target ${color.green(domain.cname || '')}.
For help, see https://devcenter.heroku.com/articles/custom-domains`)
if (domain.status !== 'none') {
if (flags.wait) {
await waitForDomain(flags.app, this.heroku, domain)
} else {
cli.log('')
cli.log(`The domain ${color.green(hostname)} has been enqueued for addition`)
let command = `heroku domains:wait ${shellescape([hostname])}`
cli.log(`Run ${color.cmd(command)} to wait for completion`)
}
cli.action.start(`Adding ${color.green(args.hostname)} to ${color.app(flags.app)}`)
const {body: domain} = await this.heroku.post<Heroku.Domain>(`/apps/${flags.app}/domains`, {
body: {hostname}
})
cli.action.stop()
if (flags.json) {
cli.styledJSON(domain)
} else {
cli.log(`Configure your app's DNS provider to point to the DNS Target ${color.green(domain.cname || '')}.
For help, see https://devcenter.heroku.com/articles/custom-domains`)
if (domain.status !== 'none') {
if (flags.wait) {
await waitForDomain(flags.app, this.heroku, domain)
} else {
cli.log('')
cli.log(`The domain ${color.green(hostname)} has been enqueued for addition`)
let command = `heroku domains:wait ${shellescape([hostname])}`
cli.log(`Run ${color.cmd(command)} to wait for completion`)
}
}
} catch (err) {
cli.error(err)
} finally {
cli.action.stop()
}
}
}
102 changes: 9 additions & 93 deletions packages/apps/test/commands/domains/add.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import * as inquirer from 'inquirer'

import {expect, test} from '../../test'

describe('domains:add', () => {
Expand All @@ -19,96 +17,14 @@ describe('domains:add', () => {
status: 'pending'
}

describe('adding a domain without the feature flag on (the old way)', () => {
test
.stderr()
.nock('https://api.heroku.com', (api: any) => api
.get('/apps/myapp/features/allow-multiple-sni-endpoints')
.reply(200, {
enabled: false
})
.post('/apps/myapp/domains', {hostname: 'example.com'})
.reply(200, domainsResponse)
)
.command(['domains:add', 'example.com', '--app', 'myapp'])
.it('adds the domain to the app', ctx => {
expect(ctx.stderr).to.contain('Adding example.com to myapp... done')
})
})

describe('adding a domain to an app with multiple certs', () => {
describe('using the --cert flag', () => {
test
.stderr()
.nock('https://api.heroku.com', (api: any) => api
.get('/apps/myapp/features/allow-multiple-sni-endpoints')
.reply(200, {
enabled: true
})
.post('/apps/myapp/domains', {
hostname: 'example.com',
sni_endpoint: 'my-cert'
})
.reply(200, domainsResponse)
)
.command(['domains:add', 'example.com', '--app', 'myapp', '--cert', 'my-cert'])
.it('adds the domain to the app', ctx => {
expect(ctx.stderr).to.contain('Adding example.com to myapp... done')
})
})

describe('without passing a cert', () => {
const certsResponse = [
{
app: {
name: 'myapp',
},
name: 'cert1',
displayName: 'Best Cert Ever',
ssl_cert: {
cert_domains: ['foo.com', 'bar.com', 'baz.com', 'baq.com', 'blah.com', 'rejairieja.com'],
},
},
{
app: {
name: 'myapp',
},
name: 'cert2',
ssl_cert: {
cert_domains: ['foo.com', 'bar.com', 'baz.com', 'baq.com', 'blah.com', 'rejairieja.com'],
},
},
]

test
.stderr()
.stub(inquirer, 'prompt', () => {
return Promise.resolve({cert: 'my-cert'})
})
.nock('https://api.heroku.com', (api: any) => api
.get('/apps/myapp/features/allow-multiple-sni-endpoints')
.reply(200, {
enabled: true
})
.post('/apps/myapp/domains', {
hostname: 'example.com',
})
.reply(422, {
id: 'invalid_params',
message: '\'sni_endpoint\' param is required when adding a domain to an app with multiple SSL certs.'
})
.post('/apps/myapp/domains', {
hostname: 'example.com',
sni_endpoint: 'my-cert'
})
.reply(200, domainsResponse)
.get('/apps/myapp/sni-endpoints')
.reply(200, certsResponse)
)
.command(['domains:add', 'example.com', '--app', 'myapp'])
.it('adds the domain to the app', ctx => {
expect(ctx.stderr).to.contain('Adding example.com to myapp... done')
})
test
.stderr()
.nock('https://api.heroku.com', (api: any) => api
.post('/apps/myapp/domains', {hostname: 'example.com'})
.reply(200, domainsResponse)
)
.command(['domains:add', 'example.com', '--app', 'myapp'])
.it('adds the domain to the app', ctx => {
expect(ctx.stderr).to.contain('Adding example.com to myapp... done')
})
})
})
21 changes: 1 addition & 20 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5258,25 +5258,6 @@ inquirer@^7.0.0:
strip-ansi "^5.1.0"
through "^2.3.6"

inquirer@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.1.tgz#13f7980eedc73c689feff3994b109c4e799c6ebb"
integrity sha512-V1FFQ3TIO15det8PijPLFR9M9baSlnRs9nL7zWu1MNVA2T9YVl9ZbrHJhYs7e9X8jeMZ3lr2JH/rdHFgNCBdYw==
dependencies:
ansi-escapes "^4.2.1"
chalk "^2.4.2"
cli-cursor "^3.1.0"
cli-width "^2.0.0"
external-editor "^3.0.3"
figures "^3.0.0"
lodash "^4.17.15"
mute-stream "0.0.8"
run-async "^2.2.0"
rxjs "^6.5.3"
string-width "^4.1.0"
strip-ansi "^5.1.0"
through "^2.3.6"

into-stream@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6"
Expand Down Expand Up @@ -8198,7 +8179,7 @@ rxjs@^5.5.2:
dependencies:
symbol-observable "1.0.1"

rxjs@^6.1.0, rxjs@^6.5.3:
rxjs@^6.1.0:
version "6.5.3"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a"
integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==
Expand Down

0 comments on commit d095a5d

Please sign in to comment.