@kumori/aurora-backend-handler 1.0.49 → 1.0.50
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/api/account-api-service.ts +0 -6
- package/api/service-api-service.ts +210 -217
- package/api/user-api-service.ts +233 -203
- package/helpers/revision-helper.ts +270 -318
- package/helpers/service-helper.ts +189 -80
- package/package.json +2 -2
- package/websocket-manager.ts +12 -5
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
Usage,
|
|
9
9
|
} from "@kumori/aurora-interfaces";
|
|
10
10
|
import { convertToGigabytes, getTimestamp } from "../utils/utils";
|
|
11
|
-
import { Revision } from "@kumori/aurora-interfaces/interfaces/revision-interface";
|
|
12
11
|
|
|
13
12
|
interface Role {
|
|
14
13
|
name: string;
|
|
@@ -32,6 +31,21 @@ interface Role {
|
|
|
32
31
|
hsize?: number;
|
|
33
32
|
}
|
|
34
33
|
|
|
34
|
+
interface Revision {
|
|
35
|
+
service: string;
|
|
36
|
+
revision: string;
|
|
37
|
+
usage: Usage;
|
|
38
|
+
status: {
|
|
39
|
+
code: string;
|
|
40
|
+
message: string;
|
|
41
|
+
timestamp: string;
|
|
42
|
+
args: string[];
|
|
43
|
+
};
|
|
44
|
+
errorCode?: string;
|
|
45
|
+
errorMsg?: string;
|
|
46
|
+
createdAt?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
35
49
|
interface HandleRevisionEventParams {
|
|
36
50
|
entityId: string;
|
|
37
51
|
eventData: any;
|
|
@@ -60,6 +74,9 @@ interface HandleRevisionEventResult {
|
|
|
60
74
|
|
|
61
75
|
const MAX_HISTORY = 100;
|
|
62
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Process role and instance data from revision event
|
|
79
|
+
*/
|
|
63
80
|
const processRolesAndInstances = (
|
|
64
81
|
eventData: any,
|
|
65
82
|
serviceId: string,
|
|
@@ -138,7 +155,7 @@ const processRolesAndInstances = (
|
|
|
138
155
|
cost: 0,
|
|
139
156
|
},
|
|
140
157
|
logs: [],
|
|
141
|
-
containers,
|
|
158
|
+
containers: containers,
|
|
142
159
|
};
|
|
143
160
|
|
|
144
161
|
roleInstances.push(instance);
|
|
@@ -159,15 +176,19 @@ const processRolesAndInstances = (
|
|
|
159
176
|
return { roles, instances, usedCpu, usedMemory };
|
|
160
177
|
};
|
|
161
178
|
|
|
179
|
+
/**
|
|
180
|
+
* Create a new revision object from event data
|
|
181
|
+
*/
|
|
162
182
|
const createRevision = (
|
|
163
183
|
entityId: string,
|
|
184
|
+
parentParts: { [entity: string]: string },
|
|
164
185
|
eventData: any,
|
|
165
186
|
usedCpu: number,
|
|
166
187
|
usedMemory: number,
|
|
167
188
|
): Revision => {
|
|
168
189
|
return {
|
|
169
|
-
|
|
170
|
-
|
|
190
|
+
service: parentParts.service,
|
|
191
|
+
revision: entityId,
|
|
171
192
|
usage: {
|
|
172
193
|
current: {
|
|
173
194
|
cpu: usedCpu,
|
|
@@ -178,8 +199,14 @@ const createRevision = (
|
|
|
178
199
|
persistentStorage: 0,
|
|
179
200
|
},
|
|
180
201
|
limit: {
|
|
181
|
-
cpu: {
|
|
182
|
-
|
|
202
|
+
cpu: {
|
|
203
|
+
max: eventData.spec.intensives?.vcpu / 1000 || 0,
|
|
204
|
+
min: 0,
|
|
205
|
+
},
|
|
206
|
+
memory: {
|
|
207
|
+
max: eventData.spec.intensives?.ram / 1000 || 0,
|
|
208
|
+
min: 0,
|
|
209
|
+
},
|
|
183
210
|
storage: {
|
|
184
211
|
max: eventData.spec.intensives?.shared_disk / 1000 || 0,
|
|
185
212
|
min: 0,
|
|
@@ -200,13 +227,22 @@ const createRevision = (
|
|
|
200
227
|
cost: 0,
|
|
201
228
|
},
|
|
202
229
|
status: eventData.status.state,
|
|
203
|
-
errorCode:
|
|
204
|
-
|
|
230
|
+
errorCode:
|
|
231
|
+
eventData.status && eventData.status.error
|
|
232
|
+
? eventData.status.error.code
|
|
233
|
+
: "",
|
|
234
|
+
errorMsg:
|
|
235
|
+
eventData.status && eventData.status.error
|
|
236
|
+
? eventData.status.error.message
|
|
237
|
+
: "",
|
|
205
238
|
createdAt:
|
|
206
239
|
(eventData.status && eventData.status.runtime?.status?.createdAt) || "",
|
|
207
240
|
};
|
|
208
241
|
};
|
|
209
242
|
|
|
243
|
+
/**
|
|
244
|
+
* Update service with new revision data
|
|
245
|
+
*/
|
|
210
246
|
const updateServiceWithRevision = (
|
|
211
247
|
existingService: Service,
|
|
212
248
|
entityId: string,
|
|
@@ -215,19 +251,27 @@ const updateServiceWithRevision = (
|
|
|
215
251
|
roles: Role[],
|
|
216
252
|
): { updatedService: Service; deploymentErrorEvent: Service | null } => {
|
|
217
253
|
const existingRevisionIndex = existingService.revisions.findIndex(
|
|
218
|
-
(rev) => rev
|
|
254
|
+
(rev) => rev === entityId,
|
|
219
255
|
);
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
256
|
+
const shouldIncludeInList =
|
|
257
|
+
newRevision.errorCode !== "COMPUTE_ERROR" &&
|
|
258
|
+
eventData.status?.error?.code !== "COMPUTE_ERROR";
|
|
259
|
+
|
|
260
|
+
let updatedRevisions;
|
|
261
|
+
if (shouldIncludeInList) {
|
|
262
|
+
updatedRevisions =
|
|
263
|
+
existingRevisionIndex === -1
|
|
264
|
+
? [...existingService.revisions, entityId]
|
|
265
|
+
: existingService.revisions;
|
|
266
|
+
} else {
|
|
267
|
+
updatedRevisions = existingService.revisions.filter(
|
|
268
|
+
(rev) => rev !== entityId,
|
|
269
|
+
);
|
|
270
|
+
}
|
|
226
271
|
|
|
227
272
|
const updatedService: Service = {
|
|
228
273
|
...existingService,
|
|
229
274
|
revisions: updatedRevisions,
|
|
230
|
-
currentRevision: entityId,
|
|
231
275
|
role: roles.length > 0 ? roles : existingService.role,
|
|
232
276
|
usage: newRevision.usage,
|
|
233
277
|
startedAt: newRevision.createdAt || existingService.startedAt,
|
|
@@ -241,6 +285,7 @@ const updateServiceWithRevision = (
|
|
|
241
285
|
|
|
242
286
|
if (incomingTs > currentTs) {
|
|
243
287
|
updatedService.status = incomingStatus;
|
|
288
|
+
|
|
244
289
|
if (eventData.status.error) {
|
|
245
290
|
updatedService.error = {
|
|
246
291
|
code: eventData.status.error.code,
|
|
@@ -254,6 +299,7 @@ const updateServiceWithRevision = (
|
|
|
254
299
|
} else if (eventData.status.error) {
|
|
255
300
|
const incomingErrorTs = getTimestamp(eventData.status.error.timestamp);
|
|
256
301
|
const currentErrorTs = getTimestamp(existingService.error?.timestamp);
|
|
302
|
+
|
|
257
303
|
if (incomingErrorTs > currentErrorTs) {
|
|
258
304
|
updatedService.error = {
|
|
259
305
|
code: eventData.status.error.code,
|
|
@@ -267,6 +313,9 @@ const updateServiceWithRevision = (
|
|
|
267
313
|
return { updatedService, deploymentErrorEvent };
|
|
268
314
|
};
|
|
269
315
|
|
|
316
|
+
/**
|
|
317
|
+
* Update environment consumption history
|
|
318
|
+
*/
|
|
270
319
|
const updateEnvironmentConsumption = (
|
|
271
320
|
environment: Environment,
|
|
272
321
|
servicesMap: Map<string, Service>,
|
|
@@ -287,24 +336,31 @@ const updateEnvironmentConsumption = (
|
|
|
287
336
|
}
|
|
288
337
|
});
|
|
289
338
|
|
|
290
|
-
if (!environment.usage.current.cpuConsuption)
|
|
339
|
+
if (!environment.usage.current.cpuConsuption) {
|
|
291
340
|
environment.usage.current.cpuConsuption = [];
|
|
292
|
-
|
|
341
|
+
}
|
|
342
|
+
if (!environment.usage.current.memoryConsuption) {
|
|
293
343
|
environment.usage.current.memoryConsuption = [];
|
|
344
|
+
}
|
|
294
345
|
|
|
295
346
|
environment.usage.current.cpuConsuption.push(totalEnvCpu);
|
|
296
347
|
environment.usage.current.memoryConsuption.push(totalEnvMemory);
|
|
297
348
|
|
|
298
|
-
if (environment.usage.current.cpuConsuption.length > MAX_HISTORY)
|
|
349
|
+
if (environment.usage.current.cpuConsuption.length > MAX_HISTORY) {
|
|
299
350
|
environment.usage.current.cpuConsuption =
|
|
300
351
|
environment.usage.current.cpuConsuption.slice(-MAX_HISTORY);
|
|
301
|
-
|
|
352
|
+
}
|
|
353
|
+
if (environment.usage.current.memoryConsuption.length > MAX_HISTORY) {
|
|
302
354
|
environment.usage.current.memoryConsuption =
|
|
303
355
|
environment.usage.current.memoryConsuption.slice(-MAX_HISTORY);
|
|
356
|
+
}
|
|
304
357
|
|
|
305
358
|
return environment;
|
|
306
359
|
};
|
|
307
360
|
|
|
361
|
+
/**
|
|
362
|
+
* Update account consumption history
|
|
363
|
+
*/
|
|
308
364
|
const updateAccountConsumption = (
|
|
309
365
|
account: Account,
|
|
310
366
|
servicesMap: Map<string, Service>,
|
|
@@ -325,24 +381,31 @@ const updateAccountConsumption = (
|
|
|
325
381
|
}
|
|
326
382
|
});
|
|
327
383
|
|
|
328
|
-
if (!account.usage.current.cpuConsuption)
|
|
384
|
+
if (!account.usage.current.cpuConsuption) {
|
|
329
385
|
account.usage.current.cpuConsuption = [];
|
|
330
|
-
|
|
386
|
+
}
|
|
387
|
+
if (!account.usage.current.memoryConsuption) {
|
|
331
388
|
account.usage.current.memoryConsuption = [];
|
|
389
|
+
}
|
|
332
390
|
|
|
333
391
|
account.usage.current.cpuConsuption.push(totalAccountCpu);
|
|
334
392
|
account.usage.current.memoryConsuption.push(totalAccountMemory);
|
|
335
393
|
|
|
336
|
-
if (account.usage.current.cpuConsuption.length > MAX_HISTORY)
|
|
394
|
+
if (account.usage.current.cpuConsuption.length > MAX_HISTORY) {
|
|
337
395
|
account.usage.current.cpuConsuption =
|
|
338
396
|
account.usage.current.cpuConsuption.slice(-MAX_HISTORY);
|
|
339
|
-
|
|
397
|
+
}
|
|
398
|
+
if (account.usage.current.memoryConsuption.length > MAX_HISTORY) {
|
|
340
399
|
account.usage.current.memoryConsuption =
|
|
341
400
|
account.usage.current.memoryConsuption.slice(-MAX_HISTORY);
|
|
401
|
+
}
|
|
342
402
|
|
|
343
403
|
return account;
|
|
344
404
|
};
|
|
345
|
-
|
|
405
|
+
/**
|
|
406
|
+
* Handles the "revision" event from WebSocket messages
|
|
407
|
+
* Processes revision data, updates services, environments, and accounts
|
|
408
|
+
*/
|
|
346
409
|
export const handleRevisionEvent = ({
|
|
347
410
|
entityId,
|
|
348
411
|
eventData,
|
|
@@ -360,15 +423,13 @@ export const handleRevisionEvent = ({
|
|
|
360
423
|
serviceId,
|
|
361
424
|
roleMap,
|
|
362
425
|
);
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
}
|
|
371
|
-
|
|
426
|
+
const newRevision = createRevision(
|
|
427
|
+
entityId,
|
|
428
|
+
parentParts,
|
|
429
|
+
eventData,
|
|
430
|
+
usedCpu,
|
|
431
|
+
usedMemory,
|
|
432
|
+
);
|
|
372
433
|
let updatedService: Service | null = null;
|
|
373
434
|
let updatedEnvironment: Environment | null = null;
|
|
374
435
|
let updatedAccount: Account | null = null;
|
|
@@ -389,9 +450,9 @@ export const handleRevisionEvent = ({
|
|
|
389
450
|
newRevision,
|
|
390
451
|
roles,
|
|
391
452
|
);
|
|
453
|
+
|
|
392
454
|
updatedService = serviceUpdateResult.updatedService;
|
|
393
455
|
serviceDeploymentErrorEvent = serviceUpdateResult.deploymentErrorEvent;
|
|
394
|
-
|
|
395
456
|
const serviceEnvironmentId = updatedService.environment;
|
|
396
457
|
if (serviceEnvironmentId) {
|
|
397
458
|
const environment = environmentsMap.get(serviceEnvironmentId);
|
|
@@ -400,6 +461,7 @@ export const handleRevisionEvent = ({
|
|
|
400
461
|
tempServicesMap.set(serviceId, updatedService);
|
|
401
462
|
const tempRevisionsMap = new Map(revisionsMap);
|
|
402
463
|
tempRevisionsMap.set(revisionKey, newRevision);
|
|
464
|
+
|
|
403
465
|
updatedEnvironment = updateEnvironmentConsumption(
|
|
404
466
|
{ ...environment },
|
|
405
467
|
tempServicesMap,
|
|
@@ -408,15 +470,16 @@ export const handleRevisionEvent = ({
|
|
|
408
470
|
);
|
|
409
471
|
}
|
|
410
472
|
}
|
|
411
|
-
|
|
412
473
|
const serviceAccountId = updatedService.account;
|
|
413
474
|
if (serviceAccountId) {
|
|
414
475
|
const account = accountsMap.get(serviceAccountId);
|
|
415
476
|
if (account) {
|
|
416
477
|
const tempServicesMap = new Map(servicesMap);
|
|
417
478
|
tempServicesMap.set(serviceId, updatedService);
|
|
479
|
+
|
|
418
480
|
const tempRevisionsMap = new Map(revisionsMap);
|
|
419
481
|
tempRevisionsMap.set(revisionKey, newRevision);
|
|
482
|
+
|
|
420
483
|
updatedAccount = updateAccountConsumption(
|
|
421
484
|
{ ...account },
|
|
422
485
|
tempServicesMap,
|
|
@@ -428,9 +491,11 @@ export const handleRevisionEvent = ({
|
|
|
428
491
|
} else if (eventData.status && eventData.status.error) {
|
|
429
492
|
newRevision.errorCode = eventData.status.error.code;
|
|
430
493
|
newRevision.errorMsg = eventData.status.error.message;
|
|
431
|
-
pendingRevisionError = {
|
|
494
|
+
pendingRevisionError = {
|
|
495
|
+
service: serviceId,
|
|
496
|
+
revision: newRevision,
|
|
497
|
+
};
|
|
432
498
|
}
|
|
433
|
-
|
|
434
499
|
if (
|
|
435
500
|
!eventData.meta.deleted &&
|
|
436
501
|
eventData.status &&
|
|
@@ -458,276 +523,45 @@ export const handleRevisionEvent = ({
|
|
|
458
523
|
serviceDeploymentErrorEvent,
|
|
459
524
|
};
|
|
460
525
|
};
|
|
461
|
-
|
|
462
|
-
const collectNamedTypes = (schema: any): string[] => {
|
|
463
|
-
if (!schema || typeof schema !== "object") return [];
|
|
464
|
-
const names: string[] = [];
|
|
465
|
-
if (schema.$kdsl?.const?.NamedType?.Name)
|
|
466
|
-
names.push(schema.$kdsl.const.NamedType.Name as string);
|
|
467
|
-
if (Array.isArray(schema.oneOf)) {
|
|
468
|
-
for (const branch of schema.oneOf) names.push(...collectNamedTypes(branch));
|
|
469
|
-
}
|
|
470
|
-
return names;
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
const namedTypeToResourceKind = (
|
|
474
|
-
namedTypes: string[],
|
|
475
|
-
): { type: string; kind?: string } | null => {
|
|
476
|
-
for (const name of namedTypes) {
|
|
477
|
-
switch (name) {
|
|
478
|
-
case "Secret":
|
|
479
|
-
return { type: "secret" };
|
|
480
|
-
case "Domain":
|
|
481
|
-
return { type: "domain" };
|
|
482
|
-
case "Port":
|
|
483
|
-
return { type: "port" };
|
|
484
|
-
case "Certificate":
|
|
485
|
-
return { type: "certificate" };
|
|
486
|
-
case "CA":
|
|
487
|
-
return { type: "ca" };
|
|
488
|
-
case "Volatile":
|
|
489
|
-
case "Ephemeral":
|
|
490
|
-
return { type: "volume", kind: "volatile" };
|
|
491
|
-
case "NonReplicated":
|
|
492
|
-
return { type: "volume", kind: "nonReplicated" };
|
|
493
|
-
case "Persisted":
|
|
494
|
-
case "Persistent":
|
|
495
|
-
return { type: "volume", kind: "persistent" };
|
|
496
|
-
case "Registered":
|
|
497
|
-
return { type: "volume" };
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
return null;
|
|
501
|
-
};
|
|
502
|
-
|
|
503
|
-
export const extractStructuredSchema = (
|
|
504
|
-
revisionData: any,
|
|
505
|
-
):
|
|
506
|
-
| {
|
|
507
|
-
parameters: {
|
|
508
|
-
name: string;
|
|
509
|
-
type: string;
|
|
510
|
-
required: boolean;
|
|
511
|
-
defaultValue?: any;
|
|
512
|
-
}[];
|
|
513
|
-
resources: {
|
|
514
|
-
name: string;
|
|
515
|
-
type: string;
|
|
516
|
-
kind?: string;
|
|
517
|
-
required: boolean;
|
|
518
|
-
}[];
|
|
519
|
-
}
|
|
520
|
-
| {} => {
|
|
521
|
-
const configSchema = revisionData?.configSchema;
|
|
522
|
-
if (!configSchema) return {};
|
|
523
|
-
|
|
524
|
-
const deploymentName = revisionData?.solution?.top;
|
|
525
|
-
const deployment = deploymentName
|
|
526
|
-
? revisionData?.solution?.deployments?.[deploymentName]
|
|
527
|
-
: Object.values(revisionData?.solution?.deployments ?? {})[0];
|
|
528
|
-
|
|
529
|
-
const parameterValues: Record<string, any> =
|
|
530
|
-
(deployment as any)?.config?.parameter ?? {};
|
|
531
|
-
const configResourceValues: Record<string, any> =
|
|
532
|
-
(deployment as any)?.config?.resource ?? {};
|
|
533
|
-
|
|
534
|
-
const requiredParams: string[] =
|
|
535
|
-
configSchema?.properties?.config?.required ?? [];
|
|
536
|
-
const requiredResources: string[] =
|
|
537
|
-
configSchema?.properties?.resource?.required ?? [];
|
|
538
|
-
const schemaConfigProps: Record<string, any> =
|
|
539
|
-
configSchema?.properties?.config?.properties ?? {};
|
|
540
|
-
|
|
541
|
-
const parameters = Object.entries(schemaConfigProps).map(
|
|
542
|
-
([name, propSchema]) => {
|
|
543
|
-
const entry: {
|
|
544
|
-
name: string;
|
|
545
|
-
type: string;
|
|
546
|
-
required: boolean;
|
|
547
|
-
defaultValue?: any;
|
|
548
|
-
} = {
|
|
549
|
-
name,
|
|
550
|
-
type: propSchema?.type ?? "string",
|
|
551
|
-
required: requiredParams.includes(name),
|
|
552
|
-
};
|
|
553
|
-
const currentValue = parameterValues[name];
|
|
554
|
-
if (currentValue !== undefined) entry.defaultValue = currentValue;
|
|
555
|
-
else if (propSchema?.default !== undefined)
|
|
556
|
-
entry.defaultValue = propSchema.default;
|
|
557
|
-
return entry;
|
|
558
|
-
},
|
|
559
|
-
);
|
|
560
|
-
|
|
561
|
-
const resolveResourceType = (
|
|
562
|
-
configValue: any,
|
|
563
|
-
): { type: string; kind?: string } | null => {
|
|
564
|
-
if (!configValue || typeof configValue !== "object") return null;
|
|
565
|
-
if ("secret" in configValue) return { type: "secret" };
|
|
566
|
-
if ("domain" in configValue) return { type: "domain" };
|
|
567
|
-
if ("port" in configValue) return { type: "port" };
|
|
568
|
-
if ("certificate" in configValue) return { type: "certificate" };
|
|
569
|
-
if ("ca" in configValue) return { type: "ca" };
|
|
570
|
-
if ("volume" in configValue) {
|
|
571
|
-
const volType = configValue.volume?.type;
|
|
572
|
-
if (volType === "persistent" || volType === "Persisted")
|
|
573
|
-
return { type: "volume", kind: "persistent" };
|
|
574
|
-
if (volType === "nonReplicated" || volType === "NonReplicated")
|
|
575
|
-
return { type: "volume", kind: "nonReplicated" };
|
|
576
|
-
if (
|
|
577
|
-
volType === "volatile" ||
|
|
578
|
-
volType === "Volatile" ||
|
|
579
|
-
volType === "ephemeral" ||
|
|
580
|
-
volType === "Ephemeral"
|
|
581
|
-
)
|
|
582
|
-
return { type: "volume", kind: "volatile" };
|
|
583
|
-
return { type: "volume" };
|
|
584
|
-
}
|
|
585
|
-
return null;
|
|
586
|
-
};
|
|
587
|
-
|
|
588
|
-
const allResourceNames = new Set<string>([
|
|
589
|
-
...Object.keys(configResourceValues),
|
|
590
|
-
...Object.keys(configSchema?.properties?.resource?.properties ?? {}),
|
|
591
|
-
]);
|
|
592
|
-
|
|
593
|
-
const resources = Array.from(allResourceNames)
|
|
594
|
-
.map((name) => {
|
|
595
|
-
const configValue = configResourceValues[name];
|
|
596
|
-
const fromConfig = resolveResourceType(configValue);
|
|
597
|
-
const schemaProps =
|
|
598
|
-
configSchema?.properties?.resource?.properties?.[name];
|
|
599
|
-
const fromSchema = schemaProps
|
|
600
|
-
? namedTypeToResourceKind(collectNamedTypes(schemaProps))
|
|
601
|
-
: null;
|
|
602
|
-
const resolved = fromConfig ?? fromSchema;
|
|
603
|
-
if (!resolved) return null;
|
|
604
|
-
const entry: {
|
|
605
|
-
name: string;
|
|
606
|
-
type: string;
|
|
607
|
-
kind?: string;
|
|
608
|
-
required: boolean;
|
|
609
|
-
} = {
|
|
610
|
-
name,
|
|
611
|
-
type: resolved.type,
|
|
612
|
-
required: requiredResources.includes(name),
|
|
613
|
-
};
|
|
614
|
-
if (resolved.kind) entry.kind = resolved.kind;
|
|
615
|
-
return entry;
|
|
616
|
-
})
|
|
617
|
-
.filter(Boolean) as {
|
|
618
|
-
name: string;
|
|
619
|
-
type: string;
|
|
620
|
-
kind?: string;
|
|
621
|
-
required: boolean;
|
|
622
|
-
}[];
|
|
623
|
-
|
|
624
|
-
return { parameters, resources };
|
|
625
|
-
};
|
|
626
|
-
|
|
627
526
|
export const processRevisionData = (
|
|
628
527
|
service: Service,
|
|
629
528
|
revisionData: any,
|
|
630
|
-
revisionsMap?: Map<string, Revision>,
|
|
631
|
-
serviceId?: string,
|
|
632
529
|
): Service => {
|
|
633
530
|
const { solution } = revisionData;
|
|
634
531
|
|
|
635
532
|
const config = revisionData?.config?.config || {};
|
|
636
|
-
const parameters = extractParametersFromConfig(
|
|
533
|
+
const parameters = extractParametersFromConfig(
|
|
534
|
+
config.parameter || {},
|
|
535
|
+
);
|
|
637
536
|
const resources = extractResources(config.resource || {});
|
|
638
537
|
|
|
639
|
-
const schemaResult = revisionData.revision
|
|
640
|
-
? extractStructuredSchema(revisionData)
|
|
641
|
-
: {};
|
|
642
|
-
const schema =
|
|
643
|
-
schemaResult && "parameters" in schemaResult ? schemaResult : {};
|
|
644
|
-
|
|
645
|
-
if (
|
|
646
|
-
revisionsMap &&
|
|
647
|
-
serviceId &&
|
|
648
|
-
revisionData.revision &&
|
|
649
|
-
"parameters" in schema
|
|
650
|
-
) {
|
|
651
|
-
const revisionId: string = revisionData.revision;
|
|
652
|
-
const revisionKey = `${serviceId}-${revisionId}`;
|
|
653
|
-
const existing = revisionsMap.get(revisionKey);
|
|
654
|
-
if (existing) {
|
|
655
|
-
revisionsMap.set(revisionKey, { ...existing, schema });
|
|
656
|
-
} else {
|
|
657
|
-
revisionsMap.set(revisionKey, {
|
|
658
|
-
id: revisionId,
|
|
659
|
-
schema,
|
|
660
|
-
usage: {
|
|
661
|
-
current: {
|
|
662
|
-
cpu: 0,
|
|
663
|
-
memory: 0,
|
|
664
|
-
storage: 0,
|
|
665
|
-
volatileStorage: 0,
|
|
666
|
-
nonReplicatedStorage: 0,
|
|
667
|
-
persistentStorage: 0,
|
|
668
|
-
},
|
|
669
|
-
limit: {
|
|
670
|
-
cpu: { max: revisionData.intensives?.vcpu / 1000 || 0, min: 0 },
|
|
671
|
-
memory: { max: revisionData.intensives?.ram / 1000 || 0, min: 0 },
|
|
672
|
-
storage: {
|
|
673
|
-
max: revisionData.intensives?.shared_disk / 1000 || 0,
|
|
674
|
-
min: 0,
|
|
675
|
-
},
|
|
676
|
-
volatileStorage: {
|
|
677
|
-
max: revisionData.intensives?.volatile_disk / 1000 || 0,
|
|
678
|
-
min: 0,
|
|
679
|
-
},
|
|
680
|
-
nonReplicatedStorage: {
|
|
681
|
-
max: revisionData.intensives?.nrpersistent_disk / 1000 || 0,
|
|
682
|
-
min: 0,
|
|
683
|
-
},
|
|
684
|
-
persistentStorage: {
|
|
685
|
-
max: revisionData.intensives?.persistent_disk / 1000 || 0,
|
|
686
|
-
min: 0,
|
|
687
|
-
},
|
|
688
|
-
},
|
|
689
|
-
cost: 0,
|
|
690
|
-
},
|
|
691
|
-
status: { code: "", message: "", timestamp: "", args: [] },
|
|
692
|
-
errorCode: "",
|
|
693
|
-
errorMsg: "",
|
|
694
|
-
createdAt: "",
|
|
695
|
-
});
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
|
|
699
538
|
const deploymentName = solution.top || service.name;
|
|
700
539
|
const deployment = solution.deployments[deploymentName];
|
|
701
540
|
|
|
702
|
-
const applySchemaToService = (svc: Service): Service => {
|
|
703
|
-
if (!revisionData.revision || !("parameters" in schema)) return svc;
|
|
704
|
-
const revisionId: string = revisionData.revision;
|
|
705
|
-
return {
|
|
706
|
-
...svc,
|
|
707
|
-
revisions: svc.revisions.map((rev) =>
|
|
708
|
-
rev.id === revisionId ? { ...rev, schema } : rev,
|
|
709
|
-
),
|
|
710
|
-
};
|
|
711
|
-
};
|
|
712
|
-
|
|
713
541
|
if (!deployment) {
|
|
714
542
|
const firstDeploymentKey = Object.keys(solution.deployments)[0];
|
|
715
543
|
if (firstDeploymentKey) {
|
|
716
|
-
return
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
resources,
|
|
723
|
-
),
|
|
544
|
+
return processDeployment(
|
|
545
|
+
service,
|
|
546
|
+
solution.deployments[firstDeploymentKey],
|
|
547
|
+
revisionData,
|
|
548
|
+
parameters,
|
|
549
|
+
resources,
|
|
724
550
|
);
|
|
725
551
|
}
|
|
726
|
-
return
|
|
552
|
+
return {
|
|
553
|
+
...service,
|
|
554
|
+
parameters: parameters,
|
|
555
|
+
resources: resources,
|
|
556
|
+
};
|
|
727
557
|
}
|
|
728
558
|
|
|
729
|
-
return
|
|
730
|
-
|
|
559
|
+
return processDeployment(
|
|
560
|
+
service,
|
|
561
|
+
deployment,
|
|
562
|
+
revisionData,
|
|
563
|
+
parameters,
|
|
564
|
+
resources,
|
|
731
565
|
);
|
|
732
566
|
};
|
|
733
567
|
|
|
@@ -740,6 +574,7 @@ export const processDeployment = (
|
|
|
740
574
|
): Service => {
|
|
741
575
|
const artifact = deployment.artifact;
|
|
742
576
|
const deploymentConfig = deployment.config || {};
|
|
577
|
+
|
|
743
578
|
const rolesDefinition = artifact.description?.role || {};
|
|
744
579
|
const hasRoles = Object.keys(rolesDefinition).length > 0;
|
|
745
580
|
let updatedRoles: Role[] = [];
|
|
@@ -749,10 +584,12 @@ export const processDeployment = (
|
|
|
749
584
|
([roleName, roleData]: [string, any]) => {
|
|
750
585
|
const existingRole = service.role.find((r) => r.name === roleName);
|
|
751
586
|
let hsize = 1;
|
|
752
|
-
if (roleData.config?.scale?.hsize !== undefined)
|
|
587
|
+
if (roleData.config?.scale?.hsize !== undefined) {
|
|
753
588
|
hsize = roleData.config.scale.hsize;
|
|
754
|
-
|
|
589
|
+
}
|
|
590
|
+
if (deploymentConfig.scale?.detail?.[roleName]?.hsize !== undefined) {
|
|
755
591
|
hsize = deploymentConfig.scale.detail[roleName].hsize;
|
|
592
|
+
}
|
|
756
593
|
const hasDuplex =
|
|
757
594
|
roleData.artifact?.description?.srv?.duplex?.length > 0;
|
|
758
595
|
const hasVolumeResource = Object.values(
|
|
@@ -765,24 +602,27 @@ export const processDeployment = (
|
|
|
765
602
|
description:
|
|
766
603
|
roleData.artifact?.ref?.module || roleData.ref?.module || "",
|
|
767
604
|
resource: resources,
|
|
768
|
-
parameters,
|
|
769
|
-
hsize,
|
|
605
|
+
parameters: parameters,
|
|
606
|
+
hsize: hsize,
|
|
770
607
|
category: hasDuplex || hasVolumeResource ? "stateful" : "",
|
|
771
608
|
};
|
|
772
609
|
if (
|
|
773
610
|
deployment.meta?.scaling &&
|
|
774
611
|
Object.keys(deployment.meta.scaling.simple || {}).length > 0
|
|
775
|
-
)
|
|
612
|
+
) {
|
|
776
613
|
role.scalling = processScalingConfig(deployment.meta);
|
|
614
|
+
}
|
|
777
615
|
updatedRoles.push(role);
|
|
778
616
|
},
|
|
779
617
|
);
|
|
780
618
|
} else {
|
|
781
619
|
let hsize = 1;
|
|
782
|
-
if (deploymentConfig.scale?.hsize !== undefined)
|
|
620
|
+
if (deploymentConfig.scale?.hsize !== undefined) {
|
|
783
621
|
hsize = deploymentConfig.scale.hsize;
|
|
784
|
-
|
|
622
|
+
}
|
|
623
|
+
if (deploymentConfig.scale?.detail?.[""]?.hsize !== undefined) {
|
|
785
624
|
hsize = deploymentConfig.scale.detail[""].hsize;
|
|
625
|
+
}
|
|
786
626
|
updatedRoles = [
|
|
787
627
|
{
|
|
788
628
|
name: service.name,
|
|
@@ -792,8 +632,8 @@ export const processDeployment = (
|
|
|
792
632
|
artifact.ref?.module ||
|
|
793
633
|
(artifact.description?.builtin ? "Builtin Service" : ""),
|
|
794
634
|
resource: resources,
|
|
795
|
-
parameters,
|
|
796
|
-
hsize,
|
|
635
|
+
parameters: parameters,
|
|
636
|
+
hsize: hsize,
|
|
797
637
|
...(deployment.meta?.scaling &&
|
|
798
638
|
Object.keys(deployment.meta.scaling.simple || {}).length > 0 && {
|
|
799
639
|
scalling: processScalingConfig(deployment.meta),
|
|
@@ -802,43 +642,60 @@ export const processDeployment = (
|
|
|
802
642
|
];
|
|
803
643
|
}
|
|
804
644
|
|
|
805
|
-
return {
|
|
645
|
+
return {
|
|
646
|
+
...service,
|
|
647
|
+
resources: resources,
|
|
648
|
+
parameters: parameters,
|
|
649
|
+
role: updatedRoles,
|
|
650
|
+
};
|
|
806
651
|
};
|
|
807
|
-
|
|
808
652
|
export const extractParametersFromConfig = (
|
|
809
653
|
parameterConfig: any,
|
|
810
654
|
): { [key: string]: string }[] => {
|
|
811
655
|
const parameters: { [key: string]: string }[] = [];
|
|
812
|
-
|
|
656
|
+
|
|
657
|
+
if (!parameterConfig || typeof parameterConfig !== "object") {
|
|
813
658
|
return parameters;
|
|
659
|
+
}
|
|
814
660
|
|
|
815
661
|
Object.entries(parameterConfig).forEach(
|
|
816
662
|
([paramName, paramValue]: [string, any]) => {
|
|
817
663
|
let value: string;
|
|
818
664
|
let description: string | undefined;
|
|
665
|
+
|
|
819
666
|
if (typeof paramValue === "object" && paramValue !== null) {
|
|
820
|
-
if (paramValue.value !== undefined)
|
|
821
|
-
|
|
667
|
+
if (paramValue.value !== undefined) {
|
|
668
|
+
value = paramValue.value;
|
|
669
|
+
} else if (paramValue.default !== undefined) {
|
|
822
670
|
value = String(paramValue.default);
|
|
823
|
-
else
|
|
824
|
-
|
|
671
|
+
} else {
|
|
672
|
+
value = JSON.stringify(paramValue);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
if (paramValue.description) {
|
|
676
|
+
description = paramValue.description;
|
|
677
|
+
}
|
|
825
678
|
} else {
|
|
826
679
|
value = String(paramValue);
|
|
827
680
|
}
|
|
681
|
+
|
|
828
682
|
const parameter: { [key: string]: string } = {
|
|
829
683
|
name: paramName,
|
|
830
|
-
value,
|
|
684
|
+
value: value,
|
|
831
685
|
type: typeof paramValue,
|
|
832
686
|
configKey: paramName,
|
|
833
687
|
};
|
|
834
|
-
|
|
688
|
+
|
|
689
|
+
if (description) {
|
|
690
|
+
parameter.description = description;
|
|
691
|
+
}
|
|
692
|
+
|
|
835
693
|
parameters.push(parameter);
|
|
836
694
|
},
|
|
837
695
|
);
|
|
838
696
|
|
|
839
697
|
return parameters;
|
|
840
698
|
};
|
|
841
|
-
|
|
842
699
|
export const extractParametersFromFilesystem = (
|
|
843
700
|
filesystem: any,
|
|
844
701
|
currentParameters: { [key: string]: string }[],
|
|
@@ -855,13 +712,13 @@ export const extractParametersFromFilesystem = (
|
|
|
855
712
|
value: value.data.value,
|
|
856
713
|
type: "file",
|
|
857
714
|
});
|
|
858
|
-
if (existingParam)
|
|
715
|
+
if (existingParam) {
|
|
859
716
|
currentParameters.splice(currentParameters.indexOf(existingParam), 1);
|
|
717
|
+
}
|
|
860
718
|
}
|
|
861
719
|
});
|
|
862
720
|
return parameters;
|
|
863
721
|
};
|
|
864
|
-
|
|
865
722
|
export const extractResourcesFromFilesystem = (
|
|
866
723
|
filesystem: any,
|
|
867
724
|
currentResources: Resource[],
|
|
@@ -885,15 +742,16 @@ export const extractResourcesFromFilesystem = (
|
|
|
885
742
|
status: existingResource?.status || "available",
|
|
886
743
|
tenant: "",
|
|
887
744
|
});
|
|
888
|
-
if (existingResource)
|
|
745
|
+
if (existingResource) {
|
|
889
746
|
currentResources.splice(currentResources.indexOf(existingResource), 1);
|
|
747
|
+
}
|
|
890
748
|
}
|
|
891
749
|
});
|
|
892
750
|
return resources;
|
|
893
751
|
};
|
|
894
|
-
|
|
895
752
|
export const extractResources = (resourceConfig: any): Resource[] => {
|
|
896
753
|
const resources: Resource[] = [];
|
|
754
|
+
|
|
897
755
|
Object.entries(resourceConfig).forEach(
|
|
898
756
|
([resourceName, resourceData]: [string, any]) => {
|
|
899
757
|
let resource: Resource;
|
|
@@ -962,34 +820,42 @@ export const extractResources = (resourceConfig: any): Resource[] => {
|
|
|
962
820
|
status: "available",
|
|
963
821
|
tenant: "",
|
|
964
822
|
};
|
|
823
|
+
|
|
965
824
|
if (resourceData.kind) resource.kind = resourceData.kind;
|
|
966
825
|
if (resourceData.domain) resource.domain = resourceData.domain;
|
|
967
826
|
if (resourceData.key) resource.key = resourceData.key;
|
|
968
827
|
if (resourceData.maxItems) resource.maxItems = resourceData.maxItems;
|
|
969
828
|
}
|
|
829
|
+
|
|
970
830
|
resources.push(resource);
|
|
971
831
|
},
|
|
972
832
|
);
|
|
833
|
+
|
|
973
834
|
return resources;
|
|
974
835
|
};
|
|
975
|
-
|
|
976
836
|
const processScalingConfig = (meta: any): any => {
|
|
977
|
-
if (!meta?.scaling?.simple || Object.keys(meta.scaling.simple).length === 0)
|
|
837
|
+
if (!meta?.scaling?.simple || Object.keys(meta.scaling.simple).length === 0) {
|
|
978
838
|
return {
|
|
979
839
|
cpu: { up: "80%", down: "20%" },
|
|
980
840
|
memory: { up: "80%", down: "20%" },
|
|
981
841
|
instances: { max: 1, min: 1 },
|
|
982
842
|
histeresys: "5",
|
|
983
843
|
};
|
|
984
|
-
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
const roleNames = Object.keys(meta.scaling.simple);
|
|
847
|
+
const firstRoleName = roleNames[0];
|
|
985
848
|
const roleScaling = meta.scaling.simple[firstRoleName];
|
|
986
|
-
|
|
849
|
+
|
|
850
|
+
if (!roleScaling) {
|
|
987
851
|
return {
|
|
988
852
|
cpu: { up: "80%", down: "20%" },
|
|
989
853
|
memory: { up: "80%", down: "20%" },
|
|
990
854
|
instances: { max: 1, min: 1 },
|
|
991
855
|
histeresys: "5",
|
|
992
856
|
};
|
|
857
|
+
}
|
|
858
|
+
|
|
993
859
|
return {
|
|
994
860
|
cpu: {
|
|
995
861
|
up: `${roleScaling.scale_up?.cpu || 80}%`,
|
|
@@ -1006,13 +872,99 @@ const processScalingConfig = (meta: any): any => {
|
|
|
1006
872
|
histeresys: `${roleScaling.hysteresis || 5}`,
|
|
1007
873
|
};
|
|
1008
874
|
};
|
|
1009
|
-
|
|
1010
875
|
const extractResourceName = (resourcePath: string): string => {
|
|
1011
876
|
if (!resourcePath) return "";
|
|
877
|
+
|
|
1012
878
|
const parts = resourcePath.split("/");
|
|
879
|
+
|
|
1013
880
|
if (parts.length === 2) {
|
|
1014
|
-
if (parts[0] === "cluster.core")
|
|
881
|
+
if (parts[0] === "cluster.core") {
|
|
882
|
+
return resourcePath;
|
|
883
|
+
}
|
|
1015
884
|
return parts[1];
|
|
1016
885
|
}
|
|
1017
886
|
return resourcePath;
|
|
1018
887
|
};
|
|
888
|
+
//UNUSED KEEPING IT JUST IN CASE:
|
|
889
|
+
const extractParameters = (
|
|
890
|
+
parameterConfig: any,
|
|
891
|
+
roleData?: any,
|
|
892
|
+
roleName?: string,
|
|
893
|
+
): { [key: string]: string }[] => {
|
|
894
|
+
const parameters: { [key: string]: string }[] = [];
|
|
895
|
+
|
|
896
|
+
if (roleData?.artifact?.description?.code) {
|
|
897
|
+
const codeEntries = Object.entries(roleData.artifact.description.code);
|
|
898
|
+
|
|
899
|
+
for (const [codeName, codeData] of codeEntries) {
|
|
900
|
+
const mapping = (codeData as any)?.mapping?.env;
|
|
901
|
+
|
|
902
|
+
if (mapping && typeof mapping === "object") {
|
|
903
|
+
Object.entries(mapping).forEach(([envName, envData]: [string, any]) => {
|
|
904
|
+
const envValue = envData.value || "";
|
|
905
|
+
let configKey = envName;
|
|
906
|
+
const matchedParam = Object.entries(parameterConfig).find(
|
|
907
|
+
([configParamName, paramData]: [string, any]) => {
|
|
908
|
+
const configValue =
|
|
909
|
+
typeof paramData === "object"
|
|
910
|
+
? paramData.value || paramData.default || ""
|
|
911
|
+
: String(paramData);
|
|
912
|
+
const envLower = envName.toLowerCase();
|
|
913
|
+
const configLower = configParamName.toLowerCase();
|
|
914
|
+
|
|
915
|
+
if (
|
|
916
|
+
envLower.includes(configLower) ||
|
|
917
|
+
configLower.includes(envLower)
|
|
918
|
+
) {
|
|
919
|
+
return configValue === envValue;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
return false;
|
|
923
|
+
},
|
|
924
|
+
);
|
|
925
|
+
|
|
926
|
+
if (matchedParam) {
|
|
927
|
+
configKey = matchedParam[0];
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
const parameter: { [key: string]: string } = {
|
|
931
|
+
name: envName,
|
|
932
|
+
value: envValue,
|
|
933
|
+
type: configKey,
|
|
934
|
+
configKey: configKey,
|
|
935
|
+
...(roleName && { fromRole: roleName }),
|
|
936
|
+
};
|
|
937
|
+
|
|
938
|
+
parameters.push(parameter);
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
if (parameters.length === 0 && parameterConfig) {
|
|
945
|
+
Object.entries(parameterConfig).forEach(
|
|
946
|
+
([paramName, paramData]: [string, any]) => {
|
|
947
|
+
const paramValue =
|
|
948
|
+
typeof paramData === "object"
|
|
949
|
+
? paramData.value || paramData.default || ""
|
|
950
|
+
: String(paramData);
|
|
951
|
+
|
|
952
|
+
const parameter: { [key: string]: string } = {
|
|
953
|
+
name: paramName,
|
|
954
|
+
value: paramValue,
|
|
955
|
+
type: paramName,
|
|
956
|
+
configKey: paramName,
|
|
957
|
+
...(roleName && { fromRole: roleName }),
|
|
958
|
+
};
|
|
959
|
+
|
|
960
|
+
if (typeof paramData === "object" && paramData.description) {
|
|
961
|
+
parameter.description = paramData.description;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
parameters.push(parameter);
|
|
965
|
+
},
|
|
966
|
+
);
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
return parameters;
|
|
970
|
+
};
|