Skip to content

Commit

Permalink
Merge pull request #103 from OldSneerJaw/run-config
Browse files Browse the repository at this point in the history
Update run command config
  • Loading branch information
OldSneerJaw authored Jan 23, 2023
2 parents c270d92 + e75f216 commit 919c3e5
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Change Log
This project adheres to [Semantic Versioning](http://semver.org/). All notable changes will be documented in this file.

## [Unreleased](https://github.com/OldSneerJaw/borealis-pg-cli/compare/v1.1.0...HEAD)
- Support the new secure tunnel connection info config var (`DATABASE_TUNNEL_BPG_CONN_INFO`)
- Require SSL/TLS for DB connections when using the `borealis-pg:run` command

## [1.1.0](https://github.com/OldSneerJaw/borealis-pg-cli/compare/v1.0.1...v1.1.0)
- Adds an add-on status field to the `borealis-pg:info` (alias: `borealis-pg`) command

Expand Down
59 changes: 53 additions & 6 deletions src/commands/borealis-pg/run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,13 @@ const expectedSshHostKey = 'AAAAC3NzaC1lZDI1NTE5AAAAIKkk9uh8+g/gKlLlbi4sVv4VJkia
const expectedSshHostKeyEntry = `${expectedSshHostKeyFormat} ${expectedSshHostKey}`

const fakeAppConfigVars: {[name: string]: string} = {FOO_BAR: 'baz'}

fakeAppConfigVars[`${fakeAttachmentName}_URL`] =
`postgres://${fakePgReadWriteAppUsername}:${fakePgReadWriteAppPassword}@` +
`${localPgHostname}:${customPgPort}/${fakePgDbName}`

fakeAppConfigVars[`${fakeAttachmentName}_READONLY_URL`] =
`postgres://${fakePgReadonlyAppUsername}:${fakePgReadonlyAppPassword}@` +
`${localPgHostname}:${customPgPort}/${fakePgDbName}`

fakeAppConfigVars[`${fakeAttachmentName}_SSH_TUNNEL_BPG_CONNECTION_INFO`] =
fakeAppConfigVars[`${fakeAttachmentName}_TUNNEL_BPG_CONN_INFO`] =
`POSTGRES_WRITER_HOST:=${fakePgWriterHost}|` +
`POSTGRES_READER_HOST:=${fakePgReaderHost}|` +
`POSTGRES_PORT:=${customPgPort}|` +
Expand All @@ -84,6 +81,14 @@ fakeAppConfigVars[`${fakeAttachmentName}_SSH_TUNNEL_BPG_CONNECTION_INFO`] =
'SSH_USERNAME:=this-ssh-username-should-be-ignored|' +
'SSH_USER_PRIVATE_KEY:=this-ssh-private-key-should-be-ignored'

const fakeObsoleteAppConfigVars: {[name: string]: string} = {}
fakeObsoleteAppConfigVars[`${fakeAttachmentName}_URL`] =
fakeAppConfigVars[`${fakeAttachmentName}_URL`]
fakeObsoleteAppConfigVars[`${fakeAttachmentName}_READONLY_URL`] =
fakeAppConfigVars[`${fakeAttachmentName}_READONLY_URL`]
fakeObsoleteAppConfigVars[`${fakeAttachmentName}_SSH_TUNNEL_BPG_CONNECTION_INFO`] =
fakeAppConfigVars[`${fakeAttachmentName}_TUNNEL_BPG_CONN_INFO`]

const fakeShellCommand = 'my-cool-shell-command'
const fakeDbCommand = 'my-cool-sql-command'

Expand Down Expand Up @@ -277,7 +282,7 @@ describe('noninteractive run command', () => {
})

defaultTestContext
.command(['borealis-pg:run', '-a', fakeHerokuAppName, '--shell-cmd', fakeShellCommand])
.command(['borealis-pg:run', '--app', fakeHerokuAppName, '--shell-cmd', fakeShellCommand])
.it('executes a shell command without a DB port option', ctx => {
executeSshClientListener()

Expand Down Expand Up @@ -325,7 +330,7 @@ describe('noninteractive run command', () => {

expect(ctx.stderr).to.endWith(`${fakeStderrMessage}\n`)

// Check what happens when the child process ends with an exit code
// Check what happens when the child process ends with a non-zero exit code
const fakeExitCode = 14

verify(mockChildProcessType.on(anyString(), anyFunction())).once()
Expand Down Expand Up @@ -408,6 +413,7 @@ describe('noninteractive run command', () => {
database: fakePgDbName,
user: fakePgReadonlyAppUsername,
password: fakePgReadonlyAppPassword,
ssl: {rejectUnauthorized: false},
}))).once()

// Check the PG client event listeners
Expand Down Expand Up @@ -609,6 +615,7 @@ describe('noninteractive run command', () => {
database: fakePgDbName,
user: fakePgReadonlyAppUsername,
password: fakePgReadonlyAppPassword,
ssl: {rejectUnauthorized: false},
}))).once()

verify(mockPgClientType.connect()).once()
Expand Down Expand Up @@ -849,6 +856,46 @@ describe('noninteractive run command', () => {
verify(mockTcpSocketType.on('error', anyFunction())).once()
})

baseTestContext
.nock(herokuApiBaseUrl, api => api.get(`/apps/${fakeHerokuAppName}/config-vars`)
.reply(200, fakeObsoleteAppConfigVars))
.nock(
borealisPgApiBaseUrl,
{reqheaders: {authorization: `Bearer ${fakeHerokuAuthToken}`}},
api => api.post(`/heroku/resources/${fakeAddonName}/personal-ssh-users`)
.reply(
200,
{
sshHost: fakeSshHost,
sshPort: customSshPort,
sshUsername: fakeSshUsername,
sshPrivateKey: fakeSshPrivateKey,
publicSshHostKey: expectedSshHostKeyEntry,
}))
.nock(herokuApiBaseUrl, api => mockAddonAttachmentRequests(api))
.command(['borealis-pg:run', '-a', fakeHerokuAppName, '-e', fakeShellCommand])
.it('executes a command with the obsolete tunnel connection info config var', () => {
executeSshClientListener()

verify(mockChildProcessFactoryType.spawn(
fakeShellCommand,
deepEqual({
env: {
...tunnelServices.nodeProcess.env,
PGHOST: localPgHostname,
PGPORT: defaultPgPort.toString(),
PGDATABASE: fakePgDbName,
PGUSER: fakePgReadonlyAppUsername,
PGPASSWORD: fakePgReadonlyAppPassword,
DATABASE_URL:
`postgres://${fakePgReadonlyAppUsername}:${fakePgReadonlyAppPassword}@` +
`${localPgHostname}:${defaultPgPort}/${fakePgDbName}`,
},
shell: true,
stdio: ['ignore', null, null],
}))).once()
})

test
.stdout()
.stderr()
Expand Down
9 changes: 8 additions & 1 deletion src/commands/borealis-pg/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,14 @@ like pgAdmin).`
appName: string,
attachmentName: string,
enableWriteAccess: boolean): Promise<DbConnectionInfo> {
const appConnInfoConfigVarName = `${attachmentName}_SSH_TUNNEL_BPG_CONNECTION_INFO`
const newConnInfoConfigVarName = `${attachmentName}_TUNNEL_BPG_CONN_INFO`
const obsoleteConnInfoConfigVarName = `${attachmentName}_SSH_TUNNEL_BPG_CONNECTION_INFO`

const configVarsInfo = await this.heroku.get<ConfigVars>(`/apps/${appName}/config-vars`)
const appConnInfoConfigVarName =
configVarsInfo.body[newConnInfoConfigVarName] ?
newConnInfoConfigVarName :
obsoleteConnInfoConfigVarName
const appConnInfo = configVarsInfo.body[appConnInfoConfigVarName]

const dbHostVar = enableWriteAccess ? 'POSTGRES_WRITER_HOST' : 'POSTGRES_READER_HOST'
Expand Down Expand Up @@ -267,6 +273,7 @@ like pgAdmin).`
database: connInfo.db.dbName,
user: connInfo.db.dbUsername,
password: connInfo.db.dbPassword,
ssl: {rejectUnauthorized: false},
}).on('end', () => {
sshClient.end()
tunnelServices.nodeProcess.exit()
Expand Down

0 comments on commit 919c3e5

Please sign in to comment.