UNPKG

2.94 kBJavaScriptView Raw
1'use strict'
2
3const co = require('co')
4const cli = require('heroku-cli-util')
5
6function * run (context, heroku) {
7 const url = require('url')
8 const util = require('../lib/util')
9 const host = require('../lib/host')
10 const pgbackups = require('../lib/pgbackups')(context, heroku)
11 const fetcher = require('../lib/fetcher')(heroku)
12 const {app, args, flags} = context
13 const interval = Math.max(3, parseInt(flags['wait-interval'])) || 3
14
15 let resolve = co.wrap(function * (db) {
16 if (db.match(/^postgres:\/\//)) {
17 let uri = url.parse(db)
18 let name = uri.path ? uri.path.slice(1) : ''
19 let hostname = `${uri.host}:${uri.port || 5432}`
20 return {
21 name: name ? `database ${name} on ${hostname}` : `database on ${hostname}`,
22 url: db,
23 confirm: name || uri.host
24 }
25 } else {
26 let attachment = yield fetcher.attachment(app, db)
27 if (!attachment) throw new Error(`${db} not found on ${cli.color.app(app)}`)
28 let [addon, config] = yield [
29 heroku.get(`/addons/${attachment.addon.name}`),
30 heroku.get(`/apps/${attachment.addon.app.name}/config-vars`)
31 ]
32 attachment.addon = addon
33 return {
34 name: attachment.name.replace(/^HEROKU_POSTGRESQL_/, '').replace(/_URL$/, ''),
35 url: config[util.getUrl(addon.config_vars)],
36 attachment,
37 confirm: app
38 }
39 }
40 })
41
42 let [source, target] = yield [resolve(args.source), resolve(args.target)]
43 if (source.url === target.url) throw new Error('Cannot copy database onto itself')
44
45 yield cli.confirmApp(target.confirm, flags.confirm, `WARNING: Destructive action
46This command will remove all data from ${cli.color.yellow(target.name)}
47Data from ${cli.color.yellow(source.name)} will then be transferred to ${cli.color.yellow(target.name)}`)
48
49 let copy
50 let attachment
51 yield cli.action(`Starting copy of ${cli.color.yellow(source.name)} to ${cli.color.yellow(target.name)}`, co(function * () {
52 attachment = target.attachment || source.attachment
53 if (!attachment) throw new Error('Heroku PostgreSQL database must be source or target')
54 copy = yield heroku.post(`/client/v11/databases/${attachment.addon.id}/transfers`, {
55 body: {
56 from_name: source.name,
57 from_url: source.url,
58 to_name: target.name,
59 to_url: target.url
60 },
61 host: host(attachment.addon)
62 })
63 }))
64 yield pgbackups.wait('Copying', copy.uuid, interval, flags.verbose, attachment.addon.app.name)
65}
66
67module.exports = {
68 topic: 'pg',
69 command: 'copy',
70 needsApp: true,
71 needsAuth: true,
72 description: 'copy all data from source db to target',
73 help: 'at least one of the databases must be a Heroku PostgreSQL DB',
74 args: [
75 {name: 'source'},
76 {name: 'target'}
77 ],
78 flags: [
79 {name: 'wait-interval', hasValue: true},
80 {name: 'verbose'},
81 {name: 'confirm', hasValue: true}
82 ],
83 run: cli.command({preauth: true}, co.wrap(run))
84}