1 | 'use strict'
|
2 |
|
3 | const cli = require('heroku-cli-util')
|
4 | const co = require('co')
|
5 |
|
6 | let context
|
7 | let heroku
|
8 | let app
|
9 | let name
|
10 | let plan
|
11 | let addon
|
12 | let service
|
13 |
|
14 | function noPlanError () {
|
15 | throw new Error(`Error: No plan specified.
|
16 | You need to specify a plan to move ${cli.color.yellow(name)} to.
|
17 | For example: ${cli.color.blue('heroku addons:upgrade heroku-redis:premium-0')}
|
18 |
|
19 | ${cli.color.cyan('https://devcenter.heroku.com/articles/managing-add-ons')}`)
|
20 | }
|
21 |
|
22 | function handlePlanChangeAPIError (err) {
|
23 | const sortBy = require('lodash.sortby')
|
24 |
|
25 | if (err.statusCode === 422 && err.body.message && err.body.message.startsWith("Couldn't find either the add-on")) {
|
26 | return heroku.get(`/addon-services/${service}/plans`)
|
27 | .then((plans) => {
|
28 | plans = sortBy(plans, 'price.cents').map((plans) => plans.name)
|
29 | throw new Error(`${err.body.message}
|
30 |
|
31 | Here are the available plans for ${cli.color.yellow(service)}:
|
32 | ${plans.join('\n')}
|
33 |
|
34 | See more plan information with ${cli.color.blue('heroku addons:plans ' + service)}
|
35 |
|
36 | ${cli.color.cyan('https://devcenter.heroku.com/articles/managing-add-ons')}`)
|
37 | })
|
38 | }
|
39 | throw err
|
40 | }
|
41 |
|
42 | function handleAPIError (err) {
|
43 | if (err.statusCode === 422 && err.body.id === 'multiple_matches') {
|
44 | let example = err.body.message.split(', ')[2] || 'redis-triangular-1234'
|
45 | throw new Error(`${err.body.message}
|
46 |
|
47 | Multiple add-ons match ${cli.color.yellow(name)}${app ? ' on ' + app : ''}
|
48 | It is not clear which add-on's plan you are trying to change.
|
49 |
|
50 | Specify the add-on name instead of the name of the add-on service.
|
51 | For example, instead of: ${cli.color.blue('heroku addons:upgrade ' + context.args.addon + ' ' + (context.args.plan || ''))}
|
52 | Run this: ${cli.color.blue('heroku addons:upgrade ' + example + ' ' + name + ':' + plan)}
|
53 | ${!app ? 'Alternatively, specify an app to filter by with ' + cli.color.blue('--app') : ''}
|
54 | ${cli.color.cyan('https://devcenter.heroku.com/articles/managing-add-ons')}`)
|
55 | }
|
56 | throw err
|
57 | }
|
58 |
|
59 | function * run (c, h) {
|
60 | const resolver = require('../../lib/resolve')
|
61 | const util = require('../../lib/util')
|
62 |
|
63 | context = c
|
64 | heroku = h
|
65 | app = context.app
|
66 | name = context.args.addon
|
67 | plan = context.args.plan
|
68 |
|
69 |
|
70 | if (!plan && name.indexOf(':') !== -1) {
|
71 | let s = name.split(':')
|
72 | name = s[0]
|
73 | plan = s[1]
|
74 | }
|
75 |
|
76 | if (!plan) noPlanError()
|
77 |
|
78 | if (plan.indexOf(':') !== -1) plan = plan.split(':')[1]
|
79 |
|
80 |
|
81 | addon = yield resolver.addon(h, app, name).catch((e) => handleAPIError(e))
|
82 |
|
83 | service = addon.addon_service.name
|
84 | app = addon.app.name
|
85 | plan = `${service}:${plan}`
|
86 | yield cli.action(`Changing ${cli.color.magenta(addon.name)} on ${cli.color.cyan(app)} from ${cli.color.blue(addon.plan.name)} to ${cli.color.blue(plan)}`, {success: false}, co(function * () {
|
87 | addon = yield heroku.request({
|
88 | path: `/apps/${app}/addons/${addon.name}`,
|
89 | method: 'PATCH',
|
90 | body: {plan: {name: plan}},
|
91 | headers: {
|
92 | 'Accept-Expansion': 'plan',
|
93 | 'X-Heroku-Legacy-Provider-Messages': 'true'
|
94 | }
|
95 | }).catch((e) => handlePlanChangeAPIError(e))
|
96 | cli.action.done(`done, ${cli.color.green(util.formatPrice(addon.plan.price))}`)
|
97 | if (addon.provision_message) cli.log(addon.provision_message)
|
98 | }))
|
99 | }
|
100 |
|
101 | let cmd = {
|
102 | topic: 'addons',
|
103 | description: 'change add-on plan',
|
104 | help: `
|
105 | See available plans with \`heroku addons:plans SERVICE\`.
|
106 |
|
107 | Note that \`heroku addons:upgrade\` and \`heroku addons:downgrade\` are the same.
|
108 | Either one can be used to change an add-on plan up or down.
|
109 |
|
110 | https://devcenter.heroku.com/articles/managing-add-ons
|
111 |
|
112 | Examples:
|
113 |
|
114 | Upgrade an add-on by service name:
|
115 |
|
116 | $ heroku addons:upgrade heroku-redis:premium-2
|
117 |
|
118 | Upgrade a specific add-on:
|
119 |
|
120 | $ heroku addons:upgrade swimming-briskly-123 heroku-redis:premium-2
|
121 | `,
|
122 | needsAuth: true,
|
123 | wantsApp: true,
|
124 | args: [{name: 'addon'}, {name: 'plan', optional: true}],
|
125 | run: cli.command({preauth: true}, co.wrap(run))
|
126 | }
|
127 |
|
128 | module.exports = [
|
129 | Object.assign({command: 'upgrade'}, cmd),
|
130 | Object.assign({command: 'downgrade'}, cmd)
|
131 | ]
|