@kumori/aurora-backend-handler 1.0.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.
@@ -0,0 +1,542 @@
1
+
2
+ import { Environment, Notification } from "@hestekumori/aurora-interfaces";
3
+ import { eventHelper } from "../backend-handler";
4
+ import {
5
+ initializeGlobalWebSocketClient,
6
+ getWebSocketStatus,
7
+ makeGlobalWebSocketRequest,
8
+ } from "../websocket-manager";
9
+
10
+ type Security = string;
11
+ export const createEnvironment = async (
12
+ env: Environment,
13
+ security: Security
14
+ ) => {
15
+ try {
16
+ await initializeGlobalWebSocketClient(security, "environment", env.name);
17
+ const status = getWebSocketStatus();
18
+ const isPrimary = true;
19
+ const baseMarks = {
20
+ vcpu: {
21
+ lowmark: env.usage.limit.cpu.min * 1000,
22
+ highmark: env.usage.limit.cpu.max * 1000,
23
+ unit: "m",
24
+ },
25
+ memory: {
26
+ lowmark: env.usage.limit.memory.min * 1000,
27
+ highmark: env.usage.limit.memory.max * 1000,
28
+ unit: "MB",
29
+ },
30
+ vstorage: {
31
+ lowmark: env.usage.limit.volatileStorage.min * 1000,
32
+ highmark: env.usage.limit.volatileStorage.max * 1000,
33
+ unit: "MB",
34
+ },
35
+ nrstorage: {
36
+ lowmark: env.usage.limit.nonReplicatedStorage.min * 1000,
37
+ highmark: env.usage.limit.nonReplicatedStorage.max * 1000,
38
+ unit: "MB",
39
+ },
40
+ rstorage: {
41
+ lowmark: env.usage.limit.persistentStorage.min * 1000,
42
+ highmark: env.usage.limit.persistentStorage.max * 1000,
43
+ unit: "MB",
44
+ },
45
+ storage: {
46
+ lowmark: env.usage.limit.storage.min * 1000,
47
+ highmark: env.usage.limit.storage.max * 1000,
48
+ unit: "MB",
49
+ },
50
+ cost: {
51
+ lowmark: env.usage.cost,
52
+ highmark: env.usage.cost,
53
+ unit: "EUR",
54
+ },
55
+ nodes: {
56
+ lowmark: env.nodes?.max,
57
+ highmark: env.nodes?.max,
58
+ unit: "",
59
+ }
60
+ };
61
+ const environmentSpec: any = isPrimary
62
+ ? {
63
+ type: "primary",
64
+ marks: baseMarks,
65
+ highlyAvailable: env.highAvaliable || false,
66
+ }
67
+ : {
68
+ type: "secondary",
69
+ primary: { name: env.organization, kind: "environment" },
70
+ parent: { kind: "account", name: env.account },
71
+ marks: baseMarks,
72
+ isolated: true,
73
+ };
74
+
75
+ const labels: { [key: string]: string } = {};
76
+ if (env.labels && env.labels.length > 0) {
77
+ env.labels.forEach((label, idx) => {
78
+ labels[`label${idx + 1}`] = label;
79
+ });
80
+ }
81
+
82
+ const environmentBody = {
83
+ tenant: env.tenant,
84
+ account: env.account,
85
+ environment: env.name,
86
+ provision_infrastructure: false,
87
+ spec: {
88
+ spec: environmentSpec,
89
+ labels,
90
+ },
91
+ };
92
+
93
+ const response = await makeGlobalWebSocketRequest(
94
+ "environment:create_environment",
95
+ environmentBody,
96
+ 30000,
97
+ "CREATE",
98
+ env.name,
99
+ "environment",
100
+ env
101
+ );
102
+
103
+ //const updatedEnv: Environment = { ...env, status: "pending" };
104
+ //eventHelper.environment.publish.created(updatedEnv);
105
+ return response;
106
+ } catch (error) {
107
+ console.error("Error creating environment:", {
108
+ error,
109
+ errorMessage: error instanceof Error ? error.message : "Unknown error",
110
+ environment: env.name,
111
+ tenant: env.tenant,
112
+ account: env.account,
113
+ webSocketStatus: getWebSocketStatus(),
114
+ });
115
+ let contentMessage = "Unknown error";
116
+ let errorContent = "Unknown error";
117
+
118
+ if (
119
+ typeof error === "object" &&
120
+ error !== null &&
121
+ "error" in error &&
122
+ typeof (error as any).error === "object" &&
123
+ (error as any).error !== null
124
+ ) {
125
+ if ("code" in (error as any).error) {
126
+ contentMessage = (error as any).error.code;
127
+ }
128
+ if ("content" in (error as any).error) {
129
+ errorContent = (error as any).error.content;
130
+ }
131
+ }
132
+ const envErrorNotification: Notification = {
133
+ type: "error",
134
+ subtype: "environment-creation-error",
135
+ info_content: {
136
+ code: contentMessage,
137
+ message: errorContent,
138
+ },
139
+ date: Date.now().toString(),
140
+ status: "unread",
141
+ callToAction: false,
142
+ data: {
143
+ environment: env.name,
144
+ account: env.account,
145
+ tenant: env.tenant
146
+ }
147
+ };
148
+ eventHelper.notification.publish.creation(envErrorNotification);
149
+ throw error;
150
+ }
151
+ };
152
+
153
+ export const deleteEnvironment = async (
154
+ env: Environment,
155
+ security: Security
156
+ ) => {
157
+ try {
158
+ await initializeGlobalWebSocketClient(security, "environment", env.name);
159
+ const status = getWebSocketStatus();
160
+
161
+ const deletePayload = {
162
+ tenant: env.tenant,
163
+ account: env.account,
164
+ environment: env.name,
165
+ delete: true,
166
+ force: true,
167
+ };
168
+
169
+ const response = await makeGlobalWebSocketRequest(
170
+ "environment:delete_environment",
171
+ deletePayload,
172
+ 30000,
173
+ "DELETE",
174
+ env.name,
175
+ "environment",
176
+ env
177
+ );
178
+
179
+ // const updatedEnv: Environment = { ...env, status: "pending" };
180
+ // eventHelper.environment.publish.deleted(updatedEnv);
181
+ const envNotification: Notification = {
182
+ type: "success",
183
+ subtype: "environment-deleting",
184
+ date: Date.now().toString(),
185
+ status: "unread",
186
+ callToAction: false,
187
+ data: {
188
+ environment: env.name,
189
+ account: env.account,
190
+ tenant: env.tenant
191
+ }
192
+ };
193
+ eventHelper.notification.publish.creation(envNotification);
194
+ return response;
195
+ } catch (error) {
196
+ console.error("Error deleting environment:", {
197
+ error,
198
+ environment: env.name,
199
+ tenant: env.tenant,
200
+ account: env.account,
201
+ webSocketStatus: getWebSocketStatus(),
202
+ });
203
+ eventHelper.environment.publish.deletionError(env);
204
+ let contentMessage = "Unknown error";
205
+ let errorContent = "Unknown error";
206
+
207
+ if (
208
+ typeof error === "object" &&
209
+ error !== null &&
210
+ "error" in error &&
211
+ typeof (error as any).error === "object" &&
212
+ (error as any).error !== null
213
+ ) {
214
+ if ("code" in (error as any).error) {
215
+ contentMessage = (error as any).error.code;
216
+ }
217
+ if ("content" in (error as any).error) {
218
+ errorContent = (error as any).error.content;
219
+ }
220
+ }
221
+ const envErrorNotification: Notification = {
222
+ type: "error",
223
+ subtype: "environment-deletion-error",
224
+ info_content: {
225
+ code: contentMessage,
226
+ message: errorContent,
227
+ },
228
+ date: Date.now().toString(),
229
+ status: "unread",
230
+ callToAction: false,
231
+ data: {
232
+ environment: env.name,
233
+ account: env.account,
234
+ tenant: env.tenant
235
+ }
236
+ };
237
+ eventHelper.notification.publish.creation(envErrorNotification);
238
+ throw error;
239
+ }
240
+ };
241
+
242
+ export const clearEnvironment = async (
243
+ env: Environment,
244
+ security: Security
245
+ ) => {
246
+ try {
247
+ const envNotification: Notification = {
248
+ type: "info",
249
+ subtype: "environment-cleaning",
250
+ date: Date.now().toString(),
251
+ status: "unread",
252
+ callToAction: false,
253
+ data: {
254
+ environment: env.name,
255
+ account: env.account,
256
+ tenant: env.tenant
257
+ }
258
+ };
259
+ eventHelper.notification.publish.creation(envNotification);
260
+ await initializeGlobalWebSocketClient(security, "environment", env.name);
261
+ const status = getWebSocketStatus();
262
+
263
+ const deletePayload = {
264
+ tenant: env.tenant,
265
+ account: env.account,
266
+ environment: env.name,
267
+ delete: false,
268
+ force: false,
269
+ };
270
+
271
+ const response = await makeGlobalWebSocketRequest(
272
+ "environment:delete_environment",
273
+ deletePayload,
274
+ 30000,
275
+ "CLEAN",
276
+ env.name,
277
+ "environment",
278
+ env
279
+ );
280
+
281
+ return response;
282
+ } catch (error) {
283
+ console.error("Error deleting environment:", {
284
+ error,
285
+ environment: env.name,
286
+ tenant: env.tenant,
287
+ account: env.account,
288
+ webSocketStatus: getWebSocketStatus(),
289
+ });
290
+ eventHelper.environment.publish.deletionError(env);
291
+ let contentMessage = "Unknown error";
292
+ let errorContent = "Unknown error";
293
+
294
+ if (
295
+ typeof error === "object" &&
296
+ error !== null &&
297
+ "error" in error &&
298
+ typeof (error as any).error === "object" &&
299
+ (error as any).error !== null
300
+ ) {
301
+ if ("code" in (error as any).error) {
302
+ contentMessage = (error as any).error.code;
303
+ }
304
+ if ("content" in (error as any).error) {
305
+ errorContent = (error as any).error.content;
306
+ }
307
+ }
308
+ const envErrorNotification: Notification = {
309
+ type: "error",
310
+ subtype: "environment-cleaning-error",
311
+ info_content: {
312
+ code: contentMessage,
313
+ message: errorContent,
314
+ },
315
+ date: Date.now().toString(),
316
+ status: "unread",
317
+ callToAction: false,
318
+ data: {
319
+ environment: env.name,
320
+ account: env.account,
321
+ tenant: env.tenant
322
+ }
323
+ };
324
+ eventHelper.notification.publish.creation(envErrorNotification);
325
+ throw error;
326
+ }
327
+ };
328
+
329
+ export const updateEnvironment = async (
330
+ env: Environment,
331
+ security: Security
332
+ ) => {
333
+ try {
334
+ await initializeGlobalWebSocketClient(security, "environment", env.name);
335
+ const status = getWebSocketStatus();
336
+
337
+ const updatePayload = {
338
+ tenant: env.tenant,
339
+ account: env.account,
340
+ environment: env.name,
341
+ spec: {
342
+ marks: {
343
+ vcpu: {
344
+ lowmark: env.usage.limit.cpu.min * 1000,
345
+ highmark: env.usage.limit.cpu.max * 1000,
346
+ unit: "m",
347
+ },
348
+ memory: {
349
+ lowmark: env.usage.limit.memory.min * 1000,
350
+ highmark: env.usage.limit.memory.max * 1000,
351
+ unit: "MB",
352
+ },
353
+ vstorage: {
354
+ lowmark: env.usage.limit.volatileStorage.min * 1000,
355
+ highmark: env.usage.limit.volatileStorage.max * 1000,
356
+ unit: "MB",
357
+ },
358
+ nrstorage: {
359
+ lowmark: env.usage.limit.nonReplicatedStorage.min * 1000,
360
+ highmark: env.usage.limit.nonReplicatedStorage.max * 1000,
361
+ unit: "MB",
362
+ },
363
+ rstorage: {
364
+ lowmark: env.usage.limit.persistentStorage.min * 1000,
365
+ highmark: env.usage.limit.persistentStorage.max * 1000,
366
+ unit: "MB",
367
+ },
368
+ storage: {
369
+ lowmark: env.usage.limit.storage.min * 1000,
370
+ highmark: env.usage.limit.storage.max * 1000,
371
+ unit: "MB",
372
+ },
373
+ cost: {
374
+ lowmark: env.usage.cost,
375
+ highmark: env.usage.cost,
376
+ unit: "EUR",
377
+ },
378
+ nodes: {
379
+ lowmark: env.nodes?.max,
380
+ highmark: env.nodes?.max,
381
+ unit: "",
382
+ }
383
+ },
384
+ isolated: true,
385
+ highlyAvailable: env.highAvaliable || false,
386
+ },
387
+ };
388
+
389
+ const response = await makeGlobalWebSocketRequest(
390
+ "environment:update_environment",
391
+ updatePayload,
392
+ 30000,
393
+ "UPDATE",
394
+ env.name,
395
+ "environment",
396
+ env
397
+ );
398
+
399
+ const updatedEnv: Environment = { ...env, status: {
400
+ code: "pending",
401
+ message: "",
402
+ timestamp: ""
403
+ } };
404
+ eventHelper.environment.publish.updated(updatedEnv);
405
+ const envNotification: Notification = {
406
+ type: "success",
407
+ subtype: "environment-updated",
408
+ date: Date.now().toString(),
409
+ status: "unread",
410
+ callToAction: false,
411
+ data: {
412
+ environment: env.name,
413
+ account: env.account,
414
+ tenant: env.tenant
415
+ }
416
+ };
417
+ eventHelper.notification.publish.creation(envNotification);
418
+ return response;
419
+ } catch (error) {
420
+ console.error("Error updating environment:", {
421
+ error,
422
+ environment: env.name,
423
+ tenant: env.tenant,
424
+ account: env.account,
425
+ webSocketStatus: getWebSocketStatus(),
426
+ });
427
+ eventHelper.environment.publish.updateError(env);
428
+ let contentMessage = "Unknown error";
429
+ let errorContent = "Unknown error";
430
+
431
+ if (
432
+ typeof error === "object" &&
433
+ error !== null &&
434
+ "error" in error &&
435
+ typeof (error as any).error === "object" &&
436
+ (error as any).error !== null
437
+ ) {
438
+ if ("code" in (error as any).error) {
439
+ contentMessage = (error as any).error.code;
440
+ }
441
+ if ("content" in (error as any).error) {
442
+ errorContent = (error as any).error.content;
443
+ }
444
+ }
445
+ const envErrorNotification: Notification = {
446
+ type: "error",
447
+ subtype: "environment-update-error",
448
+ info_content: {
449
+ code: contentMessage,
450
+ message: errorContent,
451
+ },
452
+ date: Date.now().toString(),
453
+ status: "unread",
454
+ callToAction: false,
455
+ data: {
456
+ environment: env.name,
457
+ account: env.account,
458
+ tenant: env.tenant
459
+ }
460
+ };
461
+ eventHelper.notification.publish.creation(envErrorNotification);
462
+ throw error;
463
+ }
464
+ };
465
+ export const scaleEnvironment = async (
466
+ env: Environment,
467
+ security: Security
468
+ ) => {
469
+ try{
470
+ const updatePayload = {
471
+ tenant: env.tenant,
472
+ account: env.account,
473
+ environment: env.name,
474
+ // controlPlane: env.targetVMS?.controlPlane,
475
+ // worker: env.targetVMS?.worker,
476
+ ingress: env.targetVMS?.ingress.toString(),
477
+ };
478
+ const response = await makeGlobalWebSocketRequest(
479
+ "environment:scale_environment",
480
+ updatePayload,
481
+ 30000,
482
+ "SCALE",
483
+ env.name,
484
+ "environment",
485
+ env
486
+ );
487
+ if(!response.ok) return;
488
+ eventHelper.environment.publish.scaled(env);
489
+ const envNotification: Notification = {
490
+ type: "success",
491
+ subtype: "environment-scaled",
492
+ date: Date.now().toString(),
493
+ status: "unread",
494
+ callToAction: false,
495
+ data: {
496
+ environment: env.name,
497
+ account: env.account,
498
+ tenant: env.tenant
499
+ }
500
+ };
501
+ eventHelper.notification.publish.creation(envNotification);
502
+ return response;
503
+ }
504
+ catch(error){
505
+ eventHelper.environment.publish.scaleError(env);
506
+ let contentMessage = "Unknown error";
507
+ let errorContent = "Unknown error";
508
+
509
+ if (
510
+ typeof error === "object" &&
511
+ error !== null &&
512
+ "error" in error &&
513
+ typeof (error as any).error === "object" &&
514
+ (error as any).error !== null
515
+ ) {
516
+ if ("code" in (error as any).error) {
517
+ contentMessage = (error as any).error.code;
518
+ }
519
+ if ("content" in (error as any).error) {
520
+ errorContent = (error as any).error.content;
521
+ }
522
+ }
523
+ const envErrorNotification: Notification = {
524
+ type: "error",
525
+ subtype: "environment-scale-error",
526
+ info_content: {
527
+ code: contentMessage,
528
+ message: errorContent,
529
+ },
530
+ date: Date.now().toString(),
531
+ status: "unread",
532
+ callToAction: false,
533
+ data: {
534
+ environment: env.name,
535
+ account: env.account,
536
+ tenant: env.tenant
537
+ }
538
+ };
539
+ eventHelper.notification.publish.creation(envErrorNotification);
540
+ throw error;
541
+ }
542
+ }