clever-tools 4.7.1 → 4.9.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 (89) hide show
  1. package/bin/clever.js +11 -1
  2. package/package.json +2 -2
  3. package/src/clever-client/drains.js +18 -18
  4. package/src/clever-client/k8s.js +197 -0
  5. package/src/commands/README.md +1 -0
  6. package/src/commands/accesslogs/accesslogs.command.js +2 -2
  7. package/src/commands/activity/activity.command.js +1 -1
  8. package/src/commands/addon/addon.create.command.js +2 -3
  9. package/src/commands/addon/addon.delete.command.js +2 -2
  10. package/src/commands/addon/addon.docs.md +2 -2
  11. package/src/commands/addon/addon.env.command.js +4 -6
  12. package/src/commands/config-provider/config-provider.command.js +0 -4
  13. package/src/commands/config-provider/config-provider.import.command.js +1 -1
  14. package/src/commands/config-provider/config-provider.list.command.js +8 -19
  15. package/src/commands/config-provider/config-provider.open.command.js +1 -1
  16. package/src/commands/console/console.command.js +3 -2
  17. package/src/commands/curl/curl.command.js +0 -1
  18. package/src/commands/database/database.backups.command.js +4 -7
  19. package/src/commands/database/database.backups.download.command.js +5 -7
  20. package/src/commands/database/database.command.js +0 -4
  21. package/src/commands/database/database.docs.md +2 -2
  22. package/src/commands/deploy/deploy.command.js +1 -1
  23. package/src/commands/deploy/deploy.docs.md +1 -1
  24. package/src/commands/drain/drain.command.js +14 -9
  25. package/src/commands/drain/drain.create.command.js +9 -13
  26. package/src/commands/drain/drain.disable.command.js +7 -7
  27. package/src/commands/drain/drain.docs.md +6 -0
  28. package/src/commands/drain/drain.enable.command.js +7 -7
  29. package/src/commands/drain/drain.get.command.js +12 -8
  30. package/src/commands/drain/drain.remove.command.js +7 -7
  31. package/src/commands/emails/emails.open.command.js +1 -4
  32. package/src/commands/global.commands.js +52 -0
  33. package/src/commands/global.options.js +7 -7
  34. package/src/commands/help/help.command.js +0 -3
  35. package/src/commands/k8s/k8s.activity.command.js +53 -0
  36. package/src/commands/k8s/k8s.args.js +6 -0
  37. package/src/commands/k8s/k8s.command.js +0 -4
  38. package/src/commands/k8s/k8s.create.command.js +87 -3
  39. package/src/commands/k8s/k8s.delete.command.js +15 -20
  40. package/src/commands/k8s/k8s.docs.md +264 -1
  41. package/src/commands/k8s/k8s.get.command.js +65 -4
  42. package/src/commands/k8s/k8s.nodegroups.command.js +7 -0
  43. package/src/commands/k8s/k8s.nodegroups.create.command.js +79 -0
  44. package/src/commands/k8s/k8s.nodegroups.delete.command.js +34 -0
  45. package/src/commands/k8s/k8s.nodegroups.get.command.js +66 -0
  46. package/src/commands/k8s/k8s.nodegroups.list.command.js +49 -0
  47. package/src/commands/k8s/k8s.nodegroups.update.command.js +86 -0
  48. package/src/commands/k8s/k8s.quota.command.js +77 -0
  49. package/src/commands/k8s/k8s.update.command.js +72 -0
  50. package/src/commands/k8s/k8s.version.check.command.js +18 -0
  51. package/src/commands/k8s/k8s.version.command.js +18 -0
  52. package/src/commands/k8s/k8s.version.update.command.js +18 -0
  53. package/src/commands/logs/logs.command.js +4 -5
  54. package/src/commands/ng/ng.docs.md +0 -1
  55. package/src/commands/ng/ng.get-config.command.js +3 -14
  56. package/src/commands/ng/ng.options.js +1 -1
  57. package/src/commands/notify-email/notify-email.remove.command.js +2 -2
  58. package/src/commands/oauth-consumers/oauth-consumers.args.js +8 -0
  59. package/src/commands/oauth-consumers/oauth-consumers.command.js +6 -0
  60. package/src/commands/oauth-consumers/oauth-consumers.create.command.js +64 -0
  61. package/src/commands/oauth-consumers/oauth-consumers.delete.command.js +33 -0
  62. package/src/commands/oauth-consumers/oauth-consumers.docs.md +130 -0
  63. package/src/commands/oauth-consumers/oauth-consumers.get.command.js +67 -0
  64. package/src/commands/oauth-consumers/oauth-consumers.list.command.js +34 -0
  65. package/src/commands/oauth-consumers/oauth-consumers.open.command.js +18 -0
  66. package/src/commands/oauth-consumers/oauth-consumers.options.js +48 -0
  67. package/src/commands/oauth-consumers/oauth-consumers.update.command.js +83 -0
  68. package/src/commands/open/open.command.js +1 -1
  69. package/src/commands/otoroshi/otoroshi.docs.md +14 -0
  70. package/src/commands/otoroshi/otoroshi.open.swaggerui.command.js +13 -0
  71. package/src/commands/profile/profile.open.command.js +1 -1
  72. package/src/commands/restart/restart.docs.md +1 -1
  73. package/src/commands/ssh-keys/ssh-keys.open.command.js +1 -1
  74. package/src/commands/webhooks/webhooks.remove.command.js +2 -2
  75. package/src/lib/cliparse-patched.js +2 -0
  76. package/src/lib/get-command-info.js +3 -1
  77. package/src/lib/get-command-info.types.d.ts +4 -0
  78. package/src/lib/k8s.js +411 -11
  79. package/src/lib/operator-commands.js +24 -24
  80. package/src/lib/print-items-by-owner.js +38 -0
  81. package/src/lib/prompts.js +29 -3
  82. package/src/lib/zod-utils.js +51 -0
  83. package/src/models/drain.js +17 -0
  84. package/src/models/ids-resolver.js +38 -20
  85. package/src/models/ng.js +2 -2
  86. package/src/models/notification.js +0 -4
  87. package/src/models/oauth-consumer.js +77 -0
  88. package/src/models/utils.js +1 -1
  89. package/src/parsers.js +10 -0
@@ -6,8 +6,7 @@ import { z } from 'zod';
6
6
  import { defineArgument } from '../../lib/define-argument.js';
7
7
  import { defineCommand } from '../../lib/define-command.js';
8
8
  import { defineOption } from '../../lib/define-option.js';
9
- import { findOwnerId } from '../../models/addon.js';
10
- import { resolveRealId } from '../../models/ids-resolver.js';
9
+ import { resolveAddon } from '../../models/ids-resolver.js';
11
10
  import { sendToApi } from '../../models/send-to-api.js';
12
11
  import { orgaIdOrNameOption } from '../global.options.js';
13
12
  import { databaseIdArg } from './database.args.js';
@@ -23,7 +22,7 @@ export const databaseBackupsDownloadCommand = defineCommand({
23
22
  aliases: ['out'],
24
23
  placeholder: 'file-path',
25
24
  }),
26
- org: orgaIdOrNameOption,
25
+ org: { ...orgaIdOrNameOption, deprecated: 'organisation is now resolved automatically' },
27
26
  },
28
27
  args: [
29
28
  databaseIdArg,
@@ -34,12 +33,11 @@ export const databaseBackupsDownloadCommand = defineCommand({
34
33
  }),
35
34
  ],
36
35
  async handler(options, addonIdOrRealId, backupId) {
37
- const { org, output } = options;
36
+ const { output } = options;
38
37
 
39
- const addonId = await resolveRealId(addonIdOrRealId);
40
- const ownerId = await findOwnerId(org, addonId);
38
+ const { ownerId, realId } = await resolveAddon(addonIdOrRealId);
41
39
 
42
- const backups = await getBackups({ ownerId, ref: addonId }).then(sendToApi);
40
+ const backups = await getBackups({ ownerId, ref: realId }).then(sendToApi);
43
41
  const backup = backups.find((backup) => backup.backup_id === backupId);
44
42
 
45
43
  if (backup == null) {
@@ -3,8 +3,4 @@ import { defineCommand } from '../../lib/define-command.js';
3
3
  export const databaseCommand = defineCommand({
4
4
  description: 'Manage databases and backups',
5
5
  since: '2.10.0',
6
- options: {},
7
- args: [],
8
- // Parent command - no handler, only contains subcommands
9
- handler: null,
10
6
  });
@@ -27,7 +27,7 @@ clever database backups <database-id|addon-id> [options]
27
27
  |Name|Description|
28
28
  |---|---|
29
29
  |`-F`, `--format` `<format>`|Output format (human, json) (default: human)|
30
- |`-o`, `--org`, `--owner` `<org-id\|org-name>`|Organisation to target by its ID (or name, if unambiguous)|
30
+ |`-o`, `--org`, `--owner` `<org-id\|org-name>`|Organisation to target by its ID (or name, if unambiguous) *(deprecated, organisation is now resolved automatically)*|
31
31
 
32
32
  ## ➡️ `clever database backups download` <kbd>Since 2.10.0</kbd>
33
33
 
@@ -48,5 +48,5 @@ clever database backups download <database-id|addon-id> <backup-id> [options]
48
48
 
49
49
  |Name|Description|
50
50
  |---|---|
51
- |`-o`, `--org`, `--owner` `<org-id\|org-name>`|Organisation to target by its ID (or name, if unambiguous)|
51
+ |`-o`, `--org`, `--owner` `<org-id\|org-name>`|Organisation to target by its ID (or name, if unambiguous) *(deprecated, organisation is now resolved automatically)*|
52
52
  |`--output`, `--out` `<file-path>`|Redirect the output of the command in a file|
@@ -67,7 +67,7 @@ export const deployCommand = defineCommand({
67
67
  sameCommitPolicy: defineOption({
68
68
  name: 'same-commit-policy',
69
69
  schema: z.enum(['error', 'ignore', 'restart', 'rebuild']).default('error'),
70
- description: 'What to do when local and remote commit are identical (error, ignore, restart, rebuild)',
70
+ description: 'What to do when local and remote commit are identical',
71
71
  aliases: ['p'],
72
72
  placeholder: 'policy',
73
73
  }),
@@ -14,7 +14,7 @@ clever deploy [options]
14
14
  |---|---|
15
15
  |`-a`, `--alias` `<alias>`|Short name for the application|
16
16
  |`-b`, `--branch` `<branch>`|Branch to push (current branch by default)|
17
- |`-e`, `--exit-on` `<step>`|Step at which the logs streaming is ended, steps are: deploy-start, deploy-end, never (default: deploy-end)|
17
+ |`-e`, `--exit-on` `<step>`|Step at which the logs streaming is ended (deploy-start, deploy-end, never) (default: deploy-end)|
18
18
  |`--follow`|Continue to follow logs after deployment has ended *(deprecated, use `--exit-on never` instead)*|
19
19
  |`-f`, `--force`|Force deploy even if it's not fast-forwardable|
20
20
  |`-q`, `--quiet`|Don't show logs during deployment|
@@ -1,26 +1,30 @@
1
1
  import { getDrains } from '../../clever-client/drains.js';
2
2
  import { defineCommand } from '../../lib/define-command.js';
3
3
  import { Logger } from '../../logger.js';
4
- import * as Application from '../../models/application.js';
5
- import { formatDrain } from '../../models/drain.js';
4
+ import { formatDrain, resolveDrainResource } from '../../models/drain.js';
6
5
  import { sendToApi } from '../../models/send-to-api.js';
7
- import { aliasOption, appIdOrNameOption, humanJsonOutputFormatOption } from '../global.options.js';
6
+ import {
7
+ addonIdOrRealIdOption,
8
+ aliasOption,
9
+ appIdOrNameOption,
10
+ humanJsonOutputFormatOption,
11
+ } from '../global.options.js';
8
12
 
9
13
  export const drainCommand = defineCommand({
10
14
  description: 'Manage drains',
11
15
  since: '0.9.0',
12
16
  options: {
13
17
  alias: aliasOption,
14
- app: appIdOrNameOption,
18
+ appIdOrName: appIdOrNameOption,
19
+ addonIdOrRealId: addonIdOrRealIdOption,
15
20
  format: humanJsonOutputFormatOption,
16
21
  },
17
22
  args: [],
18
23
  async handler(options) {
19
- const { alias, app: appIdOrName, format } = options;
24
+ const { alias, appIdOrName, addonIdOrRealId, format } = options;
25
+ const { ownerId, resourceId } = await resolveDrainResource(alias, appIdOrName, addonIdOrRealId);
20
26
 
21
- const { ownerId, appId: applicationId } = await Application.resolveId(appIdOrName, alias);
22
-
23
- const drains = await getDrains({ ownerId, applicationId }).then(sendToApi);
27
+ const drains = await getDrains({ ownerId, resourceId }).then(sendToApi);
24
28
 
25
29
  switch (format) {
26
30
  case 'json': {
@@ -30,7 +34,8 @@ export const drainCommand = defineCommand({
30
34
  case 'human':
31
35
  default: {
32
36
  if (drains.length === 0) {
33
- Logger.println(`There are no drains for ${applicationId}`);
37
+ const resourceLabel = addonIdOrRealId ?? appIdOrName ?? resourceId;
38
+ Logger.println(`There are no drains for ${resourceLabel}`);
34
39
  return;
35
40
  }
36
41
 
@@ -5,10 +5,9 @@ import { defineCommand } from '../../lib/define-command.js';
5
5
  import { defineOption } from '../../lib/define-option.js';
6
6
  import { styleText } from '../../lib/style-text.js';
7
7
  import { Logger } from '../../logger.js';
8
- import * as Application from '../../models/application.js';
9
- import { DRAIN_TYPE_CLI_CODES, DRAIN_TYPES } from '../../models/drain.js';
8
+ import { DRAIN_TYPE_CLI_CODES, DRAIN_TYPES, resolveDrainResource } from '../../models/drain.js';
10
9
  import { sendToApi } from '../../models/send-to-api.js';
11
- import { aliasOption, appIdOrNameOption } from '../global.options.js';
10
+ import { addonIdOrRealIdOption, aliasOption, appIdOrNameOption } from '../global.options.js';
12
11
 
13
12
  export const drainCreateCommand = defineCommand({
14
13
  description: 'Create a drain',
@@ -50,14 +49,14 @@ export const drainCreateCommand = defineCommand({
50
49
  placeholder: 'sd-params',
51
50
  }),
52
51
  alias: aliasOption,
53
- app: appIdOrNameOption,
52
+ appIdOrName: appIdOrNameOption,
53
+ addonIdOrRealId: addonIdOrRealIdOption,
54
54
  },
55
55
  args: [
56
56
  defineArgument({
57
- schema: z.string(),
58
- description: `Drain type (${DRAIN_TYPE_CLI_CODES.join(', ')})`,
57
+ schema: z.enum(DRAIN_TYPE_CLI_CODES),
58
+ description: 'Drain type',
59
59
  placeholder: 'drain-type',
60
- complete: DRAIN_TYPE_CLI_CODES,
61
60
  }),
62
61
  defineArgument({
63
62
  schema: z.string(),
@@ -66,15 +65,12 @@ export const drainCreateCommand = defineCommand({
66
65
  }),
67
66
  ],
68
67
  async handler(options, drainTypeCliCode, url) {
69
- const { alias, app: appIdOrName } = options;
68
+ const { alias, appIdOrName, addonIdOrRealId } = options;
70
69
  const { username, password, apiKey, indexPrefix, rfc5424StructuredDataParameters } = options;
71
70
 
72
71
  const drainType = Object.values(DRAIN_TYPES).find((drainType) => drainType.cliCode === drainTypeCliCode);
73
- if (!drainType) {
74
- throw new Error(`Invalid drain type. Supported types are: ${DRAIN_TYPE_CLI_CODES.join(', ')}`);
75
- }
76
72
 
77
- const { ownerId, appId: applicationId } = await Application.resolveId(appIdOrName, alias);
73
+ const { ownerId, resourceId } = await resolveDrainResource(alias, appIdOrName, addonIdOrRealId);
78
74
 
79
75
  const body = {
80
76
  kind: 'LOG',
@@ -122,7 +118,7 @@ export const drainCreateCommand = defineCommand({
122
118
  }
123
119
  }
124
120
 
125
- const drain = await createDrain({ ownerId, applicationId, body }).then(sendToApi);
121
+ const drain = await createDrain({ ownerId, resourceId, body }).then(sendToApi);
126
122
  Logger.printSuccess(`Drain ${styleText(['bold', 'green'], drain.id)} has been successfully created and enabled!`);
127
123
  },
128
124
  });
@@ -2,9 +2,9 @@ import { disableDrain } from '../../clever-client/drains.js';
2
2
  import { defineCommand } from '../../lib/define-command.js';
3
3
  import { styleText } from '../../lib/style-text.js';
4
4
  import { Logger } from '../../logger.js';
5
- import * as Application from '../../models/application.js';
5
+ import { resolveDrainResource } from '../../models/drain.js';
6
6
  import { sendToApi } from '../../models/send-to-api.js';
7
- import { aliasOption, appIdOrNameOption } from '../global.options.js';
7
+ import { addonIdOrRealIdOption, aliasOption, appIdOrNameOption } from '../global.options.js';
8
8
  import { drainIdArg } from './drain.args.js';
9
9
 
10
10
  export const drainDisableCommand = defineCommand({
@@ -12,15 +12,15 @@ export const drainDisableCommand = defineCommand({
12
12
  since: '0.9.0',
13
13
  options: {
14
14
  alias: aliasOption,
15
- app: appIdOrNameOption,
15
+ appIdOrName: appIdOrNameOption,
16
+ addonIdOrRealId: addonIdOrRealIdOption,
16
17
  },
17
18
  args: [drainIdArg],
18
19
  async handler(options, drainId) {
19
- const { alias, app: appIdOrName } = options;
20
+ const { alias, appIdOrName, addonIdOrRealId } = options;
21
+ const { ownerId, resourceId } = await resolveDrainResource(alias, appIdOrName, addonIdOrRealId);
20
22
 
21
- const { ownerId, appId: applicationId } = await Application.resolveId(appIdOrName, alias);
22
-
23
- await disableDrain({ ownerId, applicationId, drainId }).then(sendToApi);
23
+ await disableDrain({ ownerId, resourceId, drainId }).then(sendToApi);
24
24
 
25
25
  Logger.printSuccess(`Drain ${styleText(['bold', 'green'], drainId)} has been successfully disabled!`);
26
26
  },
@@ -12,6 +12,7 @@ clever drain [options]
12
12
 
13
13
  |Name|Description|
14
14
  |---|---|
15
+ |`--addon` `<addon-id>`|Add-on ID or real ID|
15
16
  |`-a`, `--alias` `<alias>`|Short name for the application|
16
17
  |`--app` `<app-id\|app-name>`|Application to manage by its ID (or name, if unambiguous)|
17
18
  |`-F`, `--format` `<format>`|Output format (human, json) (default: human)|
@@ -35,6 +36,7 @@ clever drain create <drain-type> <drain-url> [options]
35
36
 
36
37
  |Name|Description|
37
38
  |---|---|
39
+ |`--addon` `<addon-id>`|Add-on ID or real ID|
38
40
  |`-a`, `--alias` `<alias>`|Short name for the application|
39
41
  |`-k`, `--api-key` `<api-key>`|API key (for newrelic)|
40
42
  |`--app` `<app-id\|app-name>`|Application to manage by its ID (or name, if unambiguous)|
@@ -61,6 +63,7 @@ clever drain disable <drain-id> [options]
61
63
 
62
64
  |Name|Description|
63
65
  |---|---|
66
+ |`--addon` `<addon-id>`|Add-on ID or real ID|
64
67
  |`-a`, `--alias` `<alias>`|Short name for the application|
65
68
  |`--app` `<app-id\|app-name>`|Application to manage by its ID (or name, if unambiguous)|
66
69
 
@@ -82,6 +85,7 @@ clever drain enable <drain-id> [options]
82
85
 
83
86
  |Name|Description|
84
87
  |---|---|
88
+ |`--addon` `<addon-id>`|Add-on ID or real ID|
85
89
  |`-a`, `--alias` `<alias>`|Short name for the application|
86
90
  |`--app` `<app-id\|app-name>`|Application to manage by its ID (or name, if unambiguous)|
87
91
 
@@ -103,6 +107,7 @@ clever drain get <drain-id> [options]
103
107
 
104
108
  |Name|Description|
105
109
  |---|---|
110
+ |`--addon` `<addon-id>`|Add-on ID or real ID|
106
111
  |`-a`, `--alias` `<alias>`|Short name for the application|
107
112
  |`--app` `<app-id\|app-name>`|Application to manage by its ID (or name, if unambiguous)|
108
113
  |`-F`, `--format` `<format>`|Output format (human, json) (default: human)|
@@ -125,5 +130,6 @@ clever drain remove <drain-id> [options]
125
130
 
126
131
  |Name|Description|
127
132
  |---|---|
133
+ |`--addon` `<addon-id>`|Add-on ID or real ID|
128
134
  |`-a`, `--alias` `<alias>`|Short name for the application|
129
135
  |`--app` `<app-id\|app-name>`|Application to manage by its ID (or name, if unambiguous)|
@@ -2,9 +2,9 @@ import { enableDrain } from '../../clever-client/drains.js';
2
2
  import { defineCommand } from '../../lib/define-command.js';
3
3
  import { styleText } from '../../lib/style-text.js';
4
4
  import { Logger } from '../../logger.js';
5
- import * as Application from '../../models/application.js';
5
+ import { resolveDrainResource } from '../../models/drain.js';
6
6
  import { sendToApi } from '../../models/send-to-api.js';
7
- import { aliasOption, appIdOrNameOption } from '../global.options.js';
7
+ import { addonIdOrRealIdOption, aliasOption, appIdOrNameOption } from '../global.options.js';
8
8
  import { drainIdArg } from './drain.args.js';
9
9
 
10
10
  export const drainEnableCommand = defineCommand({
@@ -12,15 +12,15 @@ export const drainEnableCommand = defineCommand({
12
12
  since: '0.9.0',
13
13
  options: {
14
14
  alias: aliasOption,
15
- app: appIdOrNameOption,
15
+ appIdOrName: appIdOrNameOption,
16
+ addonIdOrRealId: addonIdOrRealIdOption,
16
17
  },
17
18
  args: [drainIdArg],
18
19
  async handler(options, drainId) {
19
- const { alias, app: appIdOrName } = options;
20
+ const { alias, appIdOrName, addonIdOrRealId } = options;
21
+ const { ownerId, resourceId } = await resolveDrainResource(alias, appIdOrName, addonIdOrRealId);
20
22
 
21
- const { ownerId, appId: applicationId } = await Application.resolveId(appIdOrName, alias);
22
-
23
- await enableDrain({ ownerId, applicationId, drainId }).then(sendToApi);
23
+ await enableDrain({ ownerId, resourceId, drainId }).then(sendToApi);
24
24
 
25
25
  Logger.printSuccess(`Drain ${styleText(['bold', 'green'], drainId)} has been successfully enabled!`);
26
26
  },
@@ -1,10 +1,14 @@
1
1
  import { getDrain } from '../../clever-client/drains.js';
2
2
  import { defineCommand } from '../../lib/define-command.js';
3
3
  import { Logger } from '../../logger.js';
4
- import * as Application from '../../models/application.js';
5
- import { formatDrain } from '../../models/drain.js';
4
+ import { formatDrain, resolveDrainResource } from '../../models/drain.js';
6
5
  import { sendToApi } from '../../models/send-to-api.js';
7
- import { aliasOption, appIdOrNameOption, humanJsonOutputFormatOption } from '../global.options.js';
6
+ import {
7
+ addonIdOrRealIdOption,
8
+ aliasOption,
9
+ appIdOrNameOption,
10
+ humanJsonOutputFormatOption,
11
+ } from '../global.options.js';
8
12
  import { drainIdArg } from './drain.args.js';
9
13
 
10
14
  export const drainGetCommand = defineCommand({
@@ -12,16 +16,16 @@ export const drainGetCommand = defineCommand({
12
16
  since: '0.9.0',
13
17
  options: {
14
18
  alias: aliasOption,
15
- app: appIdOrNameOption,
19
+ appIdOrName: appIdOrNameOption,
20
+ addonIdOrRealId: addonIdOrRealIdOption,
16
21
  format: humanJsonOutputFormatOption,
17
22
  },
18
23
  args: [drainIdArg],
19
24
  async handler(options, drainId) {
20
- const { alias, app: appIdOrName, format } = options;
25
+ const { alias, appIdOrName, addonIdOrRealId, format } = options;
26
+ const { ownerId, resourceId } = await resolveDrainResource(alias, appIdOrName, addonIdOrRealId);
21
27
 
22
- const { ownerId, appId: applicationId } = await Application.resolveId(appIdOrName, alias);
23
-
24
- const drain = await getDrain({ ownerId, applicationId, drainId }).then(sendToApi);
28
+ const drain = await getDrain({ ownerId, resourceId, drainId }).then(sendToApi);
25
29
 
26
30
  switch (format) {
27
31
  case 'json': {
@@ -2,9 +2,9 @@ import { deleteDrain } from '../../clever-client/drains.js';
2
2
  import { defineCommand } from '../../lib/define-command.js';
3
3
  import { styleText } from '../../lib/style-text.js';
4
4
  import { Logger } from '../../logger.js';
5
- import * as Application from '../../models/application.js';
5
+ import { resolveDrainResource } from '../../models/drain.js';
6
6
  import { sendToApi } from '../../models/send-to-api.js';
7
- import { aliasOption, appIdOrNameOption } from '../global.options.js';
7
+ import { addonIdOrRealIdOption, aliasOption, appIdOrNameOption } from '../global.options.js';
8
8
  import { drainIdArg } from './drain.args.js';
9
9
 
10
10
  export const drainRemoveCommand = defineCommand({
@@ -12,15 +12,15 @@ export const drainRemoveCommand = defineCommand({
12
12
  since: '0.9.0',
13
13
  options: {
14
14
  alias: aliasOption,
15
- app: appIdOrNameOption,
15
+ appIdOrName: appIdOrNameOption,
16
+ addonIdOrRealId: addonIdOrRealIdOption,
16
17
  },
17
18
  args: [drainIdArg],
18
19
  async handler(options, drainId) {
19
- const { alias, app: appIdOrName } = options;
20
+ const { alias, appIdOrName, addonIdOrRealId } = options;
21
+ const { ownerId, resourceId } = await resolveDrainResource(alias, appIdOrName, addonIdOrRealId);
20
22
 
21
- const { ownerId, appId: applicationId } = await Application.resolveId(appIdOrName, alias);
22
-
23
- await deleteDrain({ ownerId, applicationId, drainId }).then(sendToApi);
23
+ await deleteDrain({ ownerId, resourceId, drainId }).then(sendToApi);
24
24
  Logger.printSuccess(`Drain ${styleText(['bold', 'green'], drainId)} has been successfully removed!`);
25
25
  },
26
26
  });
@@ -7,9 +7,6 @@ export const emailsOpenCommand = defineCommand({
7
7
  options: {},
8
8
  args: [],
9
9
  handler() {
10
- return openBrowser(
11
- '/users/me/emails',
12
- 'Opening the email addresses management page of the Console in your browser',
13
- );
10
+ return openBrowser('/users/me/emails', 'Opening the emails page in the browser…');
14
11
  },
15
12
  });
@@ -62,6 +62,7 @@ import { featuresEnableCommand } from './features/features.enable.command.js';
62
62
  import { featuresInfoCommand } from './features/features.info.command.js';
63
63
  import { featuresListCommand } from './features/features.list.command.js';
64
64
  import { helpCommand } from './help/help.command.js';
65
+ import { k8sActivityCommand } from './k8s/k8s.activity.command.js';
65
66
  import { k8sAddPersistentStorageCommand } from './k8s/k8s.add-persistent-storage.command.js';
66
67
  import { k8sCommand } from './k8s/k8s.command.js';
67
68
  import { k8sCreateCommand } from './k8s/k8s.create.command.js';
@@ -69,6 +70,17 @@ import { k8sDeleteCommand } from './k8s/k8s.delete.command.js';
69
70
  import { k8sGetKubeconfigCommand } from './k8s/k8s.get-kubeconfig.command.js';
70
71
  import { k8sGetCommand } from './k8s/k8s.get.command.js';
71
72
  import { k8sListCommand } from './k8s/k8s.list.command.js';
73
+ import { k8sNodeGroupCommand } from './k8s/k8s.nodegroups.command.js';
74
+ import { k8sNodeGroupCreateCommand } from './k8s/k8s.nodegroups.create.command.js';
75
+ import { k8sNodeGroupDeleteCommand } from './k8s/k8s.nodegroups.delete.command.js';
76
+ import { k8sNodeGroupGetCommand } from './k8s/k8s.nodegroups.get.command.js';
77
+ import { k8sNodeGroupListCommand } from './k8s/k8s.nodegroups.list.command.js';
78
+ import { k8sNodeGroupUpdateCommand } from './k8s/k8s.nodegroups.update.command.js';
79
+ import { k8sQuotaCommand } from './k8s/k8s.quota.command.js';
80
+ import { k8sUpdateCommand } from './k8s/k8s.update.command.js';
81
+ import { k8sVersionCheckCommand } from './k8s/k8s.version.check.command.js';
82
+ import { k8sVersionCommand } from './k8s/k8s.version.command.js';
83
+ import { k8sVersionUpdateCommand } from './k8s/k8s.version.update.command.js';
72
84
  import { keycloakCommand } from './keycloak/keycloak.command.js';
73
85
  import { keycloakDisableNgCommand } from './keycloak/keycloak.disable-ng.command.js';
74
86
  import { keycloakEnableNgCommand } from './keycloak/keycloak.enable-ng.command.js';
@@ -117,6 +129,13 @@ import { ngUnlinkCommand } from './ng/ng.unlink.command.js';
117
129
  import { notifyEmailAddCommand } from './notify-email/notify-email.add.command.js';
118
130
  import { notifyEmailCommand } from './notify-email/notify-email.command.js';
119
131
  import { notifyEmailRemoveCommand } from './notify-email/notify-email.remove.command.js';
132
+ import { oauthConsumersCommand } from './oauth-consumers/oauth-consumers.command.js';
133
+ import { oauthConsumersCreateCommand } from './oauth-consumers/oauth-consumers.create.command.js';
134
+ import { oauthConsumersDeleteCommand } from './oauth-consumers/oauth-consumers.delete.command.js';
135
+ import { oauthConsumersGetCommand } from './oauth-consumers/oauth-consumers.get.command.js';
136
+ import { oauthConsumersListCommand } from './oauth-consumers/oauth-consumers.list.command.js';
137
+ import { oauthConsumersOpenCommand } from './oauth-consumers/oauth-consumers.open.command.js';
138
+ import { oauthConsumersUpdateCommand } from './oauth-consumers/oauth-consumers.update.command.js';
120
139
  import { openCommand } from './open/open.command.js';
121
140
  import { otoroshiCommand } from './otoroshi/otoroshi.command.js';
122
141
  import { otoroshiDisableNgCommand } from './otoroshi/otoroshi.disable-ng.command.js';
@@ -125,6 +144,7 @@ import { otoroshiGetConfigCommand } from './otoroshi/otoroshi.get-config.command
125
144
  import { otoroshiGetCommand } from './otoroshi/otoroshi.get.command.js';
126
145
  import { otoroshiOpenCommand } from './otoroshi/otoroshi.open.command.js';
127
146
  import { otoroshiOpenLogsCommand } from './otoroshi/otoroshi.open.logs.command.js';
147
+ import { otoroshiOpenSwaggeruiCommand } from './otoroshi/otoroshi.open.swaggerui.command.js';
128
148
  import { otoroshiOpenWebuiCommand } from './otoroshi/otoroshi.open.webui.command.js';
129
149
  import { otoroshiRebuildCommand } from './otoroshi/otoroshi.rebuild.command.js';
130
150
  import { otoroshiRestartCommand } from './otoroshi/otoroshi.restart.command.js';
@@ -287,12 +307,32 @@ export const globalCommands = {
287
307
  k8s: [
288
308
  k8sCommand,
289
309
  {
310
+ activity: k8sActivityCommand,
290
311
  'add-persistent-storage': k8sAddPersistentStorageCommand,
291
312
  create: k8sCreateCommand,
292
313
  delete: k8sDeleteCommand,
293
314
  get: k8sGetCommand,
294
315
  'get-kubeconfig': k8sGetKubeconfigCommand,
295
316
  list: k8sListCommand,
317
+ nodegroups: [
318
+ k8sNodeGroupCommand,
319
+ {
320
+ create: k8sNodeGroupCreateCommand,
321
+ delete: k8sNodeGroupDeleteCommand,
322
+ get: k8sNodeGroupGetCommand,
323
+ list: k8sNodeGroupListCommand,
324
+ update: k8sNodeGroupUpdateCommand,
325
+ },
326
+ ],
327
+ quota: k8sQuotaCommand,
328
+ update: k8sUpdateCommand,
329
+ version: [
330
+ k8sVersionCommand,
331
+ {
332
+ check: k8sVersionCheckCommand,
333
+ update: k8sVersionUpdateCommand,
334
+ },
335
+ ],
296
336
  },
297
337
  ],
298
338
  keycloak: [
@@ -384,6 +424,17 @@ export const globalCommands = {
384
424
  unlink: ngUnlinkCommand,
385
425
  },
386
426
  ],
427
+ 'oauth-consumers': [
428
+ oauthConsumersCommand,
429
+ {
430
+ create: oauthConsumersCreateCommand,
431
+ delete: oauthConsumersDeleteCommand,
432
+ get: oauthConsumersGetCommand,
433
+ list: oauthConsumersListCommand,
434
+ open: oauthConsumersOpenCommand,
435
+ update: oauthConsumersUpdateCommand,
436
+ },
437
+ ],
387
438
  'notify-email': [
388
439
  notifyEmailCommand,
389
440
  {
@@ -403,6 +454,7 @@ export const globalCommands = {
403
454
  otoroshiOpenCommand,
404
455
  {
405
456
  logs: otoroshiOpenLogsCommand,
457
+ swaggerui: otoroshiOpenSwaggeruiCommand,
406
458
  webui: otoroshiOpenWebuiCommand,
407
459
  },
408
460
  ],
@@ -23,7 +23,7 @@ export const appIdOrNameOption = defineOption({
23
23
  export const logsFormatOption = defineOption({
24
24
  name: 'format',
25
25
  schema: z.enum(['human', 'json', 'json-stream']).default('human'),
26
- description: 'Output format (human, json, json-stream)',
26
+ description: 'Output format',
27
27
  aliases: ['F'],
28
28
  placeholder: 'format',
29
29
  });
@@ -44,7 +44,7 @@ export const afterOption = defineOption({
44
44
  placeholder: 'after',
45
45
  });
46
46
 
47
- export const addonIdOption = defineOption({
47
+ export const addonIdOrRealIdOption = defineOption({
48
48
  name: 'addon',
49
49
  schema: z.string().optional(),
50
50
  description: 'Add-on ID or real ID',
@@ -62,22 +62,22 @@ export const orgaIdOrNameOption = defineOption({
62
62
  export const humanJsonOutputFormatOption = defineOption({
63
63
  name: 'format',
64
64
  schema: z.enum(['human', 'json']).default('human'),
65
- description: 'Output format (human, json)',
65
+ description: 'Output format',
66
66
  aliases: ['F'],
67
67
  placeholder: 'format',
68
68
  });
69
69
 
70
- export const confirmAddonDeletionOption = defineOption({
70
+ export const skipConfirmationOption = defineOption({
71
71
  name: 'yes',
72
72
  schema: z.boolean().default(false),
73
- description: 'Skip confirmation and delete the add-on directly',
73
+ description: 'Skip confirmation prompts',
74
74
  aliases: ['y'],
75
75
  });
76
76
 
77
77
  export const envFormatOption = defineOption({
78
78
  name: 'format',
79
79
  schema: z.enum(['human', 'json', 'shell']).default('human'),
80
- description: 'Output format (human, json, shell)',
80
+ description: 'Output format',
81
81
  aliases: ['F'],
82
82
  placeholder: 'format',
83
83
  });
@@ -107,7 +107,7 @@ export const followDeployLogsOption = defineOption({
107
107
  export const exitOnDeployOption = defineOption({
108
108
  name: 'exit-on',
109
109
  schema: z.enum(['deploy-start', 'deploy-end', 'never']).default('deploy-end'),
110
- description: 'Step at which the logs streaming is ended, steps are: deploy-start, deploy-end, never',
110
+ description: 'Step at which the logs streaming is ended',
111
111
  aliases: ['e'],
112
112
  placeholder: 'step',
113
113
  });
@@ -3,7 +3,4 @@ import { defineCommand } from '../../lib/define-command.js';
3
3
  export const helpCommand = defineCommand({
4
4
  description: 'Display help about the Clever Cloud CLI',
5
5
  since: '0.1.0',
6
- options: {},
7
- args: [],
8
- handler: null,
9
6
  });
@@ -0,0 +1,53 @@
1
+ import { z } from 'zod';
2
+ import { defineCommand } from '../../lib/define-command.js';
3
+ import { defineOption } from '../../lib/define-option.js';
4
+ import { k8sListActivity } from '../../lib/k8s.js';
5
+ import { Logger } from '../../logger.js';
6
+ import { humanJsonOutputFormatOption, orgaIdOrNameOption } from '../global.options.js';
7
+ import { k8sIdOrNameArg } from './k8s.args.js';
8
+
9
+ export const k8sActivityCommand = defineCommand({
10
+ description: 'Show recent deployment events of a Kubernetes cluster',
11
+ since: '4.9.0',
12
+ options: {
13
+ org: orgaIdOrNameOption,
14
+ format: humanJsonOutputFormatOption,
15
+ limit: defineOption({
16
+ name: 'limit',
17
+ schema: z.coerce.number().int().min(1).max(1000).default(50),
18
+ description: 'Number of events to fetch (1 to 1000)',
19
+ placeholder: 'limit',
20
+ }),
21
+ },
22
+ args: [k8sIdOrNameArg],
23
+ async handler(options, clusterIdOrName) {
24
+ const { format, org: orgIdOrName, limit } = options;
25
+ const events = await k8sListActivity(orgIdOrName, clusterIdOrName, limit);
26
+
27
+ switch (format) {
28
+ case 'json':
29
+ Logger.printJson(events);
30
+ break;
31
+ case 'human':
32
+ default:
33
+ if (events.length === 0) {
34
+ Logger.println('🔎 No deployment event found');
35
+ return;
36
+ }
37
+ console.table(
38
+ events.map((e) => ({
39
+ Date: formatDate(e.createdAt),
40
+ Operation: e.operation,
41
+ Step: e.stepName ?? '-',
42
+ Status: e.status,
43
+ })),
44
+ );
45
+ break;
46
+ }
47
+ },
48
+ });
49
+
50
+ function formatDate(iso) {
51
+ if (iso == null) return '-';
52
+ return `${iso.slice(0, 19).replace('T', ' ')}Z`;
53
+ }
@@ -7,3 +7,9 @@ export const k8sIdOrNameArg = defineArgument({
7
7
  description: 'Kubernetes cluster ID or name',
8
8
  placeholder: 'cluster-id|cluster-name',
9
9
  });
10
+
11
+ export const k8sNodeGroupIdOrNameArg = defineArgument({
12
+ schema: z.string(),
13
+ description: 'Kubernetes node group ID or name',
14
+ placeholder: 'nodegroup-id|nodegroup-name',
15
+ });
@@ -5,8 +5,4 @@ export const k8sCommand = defineCommand({
5
5
  since: '4.3.0',
6
6
  isExperimental: true,
7
7
  featureFlag: 'k8s',
8
- options: {},
9
- args: [],
10
- // Parent command - no handler, only contains subcommands
11
- handler: null,
12
8
  });