clever-tools 3.6.1 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +1 -7
  2. package/bin/clever.js +99 -47
  3. package/package.json +48 -50
  4. package/src/command-options.js +22 -3
  5. package/src/commands/accesslogs.js +114 -34
  6. package/src/commands/activity.js +70 -16
  7. package/src/commands/addon.js +153 -75
  8. package/src/commands/applications.js +83 -1
  9. package/src/commands/cancel-deploy.js +3 -3
  10. package/src/commands/config.js +6 -7
  11. package/src/commands/console.js +16 -4
  12. package/src/commands/curl.js +13 -16
  13. package/src/commands/delete.js +16 -6
  14. package/src/commands/deploy.js +9 -6
  15. package/src/commands/diag.js +68 -28
  16. package/src/commands/domain.js +13 -13
  17. package/src/commands/drain.js +42 -27
  18. package/src/commands/env.js +53 -24
  19. package/src/commands/logs.js +3 -3
  20. package/src/commands/notify-email.js +33 -18
  21. package/src/commands/open.js +3 -3
  22. package/src/commands/profile.js +29 -9
  23. package/src/commands/published-config.js +26 -15
  24. package/src/commands/restart.js +12 -5
  25. package/src/commands/scale.js +2 -3
  26. package/src/commands/service.js +42 -15
  27. package/src/commands/ssh.js +3 -3
  28. package/src/commands/status.js +72 -46
  29. package/src/commands/stop.js +3 -3
  30. package/src/commands/tcp-redirs.js +54 -18
  31. package/src/commands/webhooks.js +28 -13
  32. package/src/logger.js +9 -6
  33. package/src/models/addon.js +21 -12
  34. package/src/models/app_configuration.js +11 -3
  35. package/src/models/application.js +106 -7
  36. package/src/models/exit-strategy-option.js +24 -0
  37. package/src/models/json-array.js +28 -0
  38. package/src/models/log-v4.js +9 -29
  39. package/src/models/log.js +9 -2
  40. package/src/models/namespaces.js +20 -0
  41. package/src/models/organisation.js +0 -20
  42. package/src/models/utils.js +8 -1
  43. package/src/models/accesslogs.js +0 -54
  44. package/vendors/README_VENDORS.md +0 -18
  45. package/vendors/curlconverter-parse.js +0 -3709
@@ -1,15 +1,16 @@
1
1
  'use strict';
2
2
 
3
- const AppConfig = require('../models/app_configuration.js');
3
+ const Application = require('../models/application.js');
4
4
  const Logger = require('../logger.js');
5
+ const colors = require('colors/safe');
5
6
  const variables = require('../models/variables.js');
6
7
  const { sendToApi } = require('../models/send-to-api.js');
7
8
  const { toNameEqualsValueString, validateName } = require('@clevercloud/client/cjs/utils/env-vars.js');
8
9
  const application = require('@clevercloud/client/cjs/api/v2/application.js');
9
10
 
10
11
  async function list (params) {
11
- const { alias, 'add-export': addExports } = params.options;
12
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
12
+ const { alias, app: appIdOrName, 'add-export': addExportsOption, format } = params.options;
13
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
13
14
 
14
15
  const [envFromApp, envFromAddons, envFromDeps] = await Promise.all([
15
16
  application.getAllEnvVars({ id: ownerId, appId }).then(sendToApi),
@@ -17,30 +18,58 @@ async function list (params) {
17
18
  application.getAllEnvVarsForDependencies({ id: ownerId, appId }).then(sendToApi),
18
19
  ]);
19
20
 
20
- Logger.println('# Manually set env variables');
21
- Logger.println(toNameEqualsValueString(envFromApp, { addExports }));
22
-
23
- envFromAddons.forEach((addon) => {
24
- Logger.println('# Addon ' + addon.addon_name);
25
- Logger.println(toNameEqualsValueString(addon.env, { addExports }));
26
- });
27
-
28
- envFromDeps.forEach((dep) => {
29
- Logger.println('# Dependency ' + dep.app_name);
30
- Logger.println(toNameEqualsValueString(dep.env, { addExports }));
31
- });
32
- };
21
+ switch (format) {
22
+ case 'json': {
23
+ Logger.printJson({
24
+ env: envFromApp,
25
+ fromAddons: envFromAddons.map((addon) => ({
26
+ addonId: addon.addon_id,
27
+ addonName: addon.addon_name,
28
+ env: addon.env,
29
+ })),
30
+ fromDependencies: envFromDeps.map((dep) => ({
31
+ addonId: dep.app_id,
32
+ addonName: dep.app_name,
33
+ env: dep.env,
34
+ })),
35
+ });
36
+ break;
37
+ }
38
+ case 'shell':
39
+ case 'human':
40
+ default: {
41
+ if (addExportsOption) {
42
+ Logger.println(colors.yellow('`--add-export` option is deprecated. Use `--format shell` instead.'));
43
+ }
44
+
45
+ const addExports = addExportsOption || format === 'shell';
46
+
47
+ Logger.println('# Manually set env variables');
48
+ Logger.println(toNameEqualsValueString(envFromApp, { addExports }));
49
+
50
+ envFromAddons.forEach((addon) => {
51
+ Logger.println('# Addon ' + addon.addon_name);
52
+ Logger.println(toNameEqualsValueString(addon.env, { addExports }));
53
+ });
54
+
55
+ envFromDeps.forEach((dep) => {
56
+ Logger.println('# Dependency ' + dep.app_name);
57
+ Logger.println(toNameEqualsValueString(dep.env, { addExports }));
58
+ });
59
+ }
60
+ }
61
+ }
33
62
 
34
63
  async function set (params) {
35
64
  const [envName, value] = params.args;
36
- const { alias } = params.options;
65
+ const { alias, app: appIdOrName } = params.options;
37
66
 
38
67
  const nameIsValid = validateName(envName);
39
68
  if (!nameIsValid) {
40
69
  throw new Error(`Environment variable name ${envName} is invalid`);
41
70
  }
42
71
 
43
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
72
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
44
73
 
45
74
  await application.updateEnvVar({ id: ownerId, appId, envName }, { value }).then(sendToApi);
46
75
 
@@ -49,8 +78,8 @@ async function set (params) {
49
78
 
50
79
  async function rm (params) {
51
80
  const [envName] = params.args;
52
- const { alias } = params.options;
53
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
81
+ const { alias, app: appIdOrName } = params.options;
82
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
54
83
 
55
84
  await application.removeEnvVar({ id: ownerId, appId, envName }).then(sendToApi);
56
85
 
@@ -58,9 +87,9 @@ async function rm (params) {
58
87
  };
59
88
 
60
89
  async function importEnv (params) {
61
- const { alias, json } = params.options;
90
+ const { alias, app: appIdOrName, json } = params.options;
62
91
  const format = json ? 'json' : 'name-equals-value';
63
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
92
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
64
93
 
65
94
  const envVars = await variables.readVariablesFromStdin(format);
66
95
  await application.updateAllEnvVars({ id: ownerId, appId }, envVars).then(sendToApi);
@@ -70,7 +99,7 @@ async function importEnv (params) {
70
99
 
71
100
  async function importVarsFromLocalEnv (params) {
72
101
  const [envNames] = params.args;
73
- const { alias } = params.options;
102
+ const { alias, app: appIdOrName } = params.options;
74
103
 
75
104
  for (const envName of envNames) {
76
105
  const nameIsValid = validateName(envName);
@@ -79,7 +108,7 @@ async function importVarsFromLocalEnv (params) {
79
108
  }
80
109
  }
81
110
 
82
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
111
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
83
112
 
84
113
  for (const envName of envNames) {
85
114
  const value = process.env[envName] || '';
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const AppConfig = require('../models/app_configuration.js');
3
+ const Application = require('../models/application.js');
4
4
  const LogV2 = require('../models/log.js');
5
5
  const Log = require('../models/log-v4.js');
6
6
  const Logger = require('../logger.js');
@@ -9,7 +9,7 @@ const colors = require('colors/safe');
9
9
  const { resolveAddonId } = require('../models/ids-resolver.js');
10
10
 
11
11
  async function appLogs (params) {
12
- const { alias, addon: addonIdOrRealId, after: since, before: until, search, 'deployment-id': deploymentId, format } = params.options;
12
+ const { alias, app: appIdOrName, addon: addonIdOrRealId, after: since, before: until, search, 'deployment-id': deploymentId, format } = params.options;
13
13
 
14
14
  // ignore --search ""
15
15
  const filter = (search !== '') ? search : null;
@@ -27,7 +27,7 @@ async function appLogs (params) {
27
27
  return LogV2.displayLogs({ appAddonId: addonId, since, until, filter, deploymentId });
28
28
  }
29
29
 
30
- const { appId, ownerId } = await AppConfig.getAppDetails({ alias });
30
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
31
31
 
32
32
  if (isForHuman) {
33
33
  Logger.println(colors.blue('Waiting for application logs…'));
@@ -8,34 +8,49 @@ const { getOwnerAndApp, getOrgaIdOrUserId } = require('../models/notification.js
8
8
  const { getEmailhooks, createEmailhook, deleteEmailhook } = require('@clevercloud/client/cjs/api/v2/notification.js');
9
9
  const { sendToApi } = require('../models/send-to-api.js');
10
10
 
11
- function displayEmailhook (hook) {
12
- Logger.println((hook.name && colors.bold(hook.name)) || hook.id);
13
- Logger.println(` id: ${hook.id}`);
14
- Logger.println(` services: ${(hook.scope && hook.scope.join(', ')) || hook.ownerId}`);
15
- Logger.println(` events: ${(hook.events && hook.events.join(', ')) || colors.bold('ALL')}`);
16
- if (hook.notified) {
17
- Logger.println(' to:');
18
- hook.notified.forEach((target) => Logger.println(` ${target.target || 'whole team'}`));
19
- }
20
- else {
21
- Logger.println(' to: whole team');
22
- }
23
- Logger.println();
24
- }
25
-
26
11
  async function list (params) {
27
- const { org, 'list-all': listAll } = params.options;
12
+ const { org, 'list-all': listAll, format } = params.options;
28
13
 
29
14
  // TODO: fix alias option
30
15
  const { ownerId, appId } = await getOwnerAndApp(null, org, !listAll);
31
16
  const hooks = await getEmailhooks({ ownerId }).then(sendToApi);
32
17
 
33
- hooks
18
+ const formattedHooks = hooks
34
19
  .filter((hook) => {
35
20
  const emptyScope = !hook.scope || hook.scope.length === 0;
36
21
  return !appId || emptyScope || hook.scope.includes(appId);
37
22
  })
38
- .forEach((hook) => displayEmailhook(hook));
23
+ .map((hook) => ({
24
+ id: hook.id,
25
+ name: hook.name,
26
+ ownerId: hook.ownerId,
27
+ services: hook.scope ?? [hook.ownerId],
28
+ events: hook.events ?? ['ALL'],
29
+ notified: hook.notified ? hook.notified.map(({ target }) => target ?? 'whole team') : ['whole team'],
30
+ }));
31
+
32
+ switch (format) {
33
+ case 'json': {
34
+ Logger.printJson(formattedHooks);
35
+ break;
36
+ }
37
+ case 'human':
38
+ default: {
39
+ formattedHooks.forEach((hook, i) => {
40
+ Logger.println(colors.bold(hook.name ?? hook.id));
41
+ Logger.println(` id: ${hook.id}`);
42
+ Logger.println(` services: ${hook.services.join(', ')}`);
43
+ Logger.println(` events: ${hook.events.join(', ')}`);
44
+ if (hook.notified.length > 1) {
45
+ Logger.println(' to:');
46
+ hook.notified.forEach((target) => Logger.println(` ${target}`));
47
+ }
48
+ else {
49
+ Logger.println(` to: ${hook.notified[0]}`);
50
+ }
51
+ });
52
+ }
53
+ }
39
54
  }
40
55
 
41
56
  function getEmailNotificationTargets (notifTargets) {
@@ -2,13 +2,13 @@
2
2
 
3
3
  const openPage = require('open');
4
4
 
5
- const AppConfig = require('../models/app_configuration.js');
5
+ const Application = require('../models/application.js');
6
6
  const Domain = require('../models/domain.js');
7
7
  const Logger = require('../logger.js');
8
8
 
9
9
  async function open (params) {
10
- const { alias } = params.options;
11
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
10
+ const { alias, app: appIdOrName } = params.options;
11
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
12
12
 
13
13
  const vhost = await Domain.getBest(appId, ownerId);
14
14
  const url = 'https://' + vhost.fqdn;
@@ -5,15 +5,35 @@ const colors = require('colors/safe');
5
5
  const Logger = require('../logger.js');
6
6
  const User = require('../models/user.js');
7
7
 
8
- async function profile () {
9
- const { id, name, email, preferredMFA } = await User.getCurrent();
10
- const has2FA = (preferredMFA != null && preferredMFA !== 'NONE') ? 'yes' : 'no';
11
- const formattedName = name || colors.red.bold('[not specified]');
12
- Logger.println('You\'re currently logged in as:');
13
- Logger.println('User id ' + id);
14
- Logger.println('Name ' + formattedName);
15
- Logger.println('Email ' + email);
16
- Logger.println('Two factor auth ' + has2FA);
8
+ async function profile (params) {
9
+ const { format } = params.options;
10
+
11
+ const user = await User.getCurrent();
12
+
13
+ const formattedUser = {
14
+ id: user.id,
15
+ email: user.email,
16
+ name: user.name,
17
+ avatar: user.avatar,
18
+ creationDate: new Date(user.creationDate),
19
+ lang: user.lang,
20
+ has2FA: (user.preferredMFA != null && user.preferredMFA !== 'NONE'),
21
+ };
22
+
23
+ switch (format) {
24
+ case 'json': {
25
+ Logger.printJson(formattedUser);
26
+ break;
27
+ }
28
+ case 'human':
29
+ default: {
30
+ Logger.println('You\'re currently logged in as:');
31
+ Logger.println(`User id ${formattedUser.id}`);
32
+ Logger.println(`Name ${formattedUser.name ?? colors.red.bold('[not specified]')}`);
33
+ Logger.println(`Email ${formattedUser.email}`);
34
+ Logger.println(`Two factor auth ${formattedUser.has2FA ? 'yes' : 'no'}`);
35
+ }
36
+ }
17
37
  };
18
38
 
19
39
  module.exports = { profile };
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const AppConfig = require('../models/app_configuration.js');
3
+ const Application = require('../models/application.js');
4
4
  const Logger = require('../logger.js');
5
5
  const variables = require('../models/variables.js');
6
6
  const { sendToApi } = require('../models/send-to-api.js');
@@ -8,27 +8,38 @@ const { toNameEqualsValueString, validateName } = require('@clevercloud/client/c
8
8
  const application = require('@clevercloud/client/cjs/api/v2/application.js');
9
9
 
10
10
  async function list (params) {
11
- const { alias } = params.options;
12
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
11
+ const { alias, app: appIdOrName, format } = params.options;
12
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
13
13
 
14
14
  const publishedConfigs = await application.getAllExposedEnvVars({ id: ownerId, appId }).then(sendToApi);
15
- const pairs = Object.entries(publishedConfigs)
16
- .map(([name, value]) => ({ name, value }));
17
-
18
- Logger.println('# Published configs');
19
- Logger.println(toNameEqualsValueString(pairs));
20
- };
15
+ const pairs = Object.entries(publishedConfigs).map(([name, value]) => ({ name, value }));
16
+
17
+ switch (format) {
18
+ case 'json': {
19
+ Logger.printJson(pairs);
20
+ break;
21
+ }
22
+ case 'shell':
23
+ Logger.println(toNameEqualsValueString(pairs, { addExports: true }));
24
+ break;
25
+ case 'human':
26
+ default: {
27
+ Logger.println('# Published configs');
28
+ Logger.println(toNameEqualsValueString(pairs, { addExports: false }));
29
+ }
30
+ }
31
+ }
21
32
 
22
33
  async function set (params) {
23
34
  const [varName, varValue] = params.args;
24
- const { alias } = params.options;
35
+ const { alias, app: appIdOrName } = params.options;
25
36
 
26
37
  const nameIsValid = validateName(varName);
27
38
  if (!nameIsValid) {
28
39
  throw new Error(`Published config name ${varName} is invalid`);
29
40
  }
30
41
 
31
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
42
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
32
43
 
33
44
  const publishedConfigs = await application.getAllExposedEnvVars({ id: ownerId, appId }).then(sendToApi);
34
45
  publishedConfigs[varName] = varValue;
@@ -39,8 +50,8 @@ async function set (params) {
39
50
 
40
51
  async function rm (params) {
41
52
  const [varName] = params.args;
42
- const { alias } = params.options;
43
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
53
+ const { alias, app: appIdOrName } = params.options;
54
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
44
55
 
45
56
  const publishedConfigs = await application.getAllExposedEnvVars({ id: ownerId, appId }).then(sendToApi);
46
57
  delete publishedConfigs[varName];
@@ -50,9 +61,9 @@ async function rm (params) {
50
61
  };
51
62
 
52
63
  async function importEnv (params) {
53
- const { alias, json } = params.options;
64
+ const { alias, app: appIdOrName, json } = params.options;
54
65
  const format = json ? 'json' : 'name-equals-value';
55
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
66
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
56
67
 
57
68
  const publishedConfigs = await variables.readVariablesFromStdin(format);
58
69
  await application.updateAllExposedEnvVars({ id: ownerId, appId }, publishedConfigs).then(sendToApi);
@@ -2,26 +2,33 @@
2
2
 
3
3
  const colors = require('colors/safe');
4
4
 
5
- const AppConfig = require('../models/app_configuration.js');
6
5
  const Application = require('../models/application.js');
7
6
  const git = require('../models/git.js');
8
7
  const Log = require('../models/log-v4.js');
9
8
  const Logger = require('../logger.js');
9
+ const ExitStrategy = require('../models/exit-strategy-option.js');
10
10
 
11
11
  // Once the API call to redeploy() has been triggerred successfully,
12
12
  // the rest (waiting for deployment state to evolve and displaying logs) is done with auto retry (resilient to network pb)
13
13
  async function restart (params) {
14
- const { alias, quiet, commit, 'without-cache': withoutCache, follow } = params.options;
14
+ const { alias, app: appIdOrName, quiet, commit, 'without-cache': withoutCache, follow, 'exit-on': exitOnDeploy } = params.options;
15
15
 
16
- const { ownerId, appId, name: appName } = await AppConfig.getAppDetails({ alias });
16
+ const exitStrategy = ExitStrategy.get(follow, exitOnDeploy);
17
+
18
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
17
19
  const fullCommitId = await git.resolveFullCommitId(commit);
18
20
  const app = await Application.get(ownerId, appId);
21
+
22
+ if (app == null) {
23
+ throw new Error('The application doesn\'t exist');
24
+ }
25
+
19
26
  const remoteCommitId = app.commitId;
20
27
 
21
28
  const commitId = fullCommitId || remoteCommitId;
22
29
  if (commitId != null) {
23
30
  const cacheSuffix = withoutCache ? ' without using cache' : '';
24
- Logger.println(`Restarting ${appName} on commit ${colors.green(commitId)}${cacheSuffix}`);
31
+ Logger.println(`Restarting ${app.name} on commit ${colors.green(commitId)}${cacheSuffix}`);
25
32
  }
26
33
 
27
34
  // This should be handled by the API when a deployment ID is set but we'll do this for now
@@ -34,8 +41,8 @@ async function restart (params) {
34
41
  appId,
35
42
  deploymentId: redeploy.deploymentId,
36
43
  quiet,
37
- follow,
38
44
  redeployDate,
45
+ exitStrategy,
39
46
  });
40
47
  }
41
48
 
@@ -1,6 +1,5 @@
1
1
  'use strict';
2
2
 
3
- const AppConfig = require('../models/app_configuration.js');
4
3
  const Application = require('../models/application.js');
5
4
  const Logger = require('../logger.js');
6
5
 
@@ -45,9 +44,9 @@ function validateOptions (options) {
45
44
  }
46
45
 
47
46
  async function scale (params) {
48
- const { alias } = params.options;
47
+ const { alias, app: appIdOrName } = params.options;
49
48
  const { minFlavor, maxFlavor, minInstances, maxInstances, buildFlavor } = validateOptions(params.options);
50
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
49
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
51
50
 
52
51
  await Application.setScalability(appId, ownerId, {
53
52
  minFlavor,
@@ -1,62 +1,89 @@
1
1
  'use strict';
2
2
 
3
3
  const Addon = require('../models/addon.js');
4
- const AppConfig = require('../models/app_configuration.js');
5
4
  const Application = require('../models/application.js');
6
5
  const Logger = require('../logger.js');
7
6
 
8
7
  async function list (params) {
9
- const { alias, 'show-all': showAll, 'only-apps': onlyApps, 'only-addons': onlyAddons } = params.options;
8
+ const { alias, app: appIdOrName, 'show-all': showAll, 'only-apps': onlyApps, 'only-addons': onlyAddons, format } = params.options;
10
9
  if (onlyApps && onlyAddons) {
11
10
  throw new Error('--only-apps and --only-addons are mutually exclusive');
12
11
  }
13
12
 
14
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
13
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
14
+
15
+ const formattedServices = {};
15
16
 
16
17
  if (!onlyAddons) {
17
18
  const apps = await Application.listDependencies(ownerId, appId, showAll);
18
- Logger.println('Applications:');
19
- apps.forEach(({ isLinked, name }) => Logger.println(`${isLinked ? '*' : ' '} ${name}`));
19
+ formattedServices.applications = apps.map((app) => ({
20
+ id: app.id,
21
+ name: app.name,
22
+ isLinked: app.isLinked,
23
+ }));
20
24
  }
21
25
 
22
26
  if (!onlyApps) {
23
27
  const addons = await Addon.list(ownerId, appId, showAll);
24
- Logger.println('Addons:');
25
- addons.forEach(({ isLinked, name, realId }) => Logger.println(`${isLinked ? '*' : ' '} ${name} (${realId})`));
28
+ formattedServices.addons = addons.map((addon) => ({
29
+ id: addon.id,
30
+ realId: addon.realId,
31
+ name: addon.name,
32
+ isLinked: addon.isLinked,
33
+ }));
34
+ }
35
+
36
+ switch (format) {
37
+ case 'json': {
38
+ Logger.printJson(formattedServices);
39
+ break;
40
+ }
41
+ case 'human':
42
+ default: {
43
+ if (formattedServices.applications) {
44
+ Logger.println('Applications:');
45
+ formattedServices.applications.forEach(({ isLinked, name }) => Logger.println(`${isLinked ? '*' : ' '} ${name}`));
46
+ }
47
+
48
+ if (formattedServices.addons) {
49
+ Logger.println('Addons:');
50
+ formattedServices.addons.forEach(({ isLinked, name, realId }) => Logger.println(`${isLinked ? '*' : ' '} ${name} (${realId})`));
51
+ }
52
+ }
26
53
  }
27
54
  }
28
55
 
29
56
  async function linkApp (params) {
30
- const { alias } = params.options;
57
+ const { alias, app: appIdOrName } = params.options;
31
58
  const [dependency] = params.args;
32
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
59
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
33
60
 
34
61
  await Application.link(ownerId, appId, dependency);
35
62
  Logger.println(`App ${dependency.app_id || dependency.app_name} successfully linked`);
36
63
  }
37
64
 
38
65
  async function unlinkApp (params) {
39
- const { alias } = params.options;
66
+ const { alias, app: appIdOrName } = params.options;
40
67
  const [dependency] = params.args;
41
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
68
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
42
69
 
43
70
  await Application.unlink(ownerId, appId, dependency);
44
71
  Logger.println(`App ${dependency.app_id || dependency.app_name} successfully unlinked`);
45
72
  }
46
73
 
47
74
  async function linkAddon (params) {
48
- const { alias } = params.options;
75
+ const { alias, app: appIdOrName } = params.options;
49
76
  const [addon] = params.args;
50
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
77
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
51
78
 
52
79
  await Addon.link(ownerId, appId, addon);
53
80
  Logger.println(`Addon ${addon.addon_id || addon.addon_name} successfully linked`);
54
81
  }
55
82
 
56
83
  async function unlinkAddon (params) {
57
- const { alias } = params.options;
84
+ const { alias, app: appIdOrName } = params.options;
58
85
  const [addon] = params.args;
59
- const { ownerId, appId } = await AppConfig.getAppDetails({ alias });
86
+ const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
60
87
 
61
88
  await Addon.unlink(ownerId, appId, addon);
62
89
  Logger.println(`Addon ${addon.addon_id || addon.addon_name} successfully unlinked`);
@@ -2,13 +2,13 @@
2
2
 
3
3
  const { spawn } = require('child_process');
4
4
 
5
- const AppConfig = require('../models/app_configuration.js');
5
+ const Application = require('../models/application.js');
6
6
  const { conf } = require('../models/configuration.js');
7
7
 
8
8
  async function ssh (params) {
9
- const { alias, 'identity-file': identityFile } = params.options;
9
+ const { alias, app: appIdOrName, 'identity-file': identityFile } = params.options;
10
10
 
11
- const { appId } = await AppConfig.getAppDetails({ alias });
11
+ const { appId } = await Application.resolveId(appIdOrName, alias);
12
12
  const sshParams = ['-t', conf.SSH_GATEWAY, appId];
13
13
  if (identityFile != null) {
14
14
  sshParams.push('-i', identityFile);