clever-tools 4.8.0 → 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.
- package/package.json +1 -1
- package/src/clever-client/k8s.js +197 -0
- package/src/commands/addon/addon.docs.md +1 -1
- package/src/commands/global.commands.js +34 -0
- package/src/commands/global.options.js +1 -1
- package/src/commands/k8s/k8s.activity.command.js +53 -0
- package/src/commands/k8s/k8s.args.js +6 -0
- package/src/commands/k8s/k8s.create.command.js +87 -3
- package/src/commands/k8s/k8s.delete.command.js +13 -18
- package/src/commands/k8s/k8s.docs.md +264 -1
- package/src/commands/k8s/k8s.get.command.js +65 -4
- package/src/commands/k8s/k8s.nodegroups.command.js +7 -0
- package/src/commands/k8s/k8s.nodegroups.create.command.js +79 -0
- package/src/commands/k8s/k8s.nodegroups.delete.command.js +34 -0
- package/src/commands/k8s/k8s.nodegroups.get.command.js +66 -0
- package/src/commands/k8s/k8s.nodegroups.list.command.js +49 -0
- package/src/commands/k8s/k8s.nodegroups.update.command.js +86 -0
- package/src/commands/k8s/k8s.quota.command.js +77 -0
- package/src/commands/k8s/k8s.update.command.js +72 -0
- package/src/commands/k8s/k8s.version.check.command.js +18 -0
- package/src/commands/k8s/k8s.version.command.js +18 -0
- package/src/commands/k8s/k8s.version.update.command.js +18 -0
- package/src/commands/oauth-consumers/oauth-consumers.docs.md +1 -1
- package/src/commands/otoroshi/otoroshi.docs.md +14 -0
- package/src/commands/otoroshi/otoroshi.open.swaggerui.command.js +13 -0
- package/src/lib/k8s.js +411 -11
- package/src/lib/operator-commands.js +15 -1
- package/src/lib/prompts.js +6 -2
- package/src/parsers.js +10 -0
package/package.json
CHANGED
package/src/clever-client/k8s.js
CHANGED
|
@@ -16,6 +16,23 @@ export function createK8sCluster(params, body) {
|
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* PATCH /v4/kubernetes/organisations/{ownerId}/clusters/{clusterId}
|
|
21
|
+
* @param {Object} params
|
|
22
|
+
* @param {String} params.ownerId
|
|
23
|
+
* @param {String} params.clusterId
|
|
24
|
+
* @param {Object} body
|
|
25
|
+
*/
|
|
26
|
+
export function updateK8sCluster(params, body) {
|
|
27
|
+
return Promise.resolve({
|
|
28
|
+
method: 'PATCH',
|
|
29
|
+
url: `/v4/kubernetes/organisations/${params.ownerId}/clusters/${params.clusterId}`,
|
|
30
|
+
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
31
|
+
// no queryParams
|
|
32
|
+
body,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
19
36
|
/**
|
|
20
37
|
* DELETE /v4/kubernetes/organisations/{ownerId}/clusters/{clusterId}
|
|
21
38
|
* @param {Object} params
|
|
@@ -94,3 +111,183 @@ export function addK8sPersistentStorage(params) {
|
|
|
94
111
|
// no body
|
|
95
112
|
});
|
|
96
113
|
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* PATCH /v4/kubernetes/organisations/{ownerId}/clusters/{clusterId}/node-groups/{nodeGroupId}
|
|
117
|
+
* @param {Object} params
|
|
118
|
+
* @param {String} params.ownerId
|
|
119
|
+
* @param {String} params.clusterId
|
|
120
|
+
* @param {String} params.nodeGroupId
|
|
121
|
+
* @param {Object} body
|
|
122
|
+
*/
|
|
123
|
+
export function updateK8sNodeGroup(params, body) {
|
|
124
|
+
return Promise.resolve({
|
|
125
|
+
method: 'PATCH',
|
|
126
|
+
url: `/v4/kubernetes/organisations/${params.ownerId}/clusters/${params.clusterId}/node-groups/${params.nodeGroupId}`,
|
|
127
|
+
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
128
|
+
// no queryParams
|
|
129
|
+
body,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* DELETE /v4/kubernetes/organisations/{ownerId}/clusters/{clusterId}/node-groups/{nodeGroupId}
|
|
135
|
+
* @param {Object} params
|
|
136
|
+
* @param {String} params.ownerId
|
|
137
|
+
* @param {String} params.clusterId
|
|
138
|
+
* @param {String} params.nodeGroupId
|
|
139
|
+
*/
|
|
140
|
+
export function deleteK8sNodeGroup(params) {
|
|
141
|
+
return Promise.resolve({
|
|
142
|
+
method: 'delete',
|
|
143
|
+
url: `/v4/kubernetes/organisations/${params.ownerId}/clusters/${params.clusterId}/node-groups/${params.nodeGroupId}`,
|
|
144
|
+
headers: { Accept: 'application/json' },
|
|
145
|
+
// no queryParams
|
|
146
|
+
// no body
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* POST /v4/kubernetes/organisations/{ownerId}/clusters/{clusterId}/node-groups
|
|
152
|
+
* @param {Object} params
|
|
153
|
+
* @param {String} params.ownerId
|
|
154
|
+
* @param {String} params.clusterId
|
|
155
|
+
* @param {Object} body
|
|
156
|
+
*/
|
|
157
|
+
export function createK8sNodeGroup(params, body) {
|
|
158
|
+
return Promise.resolve({
|
|
159
|
+
method: 'post',
|
|
160
|
+
url: `/v4/kubernetes/organisations/${params.ownerId}/clusters/${params.clusterId}/node-groups`,
|
|
161
|
+
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
162
|
+
// no queryParams
|
|
163
|
+
body,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* GET /v4/kubernetes/organisations/{ownerId}/clusters/{clusterId}/node-groups
|
|
169
|
+
* @param {Object} params
|
|
170
|
+
* @param {String} params.ownerId
|
|
171
|
+
* @param {String} params.clusterId
|
|
172
|
+
*/
|
|
173
|
+
export function listK8sNodeGroups(params) {
|
|
174
|
+
return Promise.resolve({
|
|
175
|
+
method: 'get',
|
|
176
|
+
url: `/v4/kubernetes/organisations/${params.ownerId}/clusters/${params.clusterId}/node-groups`,
|
|
177
|
+
headers: { Accept: 'application/json' },
|
|
178
|
+
// no queryParams
|
|
179
|
+
// no body
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* GET /v4/kubernetes/organisations/{ownerId}/clusters/{clusterId}/node-groups/{nodeGroupId}
|
|
185
|
+
* @param {Object} params
|
|
186
|
+
* @param {String} params.ownerId
|
|
187
|
+
* @param {String} params.clusterId
|
|
188
|
+
* @param {String} params.nodeGroupId
|
|
189
|
+
*/
|
|
190
|
+
export function getK8sNodeGroup(params) {
|
|
191
|
+
return Promise.resolve({
|
|
192
|
+
method: 'get',
|
|
193
|
+
url: `/v4/kubernetes/organisations/${params.ownerId}/clusters/${params.clusterId}/node-groups/${params.nodeGroupId}`,
|
|
194
|
+
headers: { Accept: 'application/json' },
|
|
195
|
+
// no queryParams
|
|
196
|
+
// no body
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* GET /v4/kubernetes/organisations/{ownerId}/clusters/{clusterId}/deployment-events
|
|
202
|
+
* @param {Object} params
|
|
203
|
+
* @param {String} params.ownerId
|
|
204
|
+
* @param {String} params.clusterId
|
|
205
|
+
* @param {Object} [queryParams]
|
|
206
|
+
* @param {Number} [queryParams.limit]
|
|
207
|
+
*/
|
|
208
|
+
export function listK8sDeploymentEvents(params, queryParams = {}) {
|
|
209
|
+
return Promise.resolve({
|
|
210
|
+
method: 'get',
|
|
211
|
+
url: `/v4/kubernetes/organisations/${params.ownerId}/clusters/${params.clusterId}/deployment-events`,
|
|
212
|
+
headers: { Accept: 'application/json' },
|
|
213
|
+
queryParams,
|
|
214
|
+
// no body
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* GET /v4/kubernetes-product
|
|
220
|
+
*/
|
|
221
|
+
export function getK8sProduct() {
|
|
222
|
+
return Promise.resolve({
|
|
223
|
+
method: 'get',
|
|
224
|
+
url: `/v4/kubernetes-product`,
|
|
225
|
+
headers: { Accept: 'application/json' },
|
|
226
|
+
// no queryParams
|
|
227
|
+
// no body
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* GET /v4/kubernetes/organisations/{ownerId}/clusters/{clusterId}/version/check
|
|
233
|
+
* @param {Object} params
|
|
234
|
+
* @param {String} params.ownerId
|
|
235
|
+
* @param {String} params.clusterId
|
|
236
|
+
*/
|
|
237
|
+
export function getK8sVersionCheck(params) {
|
|
238
|
+
return Promise.resolve({
|
|
239
|
+
method: 'get',
|
|
240
|
+
url: `/v4/kubernetes/organisations/${params.ownerId}/clusters/${params.clusterId}/version/check`,
|
|
241
|
+
headers: { Accept: 'application/json' },
|
|
242
|
+
// no queryParams
|
|
243
|
+
// no body
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* POST /v4/kubernetes/organisations/{ownerId}/clusters/{clusterId}/version/update
|
|
249
|
+
* @param {Object} params
|
|
250
|
+
* @param {String} params.ownerId
|
|
251
|
+
* @param {String} params.clusterId
|
|
252
|
+
* @param {Object} body
|
|
253
|
+
* @param {String} body.targetVersion
|
|
254
|
+
*/
|
|
255
|
+
export function updateK8sVersion(params, body) {
|
|
256
|
+
return Promise.resolve({
|
|
257
|
+
method: 'post',
|
|
258
|
+
url: `/v4/kubernetes/organisations/${params.ownerId}/clusters/${params.clusterId}/version/update`,
|
|
259
|
+
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
260
|
+
// no queryParams
|
|
261
|
+
body,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* GET /v4/kubernetes/organisations/{ownerId}/quota
|
|
267
|
+
* @param {Object} params
|
|
268
|
+
* @param {String} params.ownerId
|
|
269
|
+
*/
|
|
270
|
+
export function getK8sQuota(params) {
|
|
271
|
+
return Promise.resolve({
|
|
272
|
+
method: 'get',
|
|
273
|
+
url: `/v4/kubernetes/organisations/${params.ownerId}/quota`,
|
|
274
|
+
headers: { Accept: 'application/json' },
|
|
275
|
+
// no queryParams
|
|
276
|
+
// no body
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* GET /v4/kubernetes/organisations/{ownerId}/usage
|
|
282
|
+
* @param {Object} params
|
|
283
|
+
* @param {String} params.ownerId
|
|
284
|
+
*/
|
|
285
|
+
export function listK8sUsage(params) {
|
|
286
|
+
return Promise.resolve({
|
|
287
|
+
method: 'get',
|
|
288
|
+
url: `/v4/kubernetes/organisations/${params.ownerId}/usage`,
|
|
289
|
+
headers: { Accept: 'application/json' },
|
|
290
|
+
// no queryParams
|
|
291
|
+
// no body
|
|
292
|
+
});
|
|
293
|
+
}
|
|
@@ -62,7 +62,7 @@ clever addon delete <addon-id|addon-name> [options]
|
|
|
62
62
|
|Name|Description|
|
|
63
63
|
|---|---|
|
|
64
64
|
|`-o`, `--org`, `--owner` `<org-id\|org-name>`|Organisation to target by its ID (or name, if unambiguous)|
|
|
65
|
-
|`-y`, `--yes`|Skip confirmation
|
|
65
|
+
|`-y`, `--yes`|Skip confirmation prompts|
|
|
66
66
|
|
|
67
67
|
## ➡️ `clever addon env` <kbd>Since 2.11.0</kbd>
|
|
68
68
|
|
|
@@ -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';
|
|
@@ -132,6 +144,7 @@ import { otoroshiGetConfigCommand } from './otoroshi/otoroshi.get-config.command
|
|
|
132
144
|
import { otoroshiGetCommand } from './otoroshi/otoroshi.get.command.js';
|
|
133
145
|
import { otoroshiOpenCommand } from './otoroshi/otoroshi.open.command.js';
|
|
134
146
|
import { otoroshiOpenLogsCommand } from './otoroshi/otoroshi.open.logs.command.js';
|
|
147
|
+
import { otoroshiOpenSwaggeruiCommand } from './otoroshi/otoroshi.open.swaggerui.command.js';
|
|
135
148
|
import { otoroshiOpenWebuiCommand } from './otoroshi/otoroshi.open.webui.command.js';
|
|
136
149
|
import { otoroshiRebuildCommand } from './otoroshi/otoroshi.rebuild.command.js';
|
|
137
150
|
import { otoroshiRestartCommand } from './otoroshi/otoroshi.restart.command.js';
|
|
@@ -294,12 +307,32 @@ export const globalCommands = {
|
|
|
294
307
|
k8s: [
|
|
295
308
|
k8sCommand,
|
|
296
309
|
{
|
|
310
|
+
activity: k8sActivityCommand,
|
|
297
311
|
'add-persistent-storage': k8sAddPersistentStorageCommand,
|
|
298
312
|
create: k8sCreateCommand,
|
|
299
313
|
delete: k8sDeleteCommand,
|
|
300
314
|
get: k8sGetCommand,
|
|
301
315
|
'get-kubeconfig': k8sGetKubeconfigCommand,
|
|
302
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
|
+
],
|
|
303
336
|
},
|
|
304
337
|
],
|
|
305
338
|
keycloak: [
|
|
@@ -421,6 +454,7 @@ export const globalCommands = {
|
|
|
421
454
|
otoroshiOpenCommand,
|
|
422
455
|
{
|
|
423
456
|
logs: otoroshiOpenLogsCommand,
|
|
457
|
+
swaggerui: otoroshiOpenSwaggeruiCommand,
|
|
424
458
|
webui: otoroshiOpenWebuiCommand,
|
|
425
459
|
},
|
|
426
460
|
],
|
|
@@ -70,7 +70,7 @@ export const humanJsonOutputFormatOption = defineOption({
|
|
|
70
70
|
export const skipConfirmationOption = defineOption({
|
|
71
71
|
name: 'yes',
|
|
72
72
|
schema: z.boolean().default(false),
|
|
73
|
-
description: 'Skip confirmation
|
|
73
|
+
description: 'Skip confirmation prompts',
|
|
74
74
|
aliases: ['y'],
|
|
75
75
|
});
|
|
76
76
|
|
|
@@ -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
|
+
});
|
|
@@ -3,10 +3,11 @@ import { typewriterLogo } from '../../lib/ascii.js';
|
|
|
3
3
|
import { defineArgument } from '../../lib/define-argument.js';
|
|
4
4
|
import { defineCommand } from '../../lib/define-command.js';
|
|
5
5
|
import { defineOption } from '../../lib/define-option.js';
|
|
6
|
-
import { getK8sCluster, k8sCreate } from '../../lib/k8s.js';
|
|
6
|
+
import { getK8sCluster, k8sCreate, k8sGetProduct } from '../../lib/k8s.js';
|
|
7
7
|
import { styleText } from '../../lib/style-text.js';
|
|
8
8
|
import { Logger } from '../../logger.js';
|
|
9
|
-
import {
|
|
9
|
+
import { flavorCount, tags } from '../../parsers.js';
|
|
10
|
+
import { orgaIdOrNameOption, skipConfirmationOption } from '../global.options.js';
|
|
10
11
|
|
|
11
12
|
const DEPLOY_POLL_DELAY_MS = 10000;
|
|
12
13
|
|
|
@@ -14,6 +15,78 @@ export const k8sCreateCommand = defineCommand({
|
|
|
14
15
|
description: 'Create a Kubernetes cluster',
|
|
15
16
|
since: '4.3.0',
|
|
16
17
|
options: {
|
|
18
|
+
clusterVersion: defineOption({
|
|
19
|
+
name: 'cluster-version',
|
|
20
|
+
schema: z.string().optional(),
|
|
21
|
+
description: 'Kubernetes version to deploy (e.g.: 1.36)',
|
|
22
|
+
placeholder: 'cluster-version',
|
|
23
|
+
complete: async () => {
|
|
24
|
+
const product = await k8sGetProduct();
|
|
25
|
+
return product.versions?.available ?? [];
|
|
26
|
+
},
|
|
27
|
+
}),
|
|
28
|
+
description: defineOption({
|
|
29
|
+
name: 'description',
|
|
30
|
+
schema: z.string().max(4096).optional(),
|
|
31
|
+
description: 'Free-form cluster description',
|
|
32
|
+
placeholder: 'description',
|
|
33
|
+
}),
|
|
34
|
+
tag: defineOption({
|
|
35
|
+
name: 'tag',
|
|
36
|
+
schema: z.string().transform(tags).optional(),
|
|
37
|
+
description: 'Semantic tags (comma-separated, e.g.: env:prod,team:platform)',
|
|
38
|
+
placeholder: 'tag[,tag...]',
|
|
39
|
+
}),
|
|
40
|
+
autoscaling: defineOption({
|
|
41
|
+
name: 'autoscaling',
|
|
42
|
+
schema: z.boolean().default(false),
|
|
43
|
+
description: 'Enable the cluster autoscaler',
|
|
44
|
+
}),
|
|
45
|
+
persistentStorage: defineOption({
|
|
46
|
+
name: 'persistent-storage',
|
|
47
|
+
schema: z.boolean().default(false),
|
|
48
|
+
description: 'Enable persistent storage (Ceph CSI)',
|
|
49
|
+
}),
|
|
50
|
+
topology: defineOption({
|
|
51
|
+
name: 'topology',
|
|
52
|
+
schema: z
|
|
53
|
+
.string()
|
|
54
|
+
.transform((v) => v.toUpperCase())
|
|
55
|
+
.optional(),
|
|
56
|
+
description: 'Cluster topology (must be set with --flavor and --replication-factor)',
|
|
57
|
+
placeholder: 'topology',
|
|
58
|
+
complete: async () => {
|
|
59
|
+
const product = await k8sGetProduct();
|
|
60
|
+
return (product.topologies ?? []).map((t) => t.topology);
|
|
61
|
+
},
|
|
62
|
+
}),
|
|
63
|
+
flavor: defineOption({
|
|
64
|
+
name: 'flavor',
|
|
65
|
+
schema: z
|
|
66
|
+
.string()
|
|
67
|
+
.transform((v) => v.toUpperCase())
|
|
68
|
+
.optional(),
|
|
69
|
+
description: 'Control plane flavor',
|
|
70
|
+
placeholder: 'flavor',
|
|
71
|
+
complete: async () => {
|
|
72
|
+
const product = await k8sGetProduct();
|
|
73
|
+
const flavors = new Set((product.topologies ?? []).flatMap((t) => t.availableFlavors ?? []));
|
|
74
|
+
return [...flavors];
|
|
75
|
+
},
|
|
76
|
+
}),
|
|
77
|
+
replicationFactor: defineOption({
|
|
78
|
+
name: 'replication-factor',
|
|
79
|
+
schema: z.coerce.number().int().optional(),
|
|
80
|
+
description: 'Control plane replication factor',
|
|
81
|
+
placeholder: 'replication-factor',
|
|
82
|
+
}),
|
|
83
|
+
nodeGroup: defineOption({
|
|
84
|
+
name: 'nodegroup',
|
|
85
|
+
schema: z.string().transform(flavorCount).optional(),
|
|
86
|
+
description: 'Initial node group (format: <flavor>:<count>, e.g.: XS:3)',
|
|
87
|
+
placeholder: 'flavor:count',
|
|
88
|
+
}),
|
|
89
|
+
yes: skipConfirmationOption,
|
|
17
90
|
watch: defineOption({
|
|
18
91
|
name: 'watch',
|
|
19
92
|
schema: z.boolean().default(false),
|
|
@@ -34,7 +107,18 @@ export const k8sCreateCommand = defineCommand({
|
|
|
34
107
|
const orgIdOrName = options.org;
|
|
35
108
|
|
|
36
109
|
try {
|
|
37
|
-
const cluster = await k8sCreate(clusterName, orgIdOrName
|
|
110
|
+
const cluster = await k8sCreate(clusterName, orgIdOrName, {
|
|
111
|
+
version: options.clusterVersion,
|
|
112
|
+
description: options.description,
|
|
113
|
+
tags: options.tag,
|
|
114
|
+
autoscaling: options.autoscaling,
|
|
115
|
+
persistentStorage: options.persistentStorage,
|
|
116
|
+
topology: options.topology,
|
|
117
|
+
flavor: options.flavor,
|
|
118
|
+
replicationFactor: options.replicationFactor,
|
|
119
|
+
nodeGroup: options.nodeGroup,
|
|
120
|
+
yes: options.yes,
|
|
121
|
+
});
|
|
38
122
|
|
|
39
123
|
if (options.watch) {
|
|
40
124
|
await typewriterLogo();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineCommand } from '../../lib/define-command.js';
|
|
2
2
|
import { k8sDelete } from '../../lib/k8s.js';
|
|
3
|
-
import {
|
|
3
|
+
import { ask } from '../../lib/prompts.js';
|
|
4
4
|
import { styleText } from '../../lib/style-text.js';
|
|
5
5
|
import { Logger } from '../../logger.js';
|
|
6
6
|
import { orgaIdOrNameOption, skipConfirmationOption } from '../global.options.js';
|
|
@@ -15,26 +15,21 @@ export const k8sDeleteCommand = defineCommand({
|
|
|
15
15
|
},
|
|
16
16
|
args: [k8sIdOrNameArg],
|
|
17
17
|
async handler(options, clusterIdOrName) {
|
|
18
|
-
const { org: orgIdOrName, yes
|
|
18
|
+
const { org: orgIdOrName, yes } = options;
|
|
19
|
+
const display = clusterIdOrName.addon_name || clusterIdOrName.operator_id;
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
proceedDeletion = await confirm(
|
|
25
|
-
`Are you sure you want to delete the Kubernetes cluster ${styleText(
|
|
26
|
-
'blue',
|
|
27
|
-
clusterIdOrName.addon_name || clusterIdOrName.operator_id,
|
|
28
|
-
)}?`,
|
|
29
|
-
'Kubernetes cluster deletion cancelled.',
|
|
21
|
+
if (!yes) {
|
|
22
|
+
const proceed = await ask(
|
|
23
|
+
`Are you sure you want to delete the Kubernetes cluster ${styleText('blue', display)}?`,
|
|
24
|
+
false,
|
|
30
25
|
);
|
|
26
|
+
if (!proceed) {
|
|
27
|
+
Logger.println('Kubernetes cluster deletion cancelled');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
Logger.printSuccess(
|
|
36
|
-
`Kubernetes cluster ${styleText('green', clusterIdOrName.addon_name || clusterIdOrName.operator_id)} successfully deleted`,
|
|
37
|
-
);
|
|
38
|
-
}
|
|
32
|
+
await k8sDelete(orgIdOrName, clusterIdOrName);
|
|
33
|
+
Logger.printSuccess(`Kubernetes cluster ${styleText('green', display)} successfully deleted`);
|
|
39
34
|
},
|
|
40
35
|
});
|