UNPKG

2.85 kBJavaScriptView Raw
1'use strict'
2
3const co = require('co')
4const cli = require('heroku-cli-util')
5
6function * run (context, heroku) {
7 const host = require('../../lib/host')
8 const fetcher = require('../../lib/fetcher')(heroku)
9 const util = require('../../lib/util')
10 const {app, args, flags} = context
11 let db = yield fetcher.addon(app, args.database)
12 let all = flags.all
13
14 if (all && 'name' in flags) {
15 cli.exit(1, 'cannot pass both --all and --name')
16 }
17 let cred = flags.name || 'default'
18 if (cred === 'default' && 'force' in flags && !all) {
19 cli.exit(1, 'Cannot force rotate the default credential.')
20 }
21 if (util.starterPlan(db) && cred !== 'default') {
22 throw new Error(`Only one default credential is supported for Hobby tier databases.`)
23 }
24 let attachments = yield heroku.get(`/addons/${db.name}/addon-attachments`)
25 if (flags.name) {
26 attachments = attachments.filter(a => a.namespace === `credential:${cred}`)
27 }
28
29 let warnings = []
30 if (!flags.all) {
31 warnings.push(`The password for the ${cred} credential will rotate.`)
32 }
33 if (flags.all || flags.force || cred === 'default') {
34 warnings.push(`Connections will be reset and applications will be restarted.`)
35 } else {
36 warnings.push(`Connections older than 30 minutes will be reset, and a temporary rotation username will be used during the process.`)
37 }
38 if (attachments.length > 0) {
39 warnings.push(`This command will affect the app${(attachments.length > 1) ? 's' : ''} ${[...new Set(attachments.map(c => cli.color.app(c.app.name)))].sort().join(', ')}.`)
40 }
41
42 yield cli.confirmApp(app, flags.confirm, `WARNING: Destructive Action
43${warnings.join('\n')}`)
44
45 let body = flags.force ? {host: host(db), force: true} : {host: host(db)}
46
47 if (all) {
48 yield cli.action(`Rotating all credentials on ${cli.color.addon(db.name)}`, co(function * () {
49 yield heroku.post(`/postgres/v0/databases/${db.name}/credentials_rotation`,
50 body)
51 }))
52 } else {
53 yield cli.action(`Rotating ${cred} on ${cli.color.addon(db.name)}`, co(function * () {
54 yield heroku.post(`/postgres/v0/databases/${db.name}/credentials/${encodeURIComponent(cred)}/credentials_rotation`,
55 body)
56 }))
57 }
58}
59
60module.exports = {
61 topic: 'pg',
62 command: 'credentials:rotate',
63 description: 'rotate the database credentials',
64 needsApp: true,
65 needsAuth: true,
66 flags: [
67 {name: 'name', char: 'n', description: 'which credentials to rotate (default credentials if not specified)', hasValue: true},
68 {name: 'all', description: 'rotate all credentials', hasValue: false},
69 {name: 'confirm', char: 'c', hasValue: true},
70 {name: 'force', description: 'forces rotating the targeted credentials', hasValue: false}
71 ],
72 args: [{name: 'database', optional: true}],
73 run: cli.command({preauth: true}, co.wrap(run))
74}