@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,1092 @@
1
+
2
+ import { Account, Notification } from "@hestekumori/aurora-interfaces";
3
+ import {
4
+ initializeGlobalWebSocketClient,
5
+ getWebSocketStatus,
6
+ makeGlobalWebSocketRequest,
7
+ } from "../websocket-manager";
8
+ import { eventHelper } from "../backend-handler";
9
+
10
+ type Security = string;
11
+
12
+ export const createAccount = async (account: Account, security: Security) => {
13
+ try {
14
+ await initializeGlobalWebSocketClient(security, "account", account.name);
15
+ const status = getWebSocketStatus();
16
+ const providerName = account.cloudProvider?.name?.toLowerCase();
17
+
18
+ let accountBody;
19
+ if (providerName === "aws") {
20
+ accountBody = {
21
+ tenant: account.tenant,
22
+ account: account.name,
23
+ provision_infrastructure: false,
24
+ spec: {
25
+ spec: {
26
+ api: "aws",
27
+ credentials: account.cloudProvider.password
28
+ ? {
29
+ admin_access_key: account.cloudProvider.username || "",
30
+ admin_secret_key: account.cloudProvider.password || "",
31
+ region: account.cloudProvider?.region || "",
32
+ }
33
+ : {
34
+ method: "aws",
35
+ aws: {
36
+ region: account.cloudProvider?.region || "",
37
+ aws_access_key_id:
38
+ account.cloudProvider?.credentialId || "",
39
+ aws_secret_access_key:
40
+ account.cloudProvider?.credentialSecret || "",
41
+ },
42
+ },
43
+ marks: {
44
+ vcpu: {
45
+ lowmark: account.usage.limit.cpu.min * 1000,
46
+ highmark: account.usage.limit.cpu.max * 1000,
47
+ unit: "m",
48
+ },
49
+ memory: {
50
+ lowmark: account.usage.limit.memory.min * 1000,
51
+ highmark: account.usage.limit.memory.max * 1000,
52
+ unit: "MB",
53
+ },
54
+ vstorage: {
55
+ lowmark: account.usage.limit.volatileStorage.min * 1000,
56
+ highmark: account.usage.limit.volatileStorage.max * 1000,
57
+ unit: "MB",
58
+ },
59
+ nrstorage: {
60
+ lowmark: account.usage.limit.nonReplicatedStorage.min * 1000,
61
+ highmark: account.usage.limit.nonReplicatedStorage.max * 1000,
62
+ unit: "MB",
63
+ },
64
+ rstorage: {
65
+ lowmark: account.usage.limit.persistentStorage.min * 1000,
66
+ highmark: account.usage.limit.persistentStorage.max * 1000,
67
+ unit: "MB",
68
+ },
69
+ storage: {
70
+ lowmark: account.usage.limit.storage.min * 1000,
71
+ highmark: account.usage.limit.storage.max * 1000,
72
+ unit: "MB",
73
+ },
74
+ cost: {
75
+ lowmark: account.usage.cost,
76
+ highmark: account.usage.cost,
77
+ unit: "EUR",
78
+ },
79
+ nodes: {
80
+ lowmark: account.nodes?.min || 0,
81
+ highmark: account.nodes?.max || 0,
82
+ unit: "",
83
+ },
84
+ },
85
+ iaasconfig: {
86
+ ...(account.flavors?.volatile?.[0] && { volatile: account.flavors.volatile[0] }),
87
+ ...(account.flavors?.persistent?.[0] && { persistent: account.flavors.persistent[0] }),
88
+ ...(account.flavors?.nonReplicated?.[0] && { nonreplicated: account.flavors.nonReplicated[0] }),
89
+ // shared: "classic",
90
+ ...(account.flavors?.small?.[0] && { smallVMFlavor: account.flavors?.small?.[0] }),
91
+ ...(account.flavors?.medium?.[0] && { mediumVMFlavor: account.flavors.medium[0] }),
92
+ // ...(account.flavors?.large?.[0] && { largeVMFlavor: account.flavors.large[0] }),
93
+ }
94
+ },
95
+ meta: {
96
+ labels: {
97
+ additionalProp1: "string",
98
+ additionalProp2: "string",
99
+ additionalProp3: "string",
100
+ },
101
+ },
102
+ },
103
+ };
104
+ } else if (providerName === "azure") {
105
+ accountBody = {
106
+ tenant: account.tenant,
107
+ account: account.name,
108
+ provision_infrastructure: false,
109
+ spec: {
110
+ spec: {
111
+ api: "azure",
112
+ credentials: account.cloudProvider.password
113
+ ? {
114
+ tenant_id: account.cloudProvider.tenantId || "",
115
+ admin_client_id: account.cloudProvider.username || "",
116
+ admin_client_secret: account.cloudProvider.password || "",
117
+ subscription_id: account.cloudProvider.subscriptionId || "",
118
+ region: account.cloudProvider?.region || "",
119
+ }
120
+ : {
121
+ method: "azure",
122
+ azure: {
123
+ region: account.cloudProvider?.region || "",
124
+ subscription_id:
125
+ account.cloudProvider?.subscriptionId || "",
126
+ tenant_id: account.cloudProvider?.tenantId || "",
127
+ client_id: account.cloudProvider?.clientId || "",
128
+ client_secret: account.cloudProvider?.clientSecret || "",
129
+ },
130
+ },
131
+ marks: {
132
+ vcpu: {
133
+ lowmark: account.usage.limit.cpu.min * 1000,
134
+ highmark: account.usage.limit.cpu.max * 1000,
135
+ unit: "m",
136
+ },
137
+ memory: {
138
+ lowmark: account.usage.limit.memory.min * 1000,
139
+ highmark: account.usage.limit.memory.max * 1000,
140
+ unit: "MB",
141
+ },
142
+ vstorage: {
143
+ lowmark: account.usage.limit.volatileStorage.min * 1000,
144
+ highmark: account.usage.limit.volatileStorage.max * 1000,
145
+ unit: "MB",
146
+ },
147
+ nrstorage: {
148
+ lowmark: account.usage.limit.nonReplicatedStorage.min * 1000,
149
+ highmark: account.usage.limit.nonReplicatedStorage.max * 1000,
150
+ unit: "MB",
151
+ },
152
+ rstorage: {
153
+ lowmark: account.usage.limit.persistentStorage.min * 1000,
154
+ highmark: account.usage.limit.persistentStorage.max * 1000,
155
+ unit: "MB",
156
+ },
157
+ storage: {
158
+ lowmark: account.usage.limit.storage.min * 1000,
159
+ highmark: account.usage.limit.storage.max * 1000,
160
+ unit: "MB",
161
+ },
162
+ cost: {
163
+ lowmark: account.usage.cost,
164
+ highmark: account.usage.cost,
165
+ unit: "EUR",
166
+ },
167
+ nodes: {
168
+ lowmark: account.nodes?.min || 0,
169
+ highmark: account.nodes?.max || 0,
170
+ unit: "",
171
+ },
172
+ },
173
+ iaasconfig: {
174
+ ...(account.flavors?.volatile?.[0] && { volatile: account.flavors.volatile[0] }),
175
+ ...(account.flavors?.persistent?.[0] && { persistent: account.flavors.persistent[0] }),
176
+ ...(account.flavors?.nonReplicated?.[0] && { nonreplicated: account.flavors.nonReplicated[0] }),
177
+ // shared: "classic",
178
+ ...(account.flavors?.small?.[0] && { smallVMFlavor: account.flavors?.small?.[0] }),
179
+ ...(account.flavors?.medium?.[0] && { mediumVMFlavor: account.flavors.medium[0] }),
180
+ // ...(account.flavors?.large?.[0] && { largeVMFlavor: account.flavors.large[0] }),
181
+ }
182
+ },
183
+ meta: {
184
+ labels: {
185
+ additionalProp1: "string",
186
+ additionalProp2: "string",
187
+ additionalProp3: "string",
188
+ },
189
+ },
190
+ },
191
+ };
192
+ } else if (providerName === "ovh") {
193
+ accountBody = {
194
+ tenant: account.tenant,
195
+ account: account.name,
196
+ provision_infrastructure: false,
197
+ spec: {
198
+ spec: {
199
+ api: providerName,
200
+ credentials: account.cloudProvider.password
201
+ ? {
202
+ username: account.cloudProvider.username || "",
203
+ password: account.cloudProvider.password || "",
204
+ region: account.cloudProvider?.region || "",
205
+ }
206
+ : {
207
+ method: providerName,
208
+ // ovh: {
209
+ // endpoint: "string",
210
+ // application_key: "string",
211
+ // application_secret: "string",
212
+ // consumer_key: "string",
213
+ // },
214
+ openstack: {
215
+ region_name: account.cloudProvider?.region || "",
216
+ interface: account.cloudProvider?.interface || "",
217
+ identity_api_version: Number(
218
+ account.cloudProvider?.apiVersion || 3
219
+ ),
220
+ auth_type: account.cloudProvider?.authType || "",
221
+ auth: {
222
+ auth_url: account.cloudProvider?.authUrl || "",
223
+ application_credential_id:
224
+ account.cloudProvider?.credentialId || "",
225
+ application_credential_secret:
226
+ account.cloudProvider?.credentialSecret || "",
227
+ },
228
+ },
229
+ },
230
+ highlyAvailable: true,
231
+ marks: {
232
+ vcpu: {
233
+ lowmark: account.usage.limit.cpu.min * 1000,
234
+ highmark: account.usage.limit.cpu.max * 1000,
235
+ unit: "m",
236
+ },
237
+ memory: {
238
+ lowmark: account.usage.limit.memory.min * 1000,
239
+ highmark: account.usage.limit.memory.max * 1000,
240
+ unit: "MB",
241
+ },
242
+ vstorage: {
243
+ lowmark: account.usage.limit.volatileStorage.min * 1000,
244
+ highmark: account.usage.limit.volatileStorage.max * 1000,
245
+ unit: "MB",
246
+ },
247
+ nrstorage: {
248
+ lowmark: account.usage.limit.nonReplicatedStorage.min * 1000,
249
+ highmark: account.usage.limit.nonReplicatedStorage.max * 1000,
250
+ unit: "MB",
251
+ },
252
+ rstorage: {
253
+ lowmark: account.usage.limit.persistentStorage.min * 1000,
254
+ highmark: account.usage.limit.persistentStorage.max * 1000,
255
+ unit: "MB",
256
+ },
257
+ storage: {
258
+ lowmark: account.usage.limit.storage.min * 1000,
259
+ highmark: account.usage.limit.storage.max * 1000,
260
+ unit: "MB",
261
+ },
262
+ cost: {
263
+ lowmark: account.usage.cost,
264
+ highmark: account.usage.cost,
265
+ unit: "EUR",
266
+ },
267
+ nodes: {
268
+ lowmark: account.nodes?.max || 0,
269
+ highmark: account.nodes?.max || 0,
270
+ unit: "",
271
+ },
272
+ },
273
+ iaasconfig: {
274
+ ...(account.flavors?.volatile?.[0] && { volatile: account.flavors.volatile[0] }),
275
+ ...(account.flavors?.persistent?.[0] && { persistent: account.flavors.persistent[0] }),
276
+ ...(account.flavors?.nonReplicated?.[0] && { nonreplicated: account.flavors.nonReplicated[0] }),
277
+ // shared: "classic",
278
+ ...(account.flavors?.small?.[0] && { smallVMFlavor: account.flavors?.small?.[0] }),
279
+ ...(account.flavors?.medium?.[0] && { mediumVMFlavor: account.flavors.medium[0] }),
280
+ // ...(account.flavors?.large?.[0] && { largeVMFlavor: account.flavors.large[0] }),
281
+ }
282
+ },
283
+ meta: {
284
+ labels: {
285
+ additionalProp1: "string",
286
+ additionalProp2: "string",
287
+ additionalProp3: "string",
288
+ },
289
+ },
290
+ },
291
+ };
292
+ }
293
+ else if (providerName === "oasix") {
294
+ accountBody = {
295
+ tenant: account.tenant,
296
+ account: account.name,
297
+ provision_infrastructure: false,
298
+ spec: {
299
+ spec: {
300
+ api: providerName,
301
+ credentials: account.cloudProvider.password
302
+ ? {
303
+ username: account.cloudProvider.username || "",
304
+ password: account.cloudProvider.password || "",
305
+ region: account.cloudProvider?.region || "",
306
+ domain: account.cloudProvider?.domain || "",
307
+ }
308
+ : {
309
+ method: providerName,
310
+ // ovh: {
311
+ // endpoint: "string",
312
+ // application_key: "string",
313
+ // application_secret: "string",
314
+ // consumer_key: "string",
315
+ // },
316
+ openstack: {
317
+ region_name: account.cloudProvider?.region || "",
318
+ interface: account.cloudProvider?.interface || "",
319
+ identity_api_version: Number(
320
+ account.cloudProvider?.apiVersion || 3
321
+ ),
322
+ auth_type: account.cloudProvider?.authType || "",
323
+ auth: {
324
+ auth_url: account.cloudProvider?.authUrl || "",
325
+ application_credential_id:
326
+ account.cloudProvider?.credentialId || "",
327
+ application_credential_secret:
328
+ account.cloudProvider?.credentialSecret || "",
329
+ },
330
+ },
331
+ },
332
+ highlyAvailable: true,
333
+ marks: {
334
+ vcpu: {
335
+ lowmark: account.usage.limit.cpu.min * 1000,
336
+ highmark: account.usage.limit.cpu.max * 1000,
337
+ unit: "m",
338
+ },
339
+ memory: {
340
+ lowmark: account.usage.limit.memory.min * 1000,
341
+ highmark: account.usage.limit.memory.max * 1000,
342
+ unit: "MB",
343
+ },
344
+ vstorage: {
345
+ lowmark: account.usage.limit.volatileStorage.min * 1000,
346
+ highmark: account.usage.limit.volatileStorage.max * 1000,
347
+ unit: "MB",
348
+ },
349
+ nrstorage: {
350
+ lowmark: account.usage.limit.nonReplicatedStorage.min * 1000,
351
+ highmark: account.usage.limit.nonReplicatedStorage.max * 1000,
352
+ unit: "MB",
353
+ },
354
+ rstorage: {
355
+ lowmark: account.usage.limit.persistentStorage.min * 1000,
356
+ highmark: account.usage.limit.persistentStorage.max * 1000,
357
+ unit: "MB",
358
+ },
359
+ storage: {
360
+ lowmark: account.usage.limit.storage.min * 1000,
361
+ highmark: account.usage.limit.storage.max * 1000,
362
+ unit: "MB",
363
+ },
364
+ cost: {
365
+ lowmark: account.usage.cost,
366
+ highmark: account.usage.cost,
367
+ unit: "EUR",
368
+ },
369
+ nodes: {
370
+ lowmark: account.nodes?.max || 0,
371
+ highmark: account.nodes?.max || 0,
372
+ unit: "",
373
+ },
374
+ },
375
+ iaasconfig: {
376
+ ...(account.flavors?.volatile?.[0] && { volatile: account.flavors.volatile[0] }),
377
+ ...(account.flavors?.persistent?.[0] && { persistent: account.flavors.persistent[0] }),
378
+ ...(account.flavors?.nonReplicated?.[0] && { nonreplicated: account.flavors.nonReplicated[0] }),
379
+ // shared: "classic",
380
+ ...(account.flavors?.small?.[0] && { smallVMFlavor: account.flavors?.small?.[0] }),
381
+ ...(account.flavors?.medium?.[0] && { mediumVMFlavor: account.flavors.medium[0] }),
382
+ // ...(account.flavors?.large?.[0] && { largeVMFlavor: account.flavors.large[0] }),
383
+ }
384
+ },
385
+ meta: {
386
+ labels: {
387
+ additionalProp1: "string",
388
+ additionalProp2: "string",
389
+ additionalProp3: "string",
390
+ },
391
+ },
392
+ },
393
+ };
394
+ } else {
395
+ throw new Error(
396
+ `Unsupported cloud provider: ${providerName}. Supported providers are: ovh, aws, azure`
397
+ );
398
+ }
399
+
400
+ const response = await makeGlobalWebSocketRequest(
401
+ "account:create_account",
402
+ accountBody,
403
+ 30000,
404
+ "CREATE",
405
+ account.name,
406
+ "account",
407
+ account
408
+ );
409
+ const updatedAccount: Account = { ...account, status: "pending" };
410
+ eventHelper.account.publish.created(updatedAccount);
411
+ // const accountNotification: Notification = {
412
+ // type: "success",
413
+ // subtype: "account-created",
414
+ // date: Date.now().toString(),
415
+ // status: "unread",
416
+ // callToAction: false,
417
+ // data: {
418
+ // account: account.name,
419
+ // tenant: account.tenant,
420
+ // },
421
+ // };
422
+ // eventHelper.notification.publish.creation(accountNotification);
423
+ return response;
424
+ } catch (error) {
425
+ console.error("Error creating account:", {
426
+ error,
427
+ errorMessage: error instanceof Error ? error.message : "Unknown error",
428
+ account: account.name,
429
+ tenant: account.tenant,
430
+ provider: account.cloudProvider?.name,
431
+ webSocketStatus: getWebSocketStatus(),
432
+ });
433
+ let contentMessage = "Unknown error";
434
+
435
+ if (
436
+ typeof error === "object" &&
437
+ error !== null &&
438
+ "error" in error &&
439
+ typeof (error as any).error === "object" &&
440
+ (error as any).error !== null &&
441
+ "content" in (error as any).error
442
+ ) {
443
+ contentMessage = (error as any).error.code;
444
+ }
445
+ const accountErrorNotification: Notification = {
446
+ type: "error",
447
+ subtype: "account-creation-error",
448
+ info_content: {
449
+ code: (error as any).error.code,
450
+ message: (error as any).error.content,
451
+ },
452
+ date: Date.now().toString(),
453
+ status: "unread",
454
+ callToAction: false,
455
+ data: {
456
+ account: account.name,
457
+ tenant: account.tenant,
458
+ },
459
+ };
460
+ eventHelper.notification.publish.creation(accountErrorNotification);
461
+ throw error;
462
+ }
463
+ };
464
+
465
+ export const deleteAccount = async (account: Account, security: Security) => {
466
+ try {
467
+ await initializeGlobalWebSocketClient(security, "account", account.name);
468
+ const providerName = account.cloudProvider?.name?.toLowerCase();
469
+ let payload = {};
470
+ if(!account.credentials){
471
+ payload = {
472
+ tenant: account.tenant,
473
+ account: account.name,
474
+ delete: true,
475
+ force: true,
476
+ };
477
+ }
478
+ else if (providerName === "ovh") {
479
+ payload = {
480
+ tenant: account.tenant,
481
+ account: account.name,
482
+ delete: true,
483
+ force: true,
484
+ spec: {
485
+ credentials: {
486
+ username: account.cloudProvider.username,
487
+ password: account.cloudProvider.password,
488
+ },
489
+
490
+ },
491
+ };
492
+ }
493
+ else if (providerName === "oasix") {
494
+ payload = {
495
+ tenant: account.tenant,
496
+ account: account.name,
497
+ delete: true,
498
+ force: true,
499
+ spec: {
500
+ credentials: {
501
+ username: account.cloudProvider.username,
502
+ password: account.cloudProvider.password,
503
+ domain: account.cloudProvider.domain,
504
+ },
505
+
506
+ },
507
+ };
508
+ }else if (providerName === "aws") {
509
+ payload = {
510
+ tenant: account.tenant,
511
+ account: account.name,
512
+ delete: true,
513
+ force: true,
514
+ spec: {
515
+ credentials: {
516
+ admin_access_key: account.cloudProvider.username,
517
+ admin_secret_key: account.cloudProvider.password,
518
+ },
519
+
520
+ },
521
+ };
522
+ } else if (providerName === "azure") {
523
+ payload = {
524
+ tenant: account.tenant,
525
+ account: account.name,
526
+ delete: true,
527
+ force: true,
528
+ spec: {
529
+ credentials: {
530
+ admin_client_id: account.cloudProvider.username,
531
+ admin_client_secret: account.cloudProvider.password,
532
+ },
533
+
534
+ },
535
+ };
536
+ }
537
+
538
+ const response = await makeGlobalWebSocketRequest(
539
+ "account:cleanup_account",
540
+ payload,
541
+ 30000,
542
+ "DELETE",
543
+ account.name,
544
+ "account",
545
+ account
546
+ );
547
+
548
+ // const updatedAccount: Account = { ...account, status: "pending" };
549
+ // eventHelper.account.publish.deleted(updatedAccount);
550
+ const accountNotification: Notification = {
551
+ type: "success",
552
+ subtype: "account-deleteing",
553
+ date: Date.now().toString(),
554
+ status: "unread",
555
+ callToAction: false,
556
+ data: {
557
+ account: account.name,
558
+ tenant: account.tenant,
559
+ },
560
+ };
561
+ eventHelper.notification.publish.creation(accountNotification);
562
+ return response;
563
+ } catch (error) {
564
+ eventHelper.account.publish.deletionError(account);
565
+ let contentMessage = "Unknown error";
566
+
567
+ if (
568
+ typeof error === "object" &&
569
+ error !== null &&
570
+ "error" in error &&
571
+ typeof (error as any).error === "object" &&
572
+ (error as any).error !== null &&
573
+ "content" in (error as any).error
574
+ ) {
575
+ contentMessage = (error as any).error.code;
576
+ }
577
+ const accountErrorNotification: Notification = {
578
+ type: "error",
579
+ subtype: "account-deletion-error",
580
+ date: Date.now().toString(),
581
+ info_content: {
582
+ code: (error as any).error.code,
583
+ message: (error as any).error.content,
584
+ },
585
+ status: "unread",
586
+ callToAction: false,
587
+ data: {
588
+ account: account.name,
589
+ tenant: account.tenant,
590
+ },
591
+ };
592
+ eventHelper.notification.publish.creation(accountErrorNotification);
593
+ throw error;
594
+ }
595
+ };
596
+
597
+ export const clearAccount = async (account: Account, security: Security) => {
598
+ try {
599
+ await initializeGlobalWebSocketClient(security, "account", account.name);
600
+ const payload = {
601
+ tenant: account.tenant,
602
+ account: account.name,
603
+ delete: false,
604
+ force: false,
605
+ };
606
+
607
+ const response = await makeGlobalWebSocketRequest(
608
+ "account:cleanup_account",
609
+ payload,
610
+ 30000,
611
+ "CLEANUP",
612
+ account.name,
613
+ "account",
614
+ account
615
+ );
616
+
617
+ const updatedAccount: Account = { ...account, status: "pending" };
618
+ eventHelper.account.publish.cleaned(updatedAccount);
619
+ const accountNotification: Notification = {
620
+ type: "success",
621
+ subtype: "account-cleaned",
622
+ date: Date.now().toString(),
623
+ status: "unread",
624
+ callToAction: false,
625
+ data: {
626
+ account: account.name,
627
+ tenant: account.tenant,
628
+ },
629
+ };
630
+ eventHelper.notification.publish.creation(accountNotification);
631
+ return response;
632
+ } catch (error) {
633
+ eventHelper.account.publish.cleanError(account);
634
+ let contentMessage = "Unknown error";
635
+
636
+ if (
637
+ typeof error === "object" &&
638
+ error !== null &&
639
+ "error" in error &&
640
+ typeof (error as any).error === "object" &&
641
+ (error as any).error !== null &&
642
+ "content" in (error as any).error
643
+ ) {
644
+ contentMessage = (error as any).error.code;
645
+ }
646
+ const accountErrorNotification: Notification = {
647
+ type: "error",
648
+ subtype: "account-clean-error",
649
+ date: Date.now().toString(),
650
+ info_content: {
651
+ code: contentMessage,
652
+ message: (error as any).error.content,
653
+ },
654
+ status: "unread",
655
+ callToAction: false,
656
+ data: {
657
+ account: account.name,
658
+ tenant: account.tenant,
659
+ },
660
+ };
661
+ eventHelper.notification.publish.creation(accountErrorNotification);
662
+ throw error;
663
+ }
664
+ };
665
+
666
+ export const updateAccount = async (account: Account, security: Security) => {
667
+ try {
668
+ await initializeGlobalWebSocketClient(security, "account", account.name);
669
+ const providerName = account.cloudProvider?.name?.toLowerCase();
670
+
671
+ let accountBody;
672
+
673
+ if (providerName === "aws") {
674
+ accountBody = {
675
+ tenant: account.tenant,
676
+ account: account.name,
677
+ provision_infrastructure: false,
678
+ spec: {
679
+ api: "aws",
680
+ credentials: account.cloudProvider.password
681
+ ? {
682
+ admin_access_key: account.cloudProvider.username || "",
683
+ admin_secret_key: account.cloudProvider.password || "",
684
+ region: account.cloudProvider?.region || "",
685
+ }
686
+ : {
687
+ method: "aws",
688
+ aws: {
689
+ region: account.cloudProvider?.region || "",
690
+ aws_access_key_id: account.cloudProvider?.credentialId || "",
691
+ aws_secret_access_key:
692
+ account.cloudProvider?.credentialSecret || "",
693
+ },
694
+ },
695
+ marks: {
696
+ vcpu: {
697
+ lowmark: account.usage.limit.cpu.min * 1000,
698
+ highmark: account.usage.limit.cpu.max * 1000,
699
+ unit: "m",
700
+ },
701
+ memory: {
702
+ lowmark: account.usage.limit.memory.min * 1000,
703
+ highmark: account.usage.limit.memory.max * 1000,
704
+ unit: "MB",
705
+ },
706
+ vstorage: {
707
+ lowmark: account.usage.limit.volatileStorage.min * 1000,
708
+ highmark: account.usage.limit.volatileStorage.max * 1000,
709
+ unit: "MB",
710
+ },
711
+ nrstorage: {
712
+ lowmark: account.usage.limit.nonReplicatedStorage.min * 1000,
713
+ highmark: account.usage.limit.nonReplicatedStorage.max * 1000,
714
+ unit: "MB",
715
+ },
716
+ rstorage: {
717
+ lowmark: account.usage.limit.persistentStorage.min * 1000,
718
+ highmark: account.usage.limit.persistentStorage.max * 1000,
719
+ unit: "MB",
720
+ },
721
+ storage: {
722
+ lowmark: account.usage.limit.storage.min * 1000,
723
+ highmark: account.usage.limit.storage.max * 1000,
724
+ unit: "MB",
725
+ },
726
+ cost: {
727
+ lowmark: account.usage.cost,
728
+ highmark: account.usage.cost,
729
+ unit: "EUR",
730
+ },
731
+ nodes: {
732
+ lowmark: account.nodes?.max || 0, // TODO: Support the min input on the wui, for now it will be the same.
733
+ highmark: account.nodes?.max || 0,
734
+ unit: "",
735
+ },
736
+ },
737
+ iaasconfig: {
738
+ ...(account.flavors?.volatile?.[0] && { volatile: account.flavors.volatile[0] }),
739
+ ...(account.flavors?.persistent?.[0] && { persistent: account.flavors.persistent[0] }),
740
+ ...(account.flavors?.nonReplicated?.[0] && { nonreplicated: account.flavors.nonReplicated[0] }),
741
+ // shared: "classic",
742
+ ...(account.flavors?.small?.[0] && { smallVMFlavor: account.flavors?.small?.[0] }),
743
+ ...(account.flavors?.medium?.[0] && { mediumVMFlavor: account.flavors.medium[0] }),
744
+ // ...(account.flavors?.large?.[0] && { largeVMFlavor: account.flavors.large[0] }),
745
+ }
746
+ },
747
+ meta: {
748
+ labels: {
749
+ additionalProp1: "string",
750
+ additionalProp2: "string",
751
+ additionalProp3: "string",
752
+ },
753
+ },
754
+ };
755
+ } else if (providerName === "azure") {
756
+ accountBody = {
757
+ tenant: account.tenant,
758
+ account: account.name,
759
+ provision_infrastructure: false,
760
+ spec: {
761
+ api: "azure",
762
+ credentials: account.cloudProvider.password
763
+ ? {
764
+ tenant_id: account.cloudProvider.tenantId || "",
765
+ admin_client_id: account.cloudProvider.username || "",
766
+ admin_client_secret: account.cloudProvider.password || "",
767
+ subscription_id: account.cloudProvider.subscriptionId || "",
768
+ region: account.cloudProvider?.region || "",
769
+ }
770
+ : {
771
+ method: "azure",
772
+ azure: {
773
+ region: account.cloudProvider?.region || "",
774
+ subscription_id: account.cloudProvider?.subscriptionId || "",
775
+ tenant_id: account.cloudProvider?.tenantId || "",
776
+ client_id: account.cloudProvider?.clientId || "",
777
+ client_secret: account.cloudProvider?.clientSecret || "",
778
+ },
779
+ },
780
+ marks: {
781
+ vcpu: {
782
+ lowmark: account.usage.limit.cpu.min * 1000,
783
+ highmark: account.usage.limit.cpu.max * 1000,
784
+ unit: "m",
785
+ },
786
+ memory: {
787
+ lowmark: account.usage.limit.memory.min * 1000,
788
+ highmark: account.usage.limit.memory.max * 1000,
789
+ unit: "MB",
790
+ },
791
+ vstorage: {
792
+ lowmark: account.usage.limit.volatileStorage.min * 1000,
793
+ highmark: account.usage.limit.volatileStorage.max * 1000,
794
+ unit: "MB",
795
+ },
796
+ nrstorage: {
797
+ lowmark: account.usage.limit.nonReplicatedStorage.min * 1000,
798
+ highmark: account.usage.limit.nonReplicatedStorage.max * 1000,
799
+ unit: "MB",
800
+ },
801
+ rstorage: {
802
+ lowmark: account.usage.limit.persistentStorage.min * 1000,
803
+ highmark: account.usage.limit.persistentStorage.max * 1000,
804
+ unit: "MB",
805
+ },
806
+ storage: {
807
+ lowmark: account.usage.limit.storage.min * 1000,
808
+ highmark: account.usage.limit.storage.max * 1000,
809
+ unit: "MB",
810
+ },
811
+ cost: {
812
+ lowmark: account.usage.cost,
813
+ highmark: account.usage.cost,
814
+ unit: "EUR",
815
+ },
816
+ nodes: {
817
+ lowmark: account.nodes?.min || 0,
818
+ highmark: account.nodes?.max || 0,
819
+ unit: "",
820
+ },
821
+ },
822
+ iaasconfig: {
823
+ ...(account.flavors?.volatile?.[0] && { volatile: account.flavors.volatile[0] }),
824
+ ...(account.flavors?.persistent?.[0] && { persistent: account.flavors.persistent[0] }),
825
+ ...(account.flavors?.nonReplicated?.[0] && { nonreplicated: account.flavors.nonReplicated[0] }),
826
+ // shared: "classic",
827
+ ...(account.flavors?.small?.[0] && { smallVMFlavor: account.flavors?.small?.[0] }),
828
+ ...(account.flavors?.medium?.[0] && { mediumVMFlavor: account.flavors.medium[0] }),
829
+ // ...(account.flavors?.large?.[0] && { largeVMFlavor: account.flavors.large[0] }),
830
+ }
831
+ },
832
+ meta: {
833
+ labels: {
834
+ additionalProp1: "string",
835
+ additionalProp2: "string",
836
+ additionalProp3: "string",
837
+ },
838
+ },
839
+ };
840
+ } else if (providerName === "ovh") {
841
+ accountBody = {
842
+ tenant: account.tenant,
843
+ account: account.name,
844
+ provision_infrastructure: false,
845
+ spec: {
846
+ api: providerName,
847
+ credentials: account.cloudProvider.password
848
+ ? {
849
+ username: account.cloudProvider.username || "",
850
+ password: account.cloudProvider.password || "",
851
+ region: account.cloudProvider?.region || "",
852
+ }
853
+ : {
854
+ method: providerName,
855
+ // ovh: {
856
+ // endpoint: "string",
857
+ // application_key: "string",
858
+ // application_secret: "string",
859
+ // consumer_key: "string",
860
+ // },
861
+ openstack: {
862
+ region_name: account.cloudProvider?.region || "",
863
+ interface: account.cloudProvider?.interface || "",
864
+ identity_api_version: Number(
865
+ account.cloudProvider?.apiVersion || 3
866
+ ),
867
+ auth_type: account.cloudProvider?.authType || "",
868
+ auth: {
869
+ auth_url: account.cloudProvider?.authUrl || "",
870
+ application_credential_id:
871
+ account.cloudProvider?.credentialId || "",
872
+ application_credential_secret:
873
+ account.cloudProvider?.credentialSecret || "",
874
+ },
875
+ },
876
+ },
877
+ highlyAvailable: true,
878
+ marks: {
879
+ vcpu: {
880
+ lowmark: account.usage.limit.cpu.min * 1000,
881
+ highmark: account.usage.limit.cpu.max * 1000,
882
+ unit: "m",
883
+ },
884
+ memory: {
885
+ lowmark: account.usage.limit.memory.min * 1000,
886
+ highmark: account.usage.limit.memory.max * 1000,
887
+ unit: "MB",
888
+ },
889
+ vstorage: {
890
+ lowmark: account.usage.limit.volatileStorage.min * 1000,
891
+ highmark: account.usage.limit.volatileStorage.max * 1000,
892
+ unit: "MB",
893
+ },
894
+ nrstorage: {
895
+ lowmark: account.usage.limit.nonReplicatedStorage.min * 1000,
896
+ highmark: account.usage.limit.nonReplicatedStorage.max * 1000,
897
+ unit: "MB",
898
+ },
899
+ rstorage: {
900
+ lowmark: account.usage.limit.persistentStorage.min * 1000,
901
+ highmark: account.usage.limit.persistentStorage.max * 1000,
902
+ unit: "MB",
903
+ },
904
+ storage: {
905
+ lowmark: account.usage.limit.storage.min * 1000,
906
+ highmark: account.usage.limit.storage.max * 1000,
907
+ unit: "MB",
908
+ },
909
+ cost: {
910
+ lowmark: account.usage.cost,
911
+ highmark: account.usage.cost,
912
+ unit: "EUR",
913
+ },
914
+ nodes: {
915
+ lowmark: account.nodes?.min || 0,
916
+ highmark: account.nodes?.max || 0,
917
+ unit: "",
918
+ },
919
+ },
920
+ iaasconfig: {
921
+ ...(account.flavors?.volatile?.[0] && { volatile: account.flavors.volatile[0] }),
922
+ ...(account.flavors?.persistent?.[0] && { persistent: account.flavors.persistent[0] }),
923
+ ...(account.flavors?.nonReplicated?.[0] && { nonreplicated: account.flavors.nonReplicated[0] }),
924
+ // shared: "classic",
925
+ ...(account.flavors?.small?.[0] && { smallVMFlavor: account.flavors?.small?.[0] }),
926
+ ...(account.flavors?.medium?.[0] && { mediumVMFlavor: account.flavors.medium[0] }),
927
+ // ...(account.flavors?.large?.[0] && { largeVMFlavor: account.flavors.large[0] }),
928
+ }
929
+ },
930
+ meta: {
931
+ labels: {
932
+ additionalProp1: "string",
933
+ additionalProp2: "string",
934
+ additionalProp3: "string",
935
+ },
936
+ },
937
+ };
938
+ } else if (providerName === "oasix") {
939
+ accountBody = {
940
+ tenant: account.tenant,
941
+ account: account.name,
942
+ provision_infrastructure: false,
943
+ spec: {
944
+ api: providerName,
945
+ credentials: account.cloudProvider.password
946
+ ? {
947
+ username: account.cloudProvider.username || "",
948
+ password: account.cloudProvider.password || "",
949
+ region: account.cloudProvider?.region || "",
950
+ domain: account.cloudProvider?.domain || "",
951
+ }
952
+ : {
953
+ method: providerName,
954
+ // ovh: {
955
+ // endpoint: "string",
956
+ // application_key: "string",
957
+ // application_secret: "string",
958
+ // consumer_key: "string",
959
+ // },
960
+ openstack: {
961
+ region_name: account.cloudProvider?.region || "",
962
+ interface: account.cloudProvider?.interface || "",
963
+ identity_api_version: Number(
964
+ account.cloudProvider?.apiVersion || 3
965
+ ),
966
+ auth_type: account.cloudProvider?.authType || "",
967
+ auth: {
968
+ auth_url: account.cloudProvider?.authUrl || "",
969
+ application_credential_id:
970
+ account.cloudProvider?.credentialId || "",
971
+ application_credential_secret:
972
+ account.cloudProvider?.credentialSecret || "",
973
+ },
974
+ },
975
+ },
976
+ highlyAvailable: true,
977
+ marks: {
978
+ vcpu: {
979
+ lowmark: account.usage.limit.cpu.min * 1000,
980
+ highmark: account.usage.limit.cpu.max * 1000,
981
+ unit: "m",
982
+ },
983
+ memory: {
984
+ lowmark: account.usage.limit.memory.min * 1000,
985
+ highmark: account.usage.limit.memory.max * 1000,
986
+ unit: "MB",
987
+ },
988
+ vstorage: {
989
+ lowmark: account.usage.limit.volatileStorage.min * 1000,
990
+ highmark: account.usage.limit.volatileStorage.max * 1000,
991
+ unit: "MB",
992
+ },
993
+ nrstorage: {
994
+ lowmark: account.usage.limit.nonReplicatedStorage.min * 1000,
995
+ highmark: account.usage.limit.nonReplicatedStorage.max * 1000,
996
+ unit: "MB",
997
+ },
998
+ rstorage: {
999
+ lowmark: account.usage.limit.persistentStorage.min * 1000,
1000
+ highmark: account.usage.limit.persistentStorage.max * 1000,
1001
+ unit: "MB",
1002
+ },
1003
+ storage: {
1004
+ lowmark: account.usage.limit.storage.min * 1000,
1005
+ highmark: account.usage.limit.storage.max * 1000,
1006
+ unit: "MB",
1007
+ },
1008
+ cost: {
1009
+ lowmark: account.usage.cost,
1010
+ highmark: account.usage.cost,
1011
+ unit: "EUR",
1012
+ },
1013
+ nodes: {
1014
+ lowmark: account.nodes?.min || 0,
1015
+ highmark: account.nodes?.max || 0,
1016
+ unit: "",
1017
+ },
1018
+ },
1019
+ iaasconfig: {
1020
+ ...(account.flavors?.volatile?.[0] && { volatile: account.flavors.volatile[0] }),
1021
+ ...(account.flavors?.persistent?.[0] && { persistent: account.flavors.persistent[0] }),
1022
+ ...(account.flavors?.nonReplicated?.[0] && { nonreplicated: account.flavors.nonReplicated[0] }),
1023
+ // shared: "classic",
1024
+ ...(account.flavors?.small?.[0] && { smallVMFlavor: account.flavors?.small?.[0] }),
1025
+ ...(account.flavors?.medium?.[0] && { mediumVMFlavor: account.flavors.medium[0] }),
1026
+ // ...(account.flavors?.large?.[0] && { largeVMFlavor: account.flavors.large[0] }),
1027
+ }
1028
+ },
1029
+ meta: {
1030
+ labels: {
1031
+ additionalProp1: "string",
1032
+ additionalProp2: "string",
1033
+ additionalProp3: "string",
1034
+ },
1035
+ },
1036
+ };
1037
+ } else {
1038
+ throw new Error(
1039
+ `Unsupported cloud provider: ${providerName}. Supported providers are: ovh, aws, azure`
1040
+ );
1041
+ }
1042
+
1043
+ const response = await makeGlobalWebSocketRequest(
1044
+ "account:update_account",
1045
+ accountBody,
1046
+ 30000,
1047
+ "UPDATE",
1048
+ account.name,
1049
+ "account",
1050
+ account
1051
+ );
1052
+ return response;
1053
+ } catch (error) {
1054
+ console.error("Error updating account:", {
1055
+ error,
1056
+ errorMessage: error instanceof Error ? error.message : "Unknown error",
1057
+ account: account.name,
1058
+ tenant: account.tenant,
1059
+ provider: account.cloudProvider?.name,
1060
+ });
1061
+ eventHelper.account.publish.updateError(account);
1062
+ let contentMessage = "Unknown error";
1063
+
1064
+ if (
1065
+ typeof error === "object" &&
1066
+ error !== null &&
1067
+ "error" in error &&
1068
+ typeof (error as any).error === "object" &&
1069
+ (error as any).error !== null &&
1070
+ "content" in (error as any).error
1071
+ ) {
1072
+ contentMessage = (error as any).error.code;
1073
+ }
1074
+ const accountErrorNotification: Notification = {
1075
+ type: "error",
1076
+ subtype: "account-update-error",
1077
+ date: Date.now().toString(),
1078
+ info_content: {
1079
+ code: contentMessage,
1080
+ message: (error as any).error.content,
1081
+ },
1082
+ status: "unread",
1083
+ callToAction: false,
1084
+ data: {
1085
+ account: account.name,
1086
+ tenant: account.tenant,
1087
+ },
1088
+ };
1089
+ eventHelper.notification.publish.creation(accountErrorNotification);
1090
+ throw error;
1091
+ }
1092
+ };