@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.
- package/.gitlab-ci.yml +57 -0
- package/README.md +352 -0
- package/api/account-api-service.ts +1092 -0
- package/api/deploy-service-helper.ts +1611 -0
- package/api/environment-api-service.ts +542 -0
- package/api/marketplace-api-service.ts +1031 -0
- package/api/organizations-api-service.ts +0 -0
- package/api/planProvider-api-service.ts +24 -0
- package/api/reporting-api-service.ts +35 -0
- package/api/resources-api-service.ts +821 -0
- package/api/service-api-service.ts +796 -0
- package/api/tenant-api-service.ts +1260 -0
- package/api/user-api-service.ts +1161 -0
- package/backend-handler.ts +1127 -0
- package/environment.ts +7 -0
- package/event-helper.ts +577 -0
- package/event-names.ts +152 -0
- package/helpers/account-helper.ts +331 -0
- package/helpers/environment-helper.ts +289 -0
- package/helpers/link-helper.ts +114 -0
- package/helpers/plan-helper.ts +104 -0
- package/helpers/registry-helper.ts +134 -0
- package/helpers/resource-helper.ts +387 -0
- package/helpers/revision-helper.ts +899 -0
- package/helpers/service-helper.ts +627 -0
- package/helpers/tenant-helper.ts +191 -0
- package/helpers/token-helper.ts +107 -0
- package/helpers/user-helper.ts +140 -0
- package/jest.config.ts +40 -0
- package/jest.setup.js +4 -0
- package/package.json +50 -0
- package/test/backend-handler.test.ts +792 -0
- package/test/deploy-service-helper.test.ts +518 -0
- package/test/event-helper.test.ts +152 -0
- package/tsconfig.json +26 -0
- package/utils/utils.ts +78 -0
- package/websocket-manager.ts +1833 -0
|
@@ -0,0 +1,821 @@
|
|
|
1
|
+
import { Notification, Resource } from "@hestekumori/aurora-interfaces";
|
|
2
|
+
import { eventHelper } from "../backend-handler";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
initializeGlobalWebSocketClient,
|
|
6
|
+
getWebSocketStatus,
|
|
7
|
+
makeGlobalWebSocketRequest,
|
|
8
|
+
} from "../websocket-manager";
|
|
9
|
+
|
|
10
|
+
const createResourceBody = (
|
|
11
|
+
tenant: string,
|
|
12
|
+
resource: Resource,
|
|
13
|
+
kind: string,
|
|
14
|
+
data: any
|
|
15
|
+
) => ({
|
|
16
|
+
tenant,
|
|
17
|
+
resource: resource.name,
|
|
18
|
+
kind,
|
|
19
|
+
spec: {
|
|
20
|
+
kind,
|
|
21
|
+
data,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const createDomain = async (
|
|
26
|
+
tenant: string,
|
|
27
|
+
domain: Resource,
|
|
28
|
+
security: string
|
|
29
|
+
) => {
|
|
30
|
+
try {
|
|
31
|
+
await initializeGlobalWebSocketClient(security);
|
|
32
|
+
const status = getWebSocketStatus();
|
|
33
|
+
|
|
34
|
+
const domainBody = createResourceBody(tenant, domain, "domain", {
|
|
35
|
+
domain: domain.value,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const response = await makeGlobalWebSocketRequest(
|
|
39
|
+
"resource:create_resource",
|
|
40
|
+
domainBody,
|
|
41
|
+
30000,
|
|
42
|
+
"CREATE",
|
|
43
|
+
domain.name
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// eventHelper.resource.publish.created(domain);
|
|
47
|
+
const resourceNotification: Notification = {
|
|
48
|
+
type: "success",
|
|
49
|
+
subtype: "resource-created",
|
|
50
|
+
date: Date.now().toString(),
|
|
51
|
+
status: "unread",
|
|
52
|
+
callToAction: false,
|
|
53
|
+
data: {
|
|
54
|
+
resource: domain.name,
|
|
55
|
+
tenant: tenant
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
eventHelper.notification.publish.creation(resourceNotification);
|
|
59
|
+
return response;
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error("Error creating domain:", {
|
|
62
|
+
error,
|
|
63
|
+
tenant,
|
|
64
|
+
domain,
|
|
65
|
+
webSocketStatus: getWebSocketStatus(),
|
|
66
|
+
});
|
|
67
|
+
let contentMessage = "Unknown error";
|
|
68
|
+
let errorContent = "Unknown error";
|
|
69
|
+
|
|
70
|
+
if (
|
|
71
|
+
typeof error === "object" &&
|
|
72
|
+
error !== null &&
|
|
73
|
+
"error" in error &&
|
|
74
|
+
typeof (error as any).error === "object" &&
|
|
75
|
+
(error as any).error !== null
|
|
76
|
+
) {
|
|
77
|
+
if ("code" in (error as any).error) {
|
|
78
|
+
contentMessage = (error as any).error.code;
|
|
79
|
+
}
|
|
80
|
+
if ("content" in (error as any).error) {
|
|
81
|
+
errorContent = (error as any).error.content;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const resourceErrorNotification: Notification = {
|
|
85
|
+
type: "error",
|
|
86
|
+
subtype: "resource-creation-error",
|
|
87
|
+
info_content: {
|
|
88
|
+
code: contentMessage,
|
|
89
|
+
message: errorContent,
|
|
90
|
+
},
|
|
91
|
+
date: Date.now().toString(),
|
|
92
|
+
status: "unread",
|
|
93
|
+
callToAction: false,
|
|
94
|
+
data: {
|
|
95
|
+
resource: domain.name,
|
|
96
|
+
tenant: tenant
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export const createPort = async (
|
|
105
|
+
tenant: string,
|
|
106
|
+
port: Resource,
|
|
107
|
+
security: string
|
|
108
|
+
) => {
|
|
109
|
+
try {
|
|
110
|
+
await initializeGlobalWebSocketClient(security);
|
|
111
|
+
const status = getWebSocketStatus();
|
|
112
|
+
|
|
113
|
+
const portBody = createResourceBody(tenant, port, "port", {
|
|
114
|
+
port: Number(port.value),
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const response = await makeGlobalWebSocketRequest(
|
|
118
|
+
"resource:create_resource",
|
|
119
|
+
portBody,
|
|
120
|
+
30000,
|
|
121
|
+
"CREATE",
|
|
122
|
+
port.name
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
eventHelper.resource.publish.created(port);
|
|
126
|
+
const resourceNotification: Notification = {
|
|
127
|
+
type: "success",
|
|
128
|
+
subtype: "resource-created",
|
|
129
|
+
date: Date.now().toString(),
|
|
130
|
+
status: "unread",
|
|
131
|
+
callToAction: false,
|
|
132
|
+
data: {
|
|
133
|
+
resource: port.name,
|
|
134
|
+
tenant: tenant
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
eventHelper.notification.publish.creation(resourceNotification);
|
|
138
|
+
return response;
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.error("Error creating port:", {
|
|
141
|
+
error,
|
|
142
|
+
tenant,
|
|
143
|
+
port,
|
|
144
|
+
webSocketStatus: getWebSocketStatus(),
|
|
145
|
+
});
|
|
146
|
+
let contentMessage = "Unknown error";
|
|
147
|
+
let errorContent = "Unknown error";
|
|
148
|
+
|
|
149
|
+
if (
|
|
150
|
+
typeof error === "object" &&
|
|
151
|
+
error !== null &&
|
|
152
|
+
"error" in error &&
|
|
153
|
+
typeof (error as any).error === "object" &&
|
|
154
|
+
(error as any).error !== null
|
|
155
|
+
) {
|
|
156
|
+
if ("code" in (error as any).error) {
|
|
157
|
+
contentMessage = (error as any).error.code;
|
|
158
|
+
}
|
|
159
|
+
if ("content" in (error as any).error) {
|
|
160
|
+
errorContent = (error as any).error.content;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const resourceErrorNotification: Notification = {
|
|
164
|
+
type: "error",
|
|
165
|
+
subtype: "resource-creation-error",
|
|
166
|
+
info_content: {
|
|
167
|
+
code: contentMessage,
|
|
168
|
+
message: errorContent,
|
|
169
|
+
},
|
|
170
|
+
date: Date.now().toString(),
|
|
171
|
+
status: "unread",
|
|
172
|
+
callToAction: false,
|
|
173
|
+
data: {
|
|
174
|
+
resource: port.name,
|
|
175
|
+
tenant: tenant
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export const createCA = async (
|
|
184
|
+
tenant: string,
|
|
185
|
+
ca: Resource,
|
|
186
|
+
security: string
|
|
187
|
+
) => {
|
|
188
|
+
try {
|
|
189
|
+
await initializeGlobalWebSocketClient(security);
|
|
190
|
+
const status = getWebSocketStatus();
|
|
191
|
+
|
|
192
|
+
const caBody = createResourceBody(tenant, ca, "ca", {
|
|
193
|
+
ca: ca.value,
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
const response = await makeGlobalWebSocketRequest(
|
|
197
|
+
"resource:create_resource",
|
|
198
|
+
caBody,
|
|
199
|
+
30000,
|
|
200
|
+
"CREATE",
|
|
201
|
+
ca.name
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
eventHelper.resource.publish.created(ca);
|
|
205
|
+
const resourceNotification: Notification = {
|
|
206
|
+
type: "success",
|
|
207
|
+
subtype: "resource-created",
|
|
208
|
+
date: Date.now().toString(),
|
|
209
|
+
status: "unread",
|
|
210
|
+
callToAction: false,
|
|
211
|
+
data: {
|
|
212
|
+
resource: ca.name,
|
|
213
|
+
tenant: tenant
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
eventHelper.notification.publish.creation(resourceNotification);
|
|
217
|
+
return response;
|
|
218
|
+
} catch (error) {
|
|
219
|
+
console.error("Error creating CA:", {
|
|
220
|
+
error,
|
|
221
|
+
tenant,
|
|
222
|
+
ca,
|
|
223
|
+
webSocketStatus: getWebSocketStatus(),
|
|
224
|
+
});
|
|
225
|
+
let contentMessage = "Unknown error";
|
|
226
|
+
let errorContent = "Unknown error";
|
|
227
|
+
|
|
228
|
+
if (
|
|
229
|
+
typeof error === "object" &&
|
|
230
|
+
error !== null &&
|
|
231
|
+
"error" in error &&
|
|
232
|
+
typeof (error as any).error === "object" &&
|
|
233
|
+
(error as any).error !== null
|
|
234
|
+
) {
|
|
235
|
+
if ("code" in (error as any).error) {
|
|
236
|
+
contentMessage = (error as any).error.code;
|
|
237
|
+
}
|
|
238
|
+
if ("content" in (error as any).error) {
|
|
239
|
+
errorContent = (error as any).error.content;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
const resourceErrorNotification: Notification = {
|
|
243
|
+
type: "error",
|
|
244
|
+
subtype: "resource-creation-error",
|
|
245
|
+
info_content: {
|
|
246
|
+
code: contentMessage,
|
|
247
|
+
message: errorContent,
|
|
248
|
+
},
|
|
249
|
+
date: Date.now().toString(),
|
|
250
|
+
status: "unread",
|
|
251
|
+
callToAction: false,
|
|
252
|
+
data: {
|
|
253
|
+
resource: ca.name,
|
|
254
|
+
tenant: tenant
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
258
|
+
throw error;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
export const createCertificate = async (
|
|
263
|
+
tenant: string,
|
|
264
|
+
certificate: Resource,
|
|
265
|
+
security: string
|
|
266
|
+
) => {
|
|
267
|
+
try {
|
|
268
|
+
await initializeGlobalWebSocketClient(security);
|
|
269
|
+
const status = getWebSocketStatus();
|
|
270
|
+
|
|
271
|
+
if (!certificate.key || !certificate.domain) {
|
|
272
|
+
throw new Error("Certificate requires both key and domain properties");
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const certificateBody = createResourceBody(
|
|
276
|
+
tenant,
|
|
277
|
+
certificate,
|
|
278
|
+
"certificate",
|
|
279
|
+
{
|
|
280
|
+
certificate: {
|
|
281
|
+
cert: certificate.value,
|
|
282
|
+
key: certificate.key,
|
|
283
|
+
domain: certificate.domain,
|
|
284
|
+
},
|
|
285
|
+
}
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
const response = await makeGlobalWebSocketRequest(
|
|
289
|
+
"resource:create_resource",
|
|
290
|
+
certificateBody,
|
|
291
|
+
30000,
|
|
292
|
+
"CREATE",
|
|
293
|
+
certificate.name
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
eventHelper.resource.publish.created(certificate);
|
|
297
|
+
const resourceNotification: Notification = {
|
|
298
|
+
type: "success",
|
|
299
|
+
subtype: "resource-created",
|
|
300
|
+
date: Date.now().toString(),
|
|
301
|
+
status: "unread",
|
|
302
|
+
callToAction: false,
|
|
303
|
+
data: {
|
|
304
|
+
resource: certificate.name,
|
|
305
|
+
tenant: tenant
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
eventHelper.notification.publish.creation(resourceNotification);
|
|
309
|
+
return response;
|
|
310
|
+
} catch (error) {
|
|
311
|
+
console.error("Error creating certificate:", {
|
|
312
|
+
error,
|
|
313
|
+
tenant,
|
|
314
|
+
certificate,
|
|
315
|
+
webSocketStatus: getWebSocketStatus(),
|
|
316
|
+
});
|
|
317
|
+
let contentMessage = "Unknown error";
|
|
318
|
+
let errorContent = "Unknown error";
|
|
319
|
+
|
|
320
|
+
if (
|
|
321
|
+
typeof error === "object" &&
|
|
322
|
+
error !== null &&
|
|
323
|
+
"error" in error &&
|
|
324
|
+
typeof (error as any).error === "object" &&
|
|
325
|
+
(error as any).error !== null
|
|
326
|
+
) {
|
|
327
|
+
if ("code" in (error as any).error) {
|
|
328
|
+
contentMessage = (error as any).error.code;
|
|
329
|
+
}
|
|
330
|
+
if ("content" in (error as any).error) {
|
|
331
|
+
errorContent = (error as any).error.content;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
const resourceErrorNotification: Notification = {
|
|
335
|
+
type: "error",
|
|
336
|
+
subtype: "resource-creation-error",
|
|
337
|
+
info_content: {
|
|
338
|
+
code: contentMessage,
|
|
339
|
+
message: errorContent,
|
|
340
|
+
},
|
|
341
|
+
date: Date.now().toString(),
|
|
342
|
+
status: "unread",
|
|
343
|
+
callToAction: false,
|
|
344
|
+
data: {
|
|
345
|
+
resource: certificate.name,
|
|
346
|
+
tenant: tenant
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
350
|
+
throw error;
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
export const createSecret = async (
|
|
355
|
+
tenant: string,
|
|
356
|
+
secret: Resource,
|
|
357
|
+
security: string
|
|
358
|
+
) => {
|
|
359
|
+
try {
|
|
360
|
+
await initializeGlobalWebSocketClient(security);
|
|
361
|
+
const status = getWebSocketStatus();
|
|
362
|
+
|
|
363
|
+
const secretBody = createResourceBody(tenant, secret, "secret", {
|
|
364
|
+
secret: secret.value,
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
const response = await makeGlobalWebSocketRequest(
|
|
368
|
+
"resource:create_resource",
|
|
369
|
+
secretBody,
|
|
370
|
+
30000,
|
|
371
|
+
"CREATE",
|
|
372
|
+
secret.name
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
eventHelper.resource.publish.created(secret);
|
|
376
|
+
const resourceNotification: Notification = {
|
|
377
|
+
type: "success",
|
|
378
|
+
subtype: "resource-created",
|
|
379
|
+
date: Date.now().toString(),
|
|
380
|
+
status: "unread",
|
|
381
|
+
callToAction: false,
|
|
382
|
+
data: {
|
|
383
|
+
resource: secret.name,
|
|
384
|
+
tenant: tenant
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
eventHelper.notification.publish.creation(resourceNotification);
|
|
388
|
+
return response;
|
|
389
|
+
} catch (error) {
|
|
390
|
+
console.error("Error creating secret:", {
|
|
391
|
+
error,
|
|
392
|
+
tenant,
|
|
393
|
+
secret,
|
|
394
|
+
webSocketStatus: getWebSocketStatus(),
|
|
395
|
+
});
|
|
396
|
+
let contentMessage = "Unknown error";
|
|
397
|
+
let errorContent = "Unknown error";
|
|
398
|
+
|
|
399
|
+
if (
|
|
400
|
+
typeof error === "object" &&
|
|
401
|
+
error !== null &&
|
|
402
|
+
"error" in error &&
|
|
403
|
+
typeof (error as any).error === "object" &&
|
|
404
|
+
(error as any).error !== null
|
|
405
|
+
) {
|
|
406
|
+
if ("code" in (error as any).error) {
|
|
407
|
+
contentMessage = (error as any).error.code;
|
|
408
|
+
}
|
|
409
|
+
if ("content" in (error as any).error) {
|
|
410
|
+
errorContent = (error as any).error.content;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
const resourceErrorNotification: Notification = {
|
|
414
|
+
type: "error",
|
|
415
|
+
subtype: "resource-creation-error",
|
|
416
|
+
info_content: {
|
|
417
|
+
code: contentMessage,
|
|
418
|
+
message: errorContent,
|
|
419
|
+
},
|
|
420
|
+
date: Date.now().toString(),
|
|
421
|
+
status: "unread",
|
|
422
|
+
callToAction: false,
|
|
423
|
+
data: {
|
|
424
|
+
resource: secret.name,
|
|
425
|
+
tenant: tenant
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
429
|
+
throw error;
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
export const createVolume = async (
|
|
434
|
+
tenant: string,
|
|
435
|
+
volume: Resource,
|
|
436
|
+
security: string
|
|
437
|
+
) => {
|
|
438
|
+
try {
|
|
439
|
+
await initializeGlobalWebSocketClient(security);
|
|
440
|
+
const status = getWebSocketStatus();
|
|
441
|
+
|
|
442
|
+
let volumeKind: "persistent" | "nonreplicated" | "shared" = "persistent";
|
|
443
|
+
if (volume.kind === "nonReplicated") {
|
|
444
|
+
volumeKind = "nonreplicated";
|
|
445
|
+
} else if (volume.kind === "volatile") {
|
|
446
|
+
volumeKind = "persistent";
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
const volumeData: any = {
|
|
450
|
+
volume: {
|
|
451
|
+
kind: volumeKind,
|
|
452
|
+
size: Number(volume.value),
|
|
453
|
+
},
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
if (volume.maxItems !== undefined) {
|
|
457
|
+
volumeData.volume.maxitems = volume.maxItems;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// if (volumeKind === "persistent") {
|
|
461
|
+
// volumeData.volume.options = {};
|
|
462
|
+
// }
|
|
463
|
+
|
|
464
|
+
const volumeBody = createResourceBody(tenant, volume, "volume", volumeData);
|
|
465
|
+
|
|
466
|
+
const response = await makeGlobalWebSocketRequest(
|
|
467
|
+
"resource:create_resource",
|
|
468
|
+
volumeBody,
|
|
469
|
+
30000,
|
|
470
|
+
"CREATE",
|
|
471
|
+
volume.name
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
eventHelper.resource.publish.created(volume);
|
|
475
|
+
const resourceNotification: Notification = {
|
|
476
|
+
type: "success",
|
|
477
|
+
subtype: "resource-created",
|
|
478
|
+
date: Date.now().toString(),
|
|
479
|
+
status: "unread",
|
|
480
|
+
callToAction: false,
|
|
481
|
+
data: {
|
|
482
|
+
resource: volume.name,
|
|
483
|
+
tenant: tenant
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
eventHelper.notification.publish.creation(resourceNotification);
|
|
487
|
+
return response;
|
|
488
|
+
} catch (error) {
|
|
489
|
+
console.error("Error creating volume:", {
|
|
490
|
+
error,
|
|
491
|
+
tenant,
|
|
492
|
+
volume,
|
|
493
|
+
webSocketStatus: getWebSocketStatus(),
|
|
494
|
+
});
|
|
495
|
+
let contentMessage = "Unknown error";
|
|
496
|
+
let errorContent = "Unknown error";
|
|
497
|
+
|
|
498
|
+
if (
|
|
499
|
+
typeof error === "object" &&
|
|
500
|
+
error !== null &&
|
|
501
|
+
"error" in error &&
|
|
502
|
+
typeof (error as any).error === "object" &&
|
|
503
|
+
(error as any).error !== null
|
|
504
|
+
) {
|
|
505
|
+
if ("code" in (error as any).error) {
|
|
506
|
+
contentMessage = (error as any).error.code;
|
|
507
|
+
}
|
|
508
|
+
if ("content" in (error as any).error) {
|
|
509
|
+
errorContent = (error as any).error.content;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
const resourceErrorNotification: Notification = {
|
|
513
|
+
type: "error",
|
|
514
|
+
subtype: "resource-creation-error",
|
|
515
|
+
info_content: {
|
|
516
|
+
code: contentMessage,
|
|
517
|
+
message: errorContent,
|
|
518
|
+
},
|
|
519
|
+
date: Date.now().toString(),
|
|
520
|
+
status: "unread",
|
|
521
|
+
callToAction: false,
|
|
522
|
+
data: {
|
|
523
|
+
resource: volume.name,
|
|
524
|
+
tenant: tenant
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
528
|
+
throw error;
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
export const createResource = async (
|
|
533
|
+
tenant: string,
|
|
534
|
+
resource: Resource,
|
|
535
|
+
security: string
|
|
536
|
+
) => {
|
|
537
|
+
switch (resource.type) {
|
|
538
|
+
case "domain":
|
|
539
|
+
return createDomain(tenant, resource, security);
|
|
540
|
+
case "port":
|
|
541
|
+
return createPort(tenant, resource, security);
|
|
542
|
+
case "ca":
|
|
543
|
+
return createCA(tenant, resource, security);
|
|
544
|
+
case "certificate":
|
|
545
|
+
return createCertificate(tenant, resource, security);
|
|
546
|
+
case "secret":
|
|
547
|
+
return createSecret(tenant, resource, security);
|
|
548
|
+
case "volume":
|
|
549
|
+
return createVolume(tenant, resource, security);
|
|
550
|
+
default:
|
|
551
|
+
throw new Error(`Unsupported resource type: ${resource.type}`);
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
const deleteResourceBody = (
|
|
556
|
+
tenant: string,
|
|
557
|
+
resource: Resource,
|
|
558
|
+
kind: string
|
|
559
|
+
) => ({
|
|
560
|
+
tenant,
|
|
561
|
+
resource: resource.name,
|
|
562
|
+
kind,
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
const deleteResourceBase = async (
|
|
566
|
+
tenant: string,
|
|
567
|
+
resource: Resource,
|
|
568
|
+
kind: string,
|
|
569
|
+
security: string
|
|
570
|
+
) => {
|
|
571
|
+
try {
|
|
572
|
+
await initializeGlobalWebSocketClient(security);
|
|
573
|
+
const body = deleteResourceBody(tenant, resource, kind);
|
|
574
|
+
|
|
575
|
+
const response = await makeGlobalWebSocketRequest(
|
|
576
|
+
"resource:delete_resource",
|
|
577
|
+
body,
|
|
578
|
+
30000,
|
|
579
|
+
"DELETE",
|
|
580
|
+
resource.name
|
|
581
|
+
);
|
|
582
|
+
|
|
583
|
+
//eventHelper.resource.publish.deleted(resource);
|
|
584
|
+
const resourceNotification: Notification = {
|
|
585
|
+
type: "success",
|
|
586
|
+
subtype: "resource-deleted",
|
|
587
|
+
date: Date.now().toString(),
|
|
588
|
+
status: "unread",
|
|
589
|
+
callToAction: false,
|
|
590
|
+
data: {
|
|
591
|
+
resource: resource.name,
|
|
592
|
+
type: resource.type,
|
|
593
|
+
tenant: tenant
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
eventHelper.notification.publish.creation(resourceNotification);
|
|
597
|
+
return response;
|
|
598
|
+
} catch (error) {
|
|
599
|
+
console.error(`Error deleting ${kind}:`, { error, tenant, resource });
|
|
600
|
+
let contentMessage = "Unknown error";
|
|
601
|
+
let errorContent = "Unknown error";
|
|
602
|
+
|
|
603
|
+
if (
|
|
604
|
+
typeof error === "object" &&
|
|
605
|
+
error !== null &&
|
|
606
|
+
"error" in error &&
|
|
607
|
+
typeof (error as any).error === "object" &&
|
|
608
|
+
(error as any).error !== null
|
|
609
|
+
) {
|
|
610
|
+
if ("code" in (error as any).error) {
|
|
611
|
+
contentMessage = (error as any).error.code;
|
|
612
|
+
}
|
|
613
|
+
if ("content" in (error as any).error) {
|
|
614
|
+
errorContent = (error as any).error.content;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
const resourceErrorNotification: Notification = {
|
|
618
|
+
type: "error",
|
|
619
|
+
subtype: "resource-deletion-error",
|
|
620
|
+
info_content: {
|
|
621
|
+
code: contentMessage,
|
|
622
|
+
message: errorContent,
|
|
623
|
+
},
|
|
624
|
+
date: Date.now().toString(),
|
|
625
|
+
status: "unread",
|
|
626
|
+
callToAction: false,
|
|
627
|
+
data: {
|
|
628
|
+
resource: resource.name,
|
|
629
|
+
type: resource.type,
|
|
630
|
+
tenant: tenant
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
634
|
+
throw error;
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
export const deleteResource = async (
|
|
639
|
+
tenant: string,
|
|
640
|
+
resource: Resource,
|
|
641
|
+
security: string
|
|
642
|
+
) => {
|
|
643
|
+
const supportedKinds = [
|
|
644
|
+
"domain",
|
|
645
|
+
"port",
|
|
646
|
+
"ca",
|
|
647
|
+
"certificate",
|
|
648
|
+
"secret",
|
|
649
|
+
"volume",
|
|
650
|
+
];
|
|
651
|
+
if (!supportedKinds.includes(resource.type)) {
|
|
652
|
+
throw new Error(`Unsupported resource type: ${resource.type}`);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
return deleteResourceBase(tenant, resource, resource.type, security);
|
|
656
|
+
};
|
|
657
|
+
|
|
658
|
+
const updateResourceBase = async (
|
|
659
|
+
tenant: string,
|
|
660
|
+
resource: Resource,
|
|
661
|
+
kind: string,
|
|
662
|
+
data: any,
|
|
663
|
+
security: string
|
|
664
|
+
) => {
|
|
665
|
+
try {
|
|
666
|
+
await initializeGlobalWebSocketClient(security);
|
|
667
|
+
const body = createResourceBody(tenant, resource, kind, data);
|
|
668
|
+
|
|
669
|
+
const response = await makeGlobalWebSocketRequest(
|
|
670
|
+
"resource:update_resource",
|
|
671
|
+
body,
|
|
672
|
+
30000,
|
|
673
|
+
"UPDATE",
|
|
674
|
+
resource.name
|
|
675
|
+
);
|
|
676
|
+
|
|
677
|
+
// eventHelper.resource.publish.updated(resource);
|
|
678
|
+
const resourceNotification: Notification = {
|
|
679
|
+
type: "success",
|
|
680
|
+
subtype: "resource-updated",
|
|
681
|
+
date: Date.now().toString(),
|
|
682
|
+
status: "unread",
|
|
683
|
+
callToAction: false,
|
|
684
|
+
data: {
|
|
685
|
+
resource: resource.name,
|
|
686
|
+
type: resource.type,
|
|
687
|
+
tenant: tenant
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
eventHelper.notification.publish.creation(resourceNotification);
|
|
691
|
+
return response;
|
|
692
|
+
} catch (error) {
|
|
693
|
+
console.error(`Error updating ${kind}:`, { error, tenant, resource });
|
|
694
|
+
let contentMessage = "Unknown error";
|
|
695
|
+
let errorContent = "Unknown error";
|
|
696
|
+
|
|
697
|
+
if (
|
|
698
|
+
typeof error === "object" &&
|
|
699
|
+
error !== null &&
|
|
700
|
+
"error" in error &&
|
|
701
|
+
typeof (error as any).error === "object" &&
|
|
702
|
+
(error as any).error !== null
|
|
703
|
+
) {
|
|
704
|
+
if ("code" in (error as any).error) {
|
|
705
|
+
contentMessage = (error as any).error.code;
|
|
706
|
+
}
|
|
707
|
+
if ("content" in (error as any).error) {
|
|
708
|
+
errorContent = (error as any).error.content;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
const resourceErrorNotification: Notification = {
|
|
712
|
+
type: "error",
|
|
713
|
+
subtype: "resource-update-error",
|
|
714
|
+
info_content: {
|
|
715
|
+
code: contentMessage,
|
|
716
|
+
message: errorContent,
|
|
717
|
+
},
|
|
718
|
+
date: Date.now().toString(),
|
|
719
|
+
status: "unread",
|
|
720
|
+
callToAction: false,
|
|
721
|
+
data: {
|
|
722
|
+
resource: resource.name,
|
|
723
|
+
type: resource.type,
|
|
724
|
+
tenant: tenant
|
|
725
|
+
}
|
|
726
|
+
};
|
|
727
|
+
eventHelper.notification.publish.creation(resourceErrorNotification);
|
|
728
|
+
throw error;
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
|
|
732
|
+
export const updateResource = async (
|
|
733
|
+
tenant: string,
|
|
734
|
+
resource: Resource,
|
|
735
|
+
security: string
|
|
736
|
+
) => {
|
|
737
|
+
switch (resource.type) {
|
|
738
|
+
case "domain":
|
|
739
|
+
return updateResourceBase(
|
|
740
|
+
tenant,
|
|
741
|
+
resource,
|
|
742
|
+
"domain",
|
|
743
|
+
{ domain: resource.value },
|
|
744
|
+
security
|
|
745
|
+
);
|
|
746
|
+
case "port":
|
|
747
|
+
return updateResourceBase(
|
|
748
|
+
tenant,
|
|
749
|
+
resource,
|
|
750
|
+
"port",
|
|
751
|
+
{ port: Number(resource.value) },
|
|
752
|
+
security
|
|
753
|
+
);
|
|
754
|
+
case "ca":
|
|
755
|
+
return updateResourceBase(
|
|
756
|
+
tenant,
|
|
757
|
+
resource,
|
|
758
|
+
"ca",
|
|
759
|
+
{ ca: resource.value },
|
|
760
|
+
security
|
|
761
|
+
);
|
|
762
|
+
case "certificate":
|
|
763
|
+
if (!resource.key || !resource.domain) {
|
|
764
|
+
throw new Error("Certificate requires both key and domain");
|
|
765
|
+
}
|
|
766
|
+
return updateResourceBase(
|
|
767
|
+
tenant,
|
|
768
|
+
resource,
|
|
769
|
+
"certificate",
|
|
770
|
+
{
|
|
771
|
+
certificate: {
|
|
772
|
+
cert: resource.value,
|
|
773
|
+
key: resource.key,
|
|
774
|
+
domain: resource.domain,
|
|
775
|
+
},
|
|
776
|
+
},
|
|
777
|
+
security
|
|
778
|
+
);
|
|
779
|
+
case "secret":
|
|
780
|
+
return updateResourceBase(
|
|
781
|
+
tenant,
|
|
782
|
+
resource,
|
|
783
|
+
"secret",
|
|
784
|
+
{ secret: resource.value },
|
|
785
|
+
security
|
|
786
|
+
);
|
|
787
|
+
case "volume":
|
|
788
|
+
let volumeKind: "persistent" | "nonreplicated" | "shared" = "persistent";
|
|
789
|
+
if (resource.kind === "nonReplicated") {
|
|
790
|
+
volumeKind = "nonreplicated";
|
|
791
|
+
} else if (resource.kind === "volatile") {
|
|
792
|
+
volumeKind = "shared";
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
const volumeData: any = {
|
|
796
|
+
volume: {
|
|
797
|
+
kind: volumeKind,
|
|
798
|
+
size: Number(resource.value),
|
|
799
|
+
},
|
|
800
|
+
};
|
|
801
|
+
|
|
802
|
+
if (resource.maxItems !== undefined) {
|
|
803
|
+
volumeData.volume.maxitems = resource.maxItems;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
if (volumeKind === "shared") {
|
|
807
|
+
volumeData.volume.options = {};
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
return updateResourceBase(
|
|
811
|
+
tenant,
|
|
812
|
+
resource,
|
|
813
|
+
"volume",
|
|
814
|
+
volumeData,
|
|
815
|
+
security
|
|
816
|
+
);
|
|
817
|
+
|
|
818
|
+
default:
|
|
819
|
+
throw new Error(`Unsupported resource type: ${resource.type}`);
|
|
820
|
+
}
|
|
821
|
+
};
|