From 79b8eca64d505f94fc86601f1c76cd0643369922 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 8 Feb 2024 11:11:25 -0800 Subject: [PATCH] feat(pg): enable credentials url/rotation command for essential tier dbs (#2621) * Allow viewing creds for essential plans. * Update rotate command to remove essential plan blocking * Update error message for legacy essential tier --- packages/pg-v5/commands/credentials/rotate.js | 4 +- packages/pg-v5/commands/credentials/url.js | 4 +- .../commands/credentials/rotate.unit.test.js | 11 +++-- .../commands/credentials/url.unit.test.js | 45 ++++++++++++------- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/packages/pg-v5/commands/credentials/rotate.js b/packages/pg-v5/commands/credentials/rotate.js index d33f803e7c..c9ba8fd846 100644 --- a/packages/pg-v5/commands/credentials/rotate.js +++ b/packages/pg-v5/commands/credentials/rotate.js @@ -16,8 +16,8 @@ async function run(context, heroku) { throw new Error('cannot pass both --all and --name') } - if (util.essentialNumPlan(db) || (util.legacyEssentialPlan(db) && cred !== 'default')) { - throw new Error("You can't rotate credentials on Essential-tier databases.") + if (util.legacyEssentialPlan(db) && cred !== 'default') { + throw new Error('Legacy Essential-tier databases do not support named credentials.') } if (all && flags.force) { diff --git a/packages/pg-v5/commands/credentials/url.js b/packages/pg-v5/commands/credentials/url.js index 43c6c17ac5..61434429dc 100644 --- a/packages/pg-v5/commands/credentials/url.js +++ b/packages/pg-v5/commands/credentials/url.js @@ -12,8 +12,8 @@ async function run(context, heroku) { let db = await fetcher.addon(app, args.database) let cred = flags.name || 'default' - if (util.essentialNumPlan(db) || (util.legacyEssentialPlan(db) && cred !== 'default')) { - throw new Error("You can't view credentials on Essential-tier databases.") + if (util.legacyEssentialPlan(db) && cred !== 'default') { + throw new Error('Legacy Essential-tier databases do not support named credentials.') } let credInfo = await heroku.get(`/postgres/v0/databases/${db.name}/credentials/${encodeURIComponent(cred)}`, diff --git a/packages/pg-v5/test/unit/commands/credentials/rotate.unit.test.js b/packages/pg-v5/test/unit/commands/credentials/rotate.unit.test.js index 2a5e2f1eba..0efaa81f29 100644 --- a/packages/pg-v5/test/unit/commands/credentials/rotate.unit.test.js +++ b/packages/pg-v5/test/unit/commands/credentials/rotate.unit.test.js @@ -122,11 +122,11 @@ describe('pg:credentials:rotate', () => { '../../lib/fetcher': fetcher, }) - const err = "You can't rotate credentials on Essential-tier databases." + const err = 'Legacy Essential-tier databases do not support named credentials.' return expect(cmd.run({app: 'myapp', args: {}, flags: {name: 'jeff'}})).to.be.rejectedWith(Error, err) }) - it('throws an error when the db is numbered essential plan', () => { + it('rotates credentials when the db is numbered essential plan', () => { const essentialAddon = { name: 'postgres-1', plan: {name: 'heroku-postgresql:essential-0'}, @@ -143,8 +143,11 @@ describe('pg:credentials:rotate', () => { '../../lib/fetcher': fetcher, }) - const err = "You can't rotate credentials on Essential-tier databases." - return expect(cmd.run({app: 'myapp', args: {}, flags: {name: 'jeff'}})).to.be.rejectedWith(Error, err) + pg.post('/postgres/v0/databases/postgres-1/credentials/lucy/credentials_rotation').reply(200) + + return cmd.run({app: 'myapp', args: {}, flags: {name: 'lucy', confirm: 'myapp', force: true}}) + .then(() => expect(cli.stdout).to.equal('')) + .then(() => expect(cli.stderr).to.equal('Rotating lucy on postgres-1... done\n')) }) it('rotates credentials with no --name with starter plan', () => { diff --git a/packages/pg-v5/test/unit/commands/credentials/url.unit.test.js b/packages/pg-v5/test/unit/commands/credentials/url.unit.test.js index 7439555169..3a10ec981d 100644 --- a/packages/pg-v5/test/unit/commands/credentials/url.unit.test.js +++ b/packages/pg-v5/test/unit/commands/credentials/url.unit.test.js @@ -95,29 +95,40 @@ Connection URL: '../../lib/fetcher': fetcher, }) - const err = "You can't view credentials on Essential-tier databases." + const err = 'Legacy Essential-tier databases do not support named credentials.' return expect(cmd.run({app: 'myapp', args: {}, flags: {name: 'jeff'}})).to.be.rejectedWith(Error, err) }) - it('throws an error when the db is numbered essential plan', () => { - const essentialAddon = { - name: 'postgres-1', - plan: {name: 'heroku-postgresql:essential-0'}, - } - - const fetcher = () => { - return { - database: () => db, - addon: () => essentialAddon, - } + it('shows the credentials when the db is numbered essential plan', () => { + let roleInfo = { + uuid: 'bbbb', + name: 'lucy', + state: 'created', + database: 'd123', + host: 'localhost', + port: 5442, + credentials: [ + { + user: 'lucy-rotating', + password: 'passw0rd', + state: 'revoking', + }, + { + user: 'lucy', + password: 'hunter2', + state: 'active', + }, + ], } - const cmd = proxyquire('../../../../commands/credentials/url', { - '../../lib/fetcher': fetcher, - }) + pg.get('/postgres/v0/databases/postgres-1/credentials/lucy').reply(200, roleInfo) - const err = "You can't view credentials on Essential-tier databases." - return expect(cmd.run({app: 'myapp', args: {}, flags: {name: 'jeff'}})).to.be.rejectedWith(Error, err) + return cmd.run({app: 'myapp', args: {}, flags: {name: 'lucy'}}) + .then(() => expect(cli.stdout).to.equal(`Connection information for lucy credential.\nConnection info string: + "dbname=d123 host=localhost port=5442 user=lucy password=hunter2 sslmode=require" +Connection URL: + postgres://lucy:hunter2@localhost:5442/d123 +`)) }) it('shows the correct credentials with starter plan', () => {