@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,1161 @@
|
|
|
1
|
+
import { eventHelper } from "../backend-handler";
|
|
2
|
+
import {
|
|
3
|
+
initializeGlobalWebSocketClient,
|
|
4
|
+
makeGlobalWebSocketRequest,
|
|
5
|
+
} from "../websocket-manager.ts";
|
|
6
|
+
import { environment } from "../environment.ts";
|
|
7
|
+
import { Account, Container, Environment, Instance, MarketplaceItem, Notification, Organization, Platform, Registry, Resource, Service, Tenant, User, UserData } from "@hestekumori/aurora-interfaces";
|
|
8
|
+
|
|
9
|
+
type Security = string;
|
|
10
|
+
|
|
11
|
+
export const loadUser = async (token: string, previousData: UserData) => {
|
|
12
|
+
try {
|
|
13
|
+
await initializeGlobalWebSocketClient(token, "", "", previousData);
|
|
14
|
+
} catch (error) {
|
|
15
|
+
console.error("Error in loadUser:", {
|
|
16
|
+
error,
|
|
17
|
+
errorMessage: error instanceof Error ? error.message : "Unknown error",
|
|
18
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
19
|
+
});
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const isUserLogged = async (security: Security) => {
|
|
25
|
+
let userLogged = false;
|
|
26
|
+
try {
|
|
27
|
+
await initializeGlobalWebSocketClient(security);
|
|
28
|
+
await makeGlobalWebSocketRequest(
|
|
29
|
+
"user:user_info",
|
|
30
|
+
{},
|
|
31
|
+
30000,
|
|
32
|
+
"GET",
|
|
33
|
+
"USER_INFO"
|
|
34
|
+
);
|
|
35
|
+
userLogged = true;
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.error("User not logged in:", error);
|
|
38
|
+
userLogged = false;
|
|
39
|
+
}
|
|
40
|
+
return userLogged;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const createUser = async (user: User) => {
|
|
44
|
+
const userBody = {
|
|
45
|
+
name: user.name,
|
|
46
|
+
surname: user.surname,
|
|
47
|
+
discoveryMethod: "work",
|
|
48
|
+
companyName: user.companyName,
|
|
49
|
+
companyRole: user.rol,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const response = await fetch(
|
|
53
|
+
`${environment.apiServer.baseUrl}/api/${environment.apiServer.apiVersion}/user`,
|
|
54
|
+
{
|
|
55
|
+
method: "POST",
|
|
56
|
+
body: JSON.stringify(userBody),
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
const error = await response.json();
|
|
62
|
+
throw new Error(
|
|
63
|
+
`HTTP Error ${response.status}: ${error.message || "Unknown error"}`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
export const loadUserData = async () => {
|
|
68
|
+
try {
|
|
69
|
+
const response = await makeGlobalWebSocketRequest("user:user_info", {});
|
|
70
|
+
const userResponse = response.data;
|
|
71
|
+
const provider = Object.keys(userResponse.profiles)[0];
|
|
72
|
+
const email = userResponse.profiles[provider]?.spec?.claims?.email;
|
|
73
|
+
|
|
74
|
+
const userData: UserData = {
|
|
75
|
+
id: userResponse.userRecord.id.name,
|
|
76
|
+
name: userResponse.userRecord.spec.userinfo.name,
|
|
77
|
+
surname: userResponse.userRecord.spec.userinfo.surname,
|
|
78
|
+
provider: [
|
|
79
|
+
{
|
|
80
|
+
name: provider,
|
|
81
|
+
email: email || "",
|
|
82
|
+
password: "",
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
notificationsEnabled: "true",
|
|
86
|
+
organizations: [],
|
|
87
|
+
clusterTokens: [],
|
|
88
|
+
tokens: [],
|
|
89
|
+
tenants: [],
|
|
90
|
+
axebowPlan: "freemium",
|
|
91
|
+
companyName: userResponse.userRecord.spec.userinfo.companyName,
|
|
92
|
+
rol: userResponse.userRecord.spec.userinfo.companyRole,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
const tenantsResponse = await makeGlobalWebSocketRequest(
|
|
97
|
+
"tenant:list_tenants",
|
|
98
|
+
{ strict: true },
|
|
99
|
+
30000,
|
|
100
|
+
"GET",
|
|
101
|
+
"ALL_TENANTS"
|
|
102
|
+
);
|
|
103
|
+
const tenantsData = tenantsResponse.data;
|
|
104
|
+
const userTenants: Tenant[] = [];
|
|
105
|
+
const userOrganizations: Organization[] = [];
|
|
106
|
+
for (const [_, value] of Object.entries(tenantsData)) {
|
|
107
|
+
const parts = (value as any).toString().split(",");
|
|
108
|
+
userTenants.push({
|
|
109
|
+
id: parts[0],
|
|
110
|
+
name: parts[0],
|
|
111
|
+
organizationsIds: [],
|
|
112
|
+
services: [],
|
|
113
|
+
accounts: [],
|
|
114
|
+
environments: [],
|
|
115
|
+
marketplaceItems: [],
|
|
116
|
+
resources: [],
|
|
117
|
+
role: parts[1],
|
|
118
|
+
status: "healthy",
|
|
119
|
+
users: [],
|
|
120
|
+
registry: [
|
|
121
|
+
{
|
|
122
|
+
name: "",
|
|
123
|
+
public: false,
|
|
124
|
+
credentials: "",
|
|
125
|
+
domain: "",
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
for (const tenant of userTenants) {
|
|
131
|
+
try {
|
|
132
|
+
const tenantResponse = await makeGlobalWebSocketRequest(
|
|
133
|
+
"tenant:tenant_info",
|
|
134
|
+
{
|
|
135
|
+
tenant: tenant.name,
|
|
136
|
+
},
|
|
137
|
+
30000,
|
|
138
|
+
"GET",
|
|
139
|
+
tenant.name
|
|
140
|
+
);
|
|
141
|
+
const tenantData = tenantResponse.data;
|
|
142
|
+
const registries = tenantData?.registries?.registries;
|
|
143
|
+
|
|
144
|
+
if (registries && Object.keys(registries).length > 0) {
|
|
145
|
+
const tenantRegistry = Object.keys(registries)[0];
|
|
146
|
+
const tenantOptions = registries[tenantRegistry]?.options;
|
|
147
|
+
let registry: Registry = {
|
|
148
|
+
name: "",
|
|
149
|
+
domain: "",
|
|
150
|
+
public: false,
|
|
151
|
+
credentials: "",
|
|
152
|
+
description: "",
|
|
153
|
+
extra: {},
|
|
154
|
+
password: "",
|
|
155
|
+
};
|
|
156
|
+
if (tenantOptions?.endpoint) {
|
|
157
|
+
registry.domain = tenantOptions.endpoint;
|
|
158
|
+
}
|
|
159
|
+
if (tenantOptions?.credentials) {
|
|
160
|
+
registry.credentials = tenantOptions.credentials;
|
|
161
|
+
}
|
|
162
|
+
if (typeof tenantOptions?.public === "boolean") {
|
|
163
|
+
registry.public = tenantOptions.public;
|
|
164
|
+
}
|
|
165
|
+
if (tenantData?.domains && Object.keys(tenantData.domains)[0]) {
|
|
166
|
+
registry.name = Object.keys(tenantData.domains)[0];
|
|
167
|
+
}
|
|
168
|
+
tenant.registry.push(registry);
|
|
169
|
+
} else {
|
|
170
|
+
console.warn(
|
|
171
|
+
`No se encontró información de registry para el tenant ${tenant.name}`
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const tenantAccounts: Account[] = [];
|
|
176
|
+
const tenantEnvironments: Environment[] = [];
|
|
177
|
+
const userServices: Service[] = [];
|
|
178
|
+
|
|
179
|
+
if (tenantData && Array.isArray(tenantData.accounts)) {
|
|
180
|
+
for (const account of tenantData.accounts) {
|
|
181
|
+
const environmentsIds: string[] = [];
|
|
182
|
+
|
|
183
|
+
if (account.environments && Array.isArray(account.environments)) {
|
|
184
|
+
for (const env of account.environments) {
|
|
185
|
+
const envId = `${env.id.name}`;
|
|
186
|
+
environmentsIds.push(envId);
|
|
187
|
+
const newEnvironment: Environment = {
|
|
188
|
+
id: envId,
|
|
189
|
+
name: env.id.name,
|
|
190
|
+
account: `${account.account.id.parent.name}-${account.account.id.name}`,
|
|
191
|
+
tenant: account.account.id.parent.name.split("tenant/")[1],
|
|
192
|
+
logo: `${
|
|
193
|
+
env.logo ||
|
|
194
|
+
"https://kumori.systems/wp-content/uploads/2023/07/cropped-favicon-kumori.png"
|
|
195
|
+
}`,
|
|
196
|
+
services: [],
|
|
197
|
+
domains: [],
|
|
198
|
+
status: {
|
|
199
|
+
code: env.status.state,
|
|
200
|
+
message: env.status.message,
|
|
201
|
+
timestamp: env.status.timestamp,
|
|
202
|
+
},
|
|
203
|
+
usage: {
|
|
204
|
+
current: {
|
|
205
|
+
cpu: env.status.marks.vcpu.current / 1000,
|
|
206
|
+
memory: env.status.marks.memory.current / 1000,
|
|
207
|
+
storage: env.status.marks.storage.current / 1000,
|
|
208
|
+
volatileStorage:
|
|
209
|
+
env.status.marks.vstorage.current / 1000,
|
|
210
|
+
nonReplicatedStorage:
|
|
211
|
+
env.status.marks.nrstorage.current / 1000,
|
|
212
|
+
persistentStorage:
|
|
213
|
+
env.status.marks.rstorage.current / 1000,
|
|
214
|
+
},
|
|
215
|
+
limit: {
|
|
216
|
+
cpu: {
|
|
217
|
+
max: env.spec.marks.vcpu.highmark / 1000,
|
|
218
|
+
min: env.spec.marks.vcpu.lowmark / 1000,
|
|
219
|
+
},
|
|
220
|
+
memory: {
|
|
221
|
+
max: env.spec.marks.memory.highmark / 1000,
|
|
222
|
+
min: env.spec.marks.memory.lowmark / 1000,
|
|
223
|
+
},
|
|
224
|
+
storage: {
|
|
225
|
+
max: env.spec.marks.storage.highmark / 1000,
|
|
226
|
+
min: env.spec.marks.storage.lowmark / 1000,
|
|
227
|
+
},
|
|
228
|
+
volatileStorage: {
|
|
229
|
+
max: env.spec.marks.vstorage.highmark / 1000,
|
|
230
|
+
min: env.spec.marks.vstorage.lowmark / 1000,
|
|
231
|
+
},
|
|
232
|
+
nonReplicatedStorage: {
|
|
233
|
+
max: env.spec.marks.nrstorage.highmark / 1000,
|
|
234
|
+
min: env.spec.marks.nrstorage.lowmark / 1000,
|
|
235
|
+
},
|
|
236
|
+
persistentStorage: {
|
|
237
|
+
max: env.spec.marks.rstorage.highmark / 1000,
|
|
238
|
+
min: env.spec.marks.rstorage.lowmark / 1000,
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
cost: env.status.marks.cost.current,
|
|
242
|
+
},
|
|
243
|
+
organization: "",
|
|
244
|
+
cloudProvider: "",
|
|
245
|
+
labels: [],
|
|
246
|
+
type: "",
|
|
247
|
+
cluster: { name: "" },
|
|
248
|
+
};
|
|
249
|
+
tenantEnvironments.push(newEnvironment);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const cloudProviderInfo = extractCloudProviderInfo(
|
|
254
|
+
account.account.spec
|
|
255
|
+
);
|
|
256
|
+
const newAccount: Account = {
|
|
257
|
+
id: `${account.account.id.parent.name}-${account.account.id.name}`,
|
|
258
|
+
name: account.account.id.name,
|
|
259
|
+
tenant: account.account.id.parent.name.split("tenant/")[1],
|
|
260
|
+
cloudProvider: {
|
|
261
|
+
name: account.account.spec.api,
|
|
262
|
+
...cloudProviderInfo,
|
|
263
|
+
},
|
|
264
|
+
logo: `${
|
|
265
|
+
account.account.spec.api ||
|
|
266
|
+
"https://kumori.systems/wp-content/uploads/2023/07/cropped-favicon-kumori.png"
|
|
267
|
+
}`,
|
|
268
|
+
environments: environmentsIds,
|
|
269
|
+
services: [],
|
|
270
|
+
domains: [],
|
|
271
|
+
status: account.account.status.validCredentials
|
|
272
|
+
? account.account.status.validCredentials?.status ===
|
|
273
|
+
"InvalidCredentials"
|
|
274
|
+
? "InvalidCredentials"
|
|
275
|
+
: !account.account.status.validCredentials?.status &&
|
|
276
|
+
account.account.id !== "kumori"
|
|
277
|
+
? "pending"
|
|
278
|
+
: "healthy"
|
|
279
|
+
: "",
|
|
280
|
+
usage: {
|
|
281
|
+
current: {
|
|
282
|
+
cpu: account.account.status.marks.vcpu.current / 1000,
|
|
283
|
+
memory: account.account.status.marks.memory.current / 1000,
|
|
284
|
+
storage:
|
|
285
|
+
account.account.status.marks.storage.current / 1000,
|
|
286
|
+
volatileStorage:
|
|
287
|
+
account.account.status.marks.vstorage.current / 1000,
|
|
288
|
+
nonReplicatedStorage:
|
|
289
|
+
account.account.status.marks.nrstorage.current / 1000,
|
|
290
|
+
persistentStorage:
|
|
291
|
+
account.account.status.marks.rstorage.current / 1000,
|
|
292
|
+
},
|
|
293
|
+
limit: {
|
|
294
|
+
cpu: {
|
|
295
|
+
max: account.account.spec.marks.vcpu.highmark / 1000,
|
|
296
|
+
min: account.account.spec.marks.vcpu.lowmark / 1000,
|
|
297
|
+
},
|
|
298
|
+
memory: {
|
|
299
|
+
max: account.account.spec.marks.memory.highmark / 1000,
|
|
300
|
+
min: account.account.spec.marks.memory.lowmark / 1000,
|
|
301
|
+
},
|
|
302
|
+
storage: {
|
|
303
|
+
max: account.account.spec.marks.storage.highmark / 1000,
|
|
304
|
+
min: account.account.spec.marks.storage.lowmark / 1000,
|
|
305
|
+
},
|
|
306
|
+
volatileStorage: {
|
|
307
|
+
max: account.account.spec.marks.vstorage.highmark / 1000,
|
|
308
|
+
min: account.account.spec.marks.vstorage.lowmark / 1000,
|
|
309
|
+
},
|
|
310
|
+
nonReplicatedStorage: {
|
|
311
|
+
max: account.account.spec.marks.nrstorage.highmark / 1000,
|
|
312
|
+
min: account.account.spec.marks.nrstorage.lowmark / 1000,
|
|
313
|
+
},
|
|
314
|
+
persistentStorage: {
|
|
315
|
+
max: account.account.spec.marks.rstorage.highmark / 1000,
|
|
316
|
+
min: account.account.spec.marks.rstorage.lowmark / 1000,
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
cost: account.account.status.marks.cost.current,
|
|
320
|
+
},
|
|
321
|
+
flavors: {
|
|
322
|
+
small: account.account.spec.iaasconfig.smallVMFlavor,
|
|
323
|
+
medium: account.account.spec.iaasconfig.mediumVMFlavor,
|
|
324
|
+
large: account.account.spec.iaasconfig.largeVMFlavor,
|
|
325
|
+
volatile: account.account.spec.iaasconfig.volatile,
|
|
326
|
+
nonReplicated: account.account.spec.iaasconfig.nonreplicated,
|
|
327
|
+
persistent: account.account.spec.iaasconfig.persistent,
|
|
328
|
+
},
|
|
329
|
+
organization: account.organization,
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
tenantAccounts.push(newAccount);
|
|
333
|
+
}
|
|
334
|
+
const kinds = [
|
|
335
|
+
"ca",
|
|
336
|
+
"certificate",
|
|
337
|
+
"domain",
|
|
338
|
+
"port",
|
|
339
|
+
"secret",
|
|
340
|
+
"volume",
|
|
341
|
+
];
|
|
342
|
+
|
|
343
|
+
for (const kind of kinds) {
|
|
344
|
+
try {
|
|
345
|
+
const resourcesResponse = await makeGlobalWebSocketRequest(
|
|
346
|
+
"resource:list_resources",
|
|
347
|
+
{
|
|
348
|
+
tenant: tenant.name,
|
|
349
|
+
kind: kind,
|
|
350
|
+
},
|
|
351
|
+
30000,
|
|
352
|
+
"GET",
|
|
353
|
+
"ALL_RESOURCES"
|
|
354
|
+
);
|
|
355
|
+
const resourcesData = resourcesResponse.data;
|
|
356
|
+
if (
|
|
357
|
+
!resourcesData[kind] ||
|
|
358
|
+
!Array.isArray(resourcesData[kind])
|
|
359
|
+
) {
|
|
360
|
+
console.warn(
|
|
361
|
+
`No se encontraron recursos de tipo ${kind} o no es un array`
|
|
362
|
+
);
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
for (const resource of resourcesData[kind]) {
|
|
367
|
+
try {
|
|
368
|
+
const resourceName = resource.id.name;
|
|
369
|
+
const resourceResponse = await makeGlobalWebSocketRequest(
|
|
370
|
+
"resource:resource_info",
|
|
371
|
+
{
|
|
372
|
+
tenant: tenant.name,
|
|
373
|
+
kind: kind,
|
|
374
|
+
resource: resourceName,
|
|
375
|
+
},
|
|
376
|
+
30000,
|
|
377
|
+
"GET",
|
|
378
|
+
resourceName
|
|
379
|
+
);
|
|
380
|
+
const resourceDataJson = resourceResponse.data;
|
|
381
|
+
const resourceType = resourceDataJson.id.kind;
|
|
382
|
+
let resourceStatus: "used" | "available" | "error" =
|
|
383
|
+
"available";
|
|
384
|
+
|
|
385
|
+
if (
|
|
386
|
+
resourceDataJson.status &&
|
|
387
|
+
resourceDataJson.status.requested
|
|
388
|
+
) {
|
|
389
|
+
const requestedKeys = Object.keys(
|
|
390
|
+
resourceDataJson.status.requested
|
|
391
|
+
);
|
|
392
|
+
if (requestedKeys.length > 0) {
|
|
393
|
+
resourceStatus = "used";
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (resourceType === "volume") {
|
|
398
|
+
tenant.resources.push({
|
|
399
|
+
type: kind,
|
|
400
|
+
name: resourceName,
|
|
401
|
+
value: resourceDataJson.spec[resourceType].size,
|
|
402
|
+
kind: resourceDataJson.spec[resourceType].kind,
|
|
403
|
+
maxItems: resourceDataJson.spec[resourceType].maxitems,
|
|
404
|
+
status: resourceStatus,
|
|
405
|
+
} as Resource);
|
|
406
|
+
} else if (resourceType === "certificate") {
|
|
407
|
+
tenant.resources.push({
|
|
408
|
+
type: kind,
|
|
409
|
+
name: resourceName,
|
|
410
|
+
value: resourceDataJson.spec[resourceType].cert,
|
|
411
|
+
key: resourceDataJson.spec[resourceType].key,
|
|
412
|
+
domain: resourceDataJson.spec[resourceType].domain,
|
|
413
|
+
status: resourceStatus,
|
|
414
|
+
} as Resource);
|
|
415
|
+
} else if (
|
|
416
|
+
resourceType === "domain" ||
|
|
417
|
+
resourceType === "port" ||
|
|
418
|
+
resourceType === "ca" ||
|
|
419
|
+
resourceType === "secret"
|
|
420
|
+
) {
|
|
421
|
+
tenant.resources.push({
|
|
422
|
+
type: kind,
|
|
423
|
+
name: resourceName,
|
|
424
|
+
value: resourceDataJson.spec[resourceType],
|
|
425
|
+
status: resourceStatus,
|
|
426
|
+
} as Resource);
|
|
427
|
+
}
|
|
428
|
+
} catch (resourceError) {
|
|
429
|
+
console.error(
|
|
430
|
+
`Error procesando recurso individual de tipo ${kind}:`,
|
|
431
|
+
resourceError
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
} catch (error) {
|
|
436
|
+
console.error(
|
|
437
|
+
`Error procesando recursos de tipo ${kind}:`,
|
|
438
|
+
error
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
const servicesResponse = await makeGlobalWebSocketRequest(
|
|
444
|
+
"service:list_services",
|
|
445
|
+
{
|
|
446
|
+
tenant: tenant.name,
|
|
447
|
+
},
|
|
448
|
+
30000,
|
|
449
|
+
"GET",
|
|
450
|
+
"ALL_SERVICES"
|
|
451
|
+
);
|
|
452
|
+
const servicesData = servicesResponse.data;
|
|
453
|
+
const serviceEntries = Object.entries(servicesData);
|
|
454
|
+
|
|
455
|
+
for (const [, serviceValue] of serviceEntries) {
|
|
456
|
+
try {
|
|
457
|
+
let serviceStatus = {
|
|
458
|
+
code: "",
|
|
459
|
+
message: "",
|
|
460
|
+
timestamp: "",
|
|
461
|
+
args: [],
|
|
462
|
+
};
|
|
463
|
+
const serviceResponse = await makeGlobalWebSocketRequest(
|
|
464
|
+
"service:describe_service",
|
|
465
|
+
{
|
|
466
|
+
tenant: tenant.name,
|
|
467
|
+
service: (serviceValue as any).name,
|
|
468
|
+
summary: false,
|
|
469
|
+
},
|
|
470
|
+
30000,
|
|
471
|
+
"GET",
|
|
472
|
+
(serviceValue as any).name
|
|
473
|
+
);
|
|
474
|
+
const serviceData = serviceResponse.data;
|
|
475
|
+
let revisionData;
|
|
476
|
+
try {
|
|
477
|
+
const revisionResponse = await makeGlobalWebSocketRequest(
|
|
478
|
+
"revision:revision_info",
|
|
479
|
+
{
|
|
480
|
+
tenant: tenant.name,
|
|
481
|
+
service: (serviceValue as any).name,
|
|
482
|
+
revision: "latest",
|
|
483
|
+
},
|
|
484
|
+
30000,
|
|
485
|
+
"GET_REVISION",
|
|
486
|
+
(serviceValue as any).name
|
|
487
|
+
);
|
|
488
|
+
revisionData = revisionResponse.data;
|
|
489
|
+
} catch (revisionError) {
|
|
490
|
+
serviceStatus = {
|
|
491
|
+
code: "PENDING",
|
|
492
|
+
message: "",
|
|
493
|
+
timestamp: "",
|
|
494
|
+
args: [],
|
|
495
|
+
},
|
|
496
|
+
console.warn(
|
|
497
|
+
`No se pudo obtener la revisión para el servicio ${
|
|
498
|
+
(serviceValue as any).name
|
|
499
|
+
}:`,
|
|
500
|
+
revisionError
|
|
501
|
+
);
|
|
502
|
+
continue;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const serviceName = revisionData.solution.top;
|
|
506
|
+
let revisionsData;
|
|
507
|
+
try {
|
|
508
|
+
const revisionsResponse = await makeGlobalWebSocketRequest(
|
|
509
|
+
"service:report_history_service",
|
|
510
|
+
{
|
|
511
|
+
tenant: tenant.name,
|
|
512
|
+
service: serviceName,
|
|
513
|
+
},
|
|
514
|
+
30000,
|
|
515
|
+
"GET_HISTORY",
|
|
516
|
+
serviceName
|
|
517
|
+
);
|
|
518
|
+
revisionsData = revisionsResponse.data;
|
|
519
|
+
} catch (historyError) {
|
|
520
|
+
serviceStatus = {
|
|
521
|
+
code: "PENDING",
|
|
522
|
+
message: "",
|
|
523
|
+
timestamp: "",
|
|
524
|
+
args: [],
|
|
525
|
+
},
|
|
526
|
+
console.warn(
|
|
527
|
+
`No se pudo obtener el historial para el servicio ${serviceName}:`,
|
|
528
|
+
historyError
|
|
529
|
+
);
|
|
530
|
+
continue;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
const revisions: string[] = [];
|
|
534
|
+
for (const revision of revisionsData) {
|
|
535
|
+
revisions.push(revision.revision);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const serviceRoles: { name: string; instances: Instance[] }[] =
|
|
539
|
+
[];
|
|
540
|
+
let serviceUsedVCPU = 0;
|
|
541
|
+
let serviceUsedRAM = 0;
|
|
542
|
+
const roles =
|
|
543
|
+
revisionData.solution.deployments[serviceName].artifact
|
|
544
|
+
.description.role;
|
|
545
|
+
|
|
546
|
+
for (const roleName of Object.keys(roles)) {
|
|
547
|
+
try {
|
|
548
|
+
const instancesResponse = await makeGlobalWebSocketRequest(
|
|
549
|
+
"service:describe_role_service",
|
|
550
|
+
{
|
|
551
|
+
tenant: tenant.name,
|
|
552
|
+
service: serviceName,
|
|
553
|
+
role: roleName,
|
|
554
|
+
},
|
|
555
|
+
30000,
|
|
556
|
+
"GET_ROLE",
|
|
557
|
+
serviceName + "_" + roleName
|
|
558
|
+
);
|
|
559
|
+
const instancesData = instancesResponse.data;
|
|
560
|
+
const instances: Instance[] = [];
|
|
561
|
+
|
|
562
|
+
for (const [instanceName, instanceValue] of Object.entries(
|
|
563
|
+
instancesData.instances
|
|
564
|
+
)) {
|
|
565
|
+
const containers: Container[] = [];
|
|
566
|
+
for (const [
|
|
567
|
+
containerName,
|
|
568
|
+
containerValue,
|
|
569
|
+
] of Object.entries((instanceValue as any).containers)) {
|
|
570
|
+
containers.push({
|
|
571
|
+
name: containerName,
|
|
572
|
+
ready: (containerValue as any).ready,
|
|
573
|
+
reestartCount: (containerValue as any).restarts,
|
|
574
|
+
metrics: {
|
|
575
|
+
cpu: (containerValue as any).metrics.usage.cpu,
|
|
576
|
+
memory: (containerValue as any).metrics.usage.memory,
|
|
577
|
+
},
|
|
578
|
+
states: (containerValue as any).states,
|
|
579
|
+
});
|
|
580
|
+
serviceUsedVCPU += (containerValue as any).metrics.usage
|
|
581
|
+
.cpu;
|
|
582
|
+
serviceUsedRAM += (containerValue as any).metrics.usage
|
|
583
|
+
.memory;
|
|
584
|
+
}
|
|
585
|
+
instances.push({
|
|
586
|
+
id: instanceName,
|
|
587
|
+
name: instanceName,
|
|
588
|
+
status: (instanceValue as any).status,
|
|
589
|
+
usage: {
|
|
590
|
+
current: {
|
|
591
|
+
cpu: (instanceValue as any).metrics.usage.cpu,
|
|
592
|
+
memory: (instanceValue as any).metrics.usage.memory,
|
|
593
|
+
storage: 0,
|
|
594
|
+
volatileStorage: 0,
|
|
595
|
+
nonReplicatedStorage: 0,
|
|
596
|
+
persistentStorage: 0,
|
|
597
|
+
},
|
|
598
|
+
limit: {
|
|
599
|
+
cpu: {
|
|
600
|
+
max:
|
|
601
|
+
serviceData.artifact.description.role[roleName]
|
|
602
|
+
.artifact.description.code[roleName]?.size?.cpu
|
|
603
|
+
?.min / 1000,
|
|
604
|
+
min:
|
|
605
|
+
serviceData.artifact.description.role[roleName]
|
|
606
|
+
.artifact.description.code[roleName]?.size?.cpu
|
|
607
|
+
?.min / 1000,
|
|
608
|
+
},
|
|
609
|
+
memory: {
|
|
610
|
+
max:
|
|
611
|
+
serviceData.artifact.description.role[roleName]
|
|
612
|
+
.artifact.description.code[roleName]?.size
|
|
613
|
+
?.memory?.size / 1000,
|
|
614
|
+
min:
|
|
615
|
+
serviceData.artifact.description.role[roleName]
|
|
616
|
+
.artifact.description.code[roleName]?.size
|
|
617
|
+
?.memory?.size / 1000,
|
|
618
|
+
},
|
|
619
|
+
storage: {
|
|
620
|
+
max: 0,
|
|
621
|
+
min: 0,
|
|
622
|
+
},
|
|
623
|
+
volatileStorage: {
|
|
624
|
+
max: 0,
|
|
625
|
+
min: 0,
|
|
626
|
+
},
|
|
627
|
+
nonReplicatedStorage: {
|
|
628
|
+
max: 0,
|
|
629
|
+
min: 0,
|
|
630
|
+
},
|
|
631
|
+
persistentStorage: {
|
|
632
|
+
max: 0,
|
|
633
|
+
min: 0,
|
|
634
|
+
},
|
|
635
|
+
},
|
|
636
|
+
cost: 0,
|
|
637
|
+
},
|
|
638
|
+
logs: [],
|
|
639
|
+
containers: containers,
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
serviceRoles.push({ name: roleName, instances });
|
|
643
|
+
} catch (instanceError) {
|
|
644
|
+
serviceStatus = {
|
|
645
|
+
code: "PENDING",
|
|
646
|
+
message: "",
|
|
647
|
+
timestamp: "",
|
|
648
|
+
args: [],
|
|
649
|
+
},
|
|
650
|
+
console.warn(
|
|
651
|
+
`Error obteniendo instancias para el rol ${roleName}:`,
|
|
652
|
+
instanceError
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
let containerName = "";
|
|
658
|
+
const firstRoleName = Object.keys(roles)[0];
|
|
659
|
+
const code = roles[firstRoleName].artifact.description.code;
|
|
660
|
+
for (const key of Object.keys(code)) {
|
|
661
|
+
if (!key.includes("INIT")) {
|
|
662
|
+
containerName = key;
|
|
663
|
+
break;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const newService: Service = {
|
|
668
|
+
id: (serviceValue as any).name,
|
|
669
|
+
tenant: tenant.name,
|
|
670
|
+
account: (serviceValue as any).environment.split("/")[4],
|
|
671
|
+
environment: (serviceValue as any).environment.split("/")[6],
|
|
672
|
+
name: (serviceValue as any).name,
|
|
673
|
+
logo: "",
|
|
674
|
+
description: "",
|
|
675
|
+
revisions: revisions,
|
|
676
|
+
status: serviceStatus,
|
|
677
|
+
role: serviceRoles,
|
|
678
|
+
links: [],
|
|
679
|
+
resources: [],
|
|
680
|
+
parameters: [],
|
|
681
|
+
usage: {
|
|
682
|
+
current: {
|
|
683
|
+
cpu: serviceUsedVCPU,
|
|
684
|
+
memory: serviceUsedRAM / 1000000000,
|
|
685
|
+
storage: 0,
|
|
686
|
+
volatileStorage: 0,
|
|
687
|
+
nonReplicatedStorage: 0,
|
|
688
|
+
persistentStorage: 0,
|
|
689
|
+
},
|
|
690
|
+
limit: {
|
|
691
|
+
cpu: {
|
|
692
|
+
max: revisionData.revision.spec.intensives.vcpu / 1000,
|
|
693
|
+
min: revisionData.revision.spec.intensives.vcpu / 1000,
|
|
694
|
+
},
|
|
695
|
+
memory: {
|
|
696
|
+
max: revisionData.revision.spec.intensives.ram / 1000,
|
|
697
|
+
min: revisionData.revision.spec.intensives.ram / 1000,
|
|
698
|
+
},
|
|
699
|
+
storage: {
|
|
700
|
+
max: revisionData.revision.spec.intensives.shared_disk,
|
|
701
|
+
min: revisionData.revision.spec.intensives.shared_disk,
|
|
702
|
+
},
|
|
703
|
+
volatileStorage: {
|
|
704
|
+
max: revisionData.revision.spec.intensives.volatile_disk,
|
|
705
|
+
min: revisionData.revision.spec.intensives.volatile_disk,
|
|
706
|
+
},
|
|
707
|
+
nonReplicatedStorage: {
|
|
708
|
+
max: revisionData.revision.spec.intensives
|
|
709
|
+
.nrpersistent_disk,
|
|
710
|
+
min: revisionData.revision.spec.intensives
|
|
711
|
+
.nrpersistent_disk,
|
|
712
|
+
},
|
|
713
|
+
persistentStorage: {
|
|
714
|
+
max: revisionData.revision.spec.intensives
|
|
715
|
+
.persistent_disk,
|
|
716
|
+
min: revisionData.revision.spec.intensives
|
|
717
|
+
.persistent_disk,
|
|
718
|
+
},
|
|
719
|
+
},
|
|
720
|
+
cost: 0,
|
|
721
|
+
},
|
|
722
|
+
minReplicas: 0,
|
|
723
|
+
maxReplicas: 0,
|
|
724
|
+
lastDeployed: `${revisionData.revision.spec.tstamp}`,
|
|
725
|
+
project: "",
|
|
726
|
+
registry:
|
|
727
|
+
roles[firstRoleName].artifact.description.code[containerName]
|
|
728
|
+
.image.hub.name,
|
|
729
|
+
imageName:
|
|
730
|
+
roles[firstRoleName].artifact.description.code[containerName]
|
|
731
|
+
.image.tag,
|
|
732
|
+
entrypoint:
|
|
733
|
+
roles[firstRoleName].artifact.description.code[containerName]
|
|
734
|
+
.entrypoint,
|
|
735
|
+
cmd: roles[firstRoleName].artifact.description.code[
|
|
736
|
+
containerName
|
|
737
|
+
].cmd,
|
|
738
|
+
serverChannels: [],
|
|
739
|
+
clientChannels: [],
|
|
740
|
+
duplexChannels: [],
|
|
741
|
+
cloudProvider: "",
|
|
742
|
+
currentRevision: revisionData.revision.id.name,
|
|
743
|
+
};
|
|
744
|
+
|
|
745
|
+
userServices.push(newService);
|
|
746
|
+
} catch (error) {
|
|
747
|
+
console.error("Error al obtener los datos del servicio:", error);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
for (const account of tenantAccounts) {
|
|
751
|
+
account.services = userServices
|
|
752
|
+
.filter((service) => service.account === account.name)
|
|
753
|
+
.map((service) => service.name);
|
|
754
|
+
}
|
|
755
|
+
for (const environment of tenantEnvironments) {
|
|
756
|
+
environment.services = userServices
|
|
757
|
+
.filter((service) => service.environment === environment.name)
|
|
758
|
+
.map((service) => service.name);
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
try {
|
|
762
|
+
const marketplaceResponse = await makeGlobalWebSocketRequest(
|
|
763
|
+
"marketplace:search_marketplace",
|
|
764
|
+
{
|
|
765
|
+
tenant: tenant.name,
|
|
766
|
+
name: "",
|
|
767
|
+
},
|
|
768
|
+
30000,
|
|
769
|
+
"GET",
|
|
770
|
+
"MARKETPLACE"
|
|
771
|
+
);
|
|
772
|
+
const marketplaceData = marketplaceResponse.data;
|
|
773
|
+
const tenantItems: MarketplaceItem[] = [];
|
|
774
|
+
Object.entries(marketplaceData.items).forEach(([_, value]) => {
|
|
775
|
+
let cpu = 0;
|
|
776
|
+
let memory = 0;
|
|
777
|
+
(value as any).tags.forEach((tag: string) => {
|
|
778
|
+
if (tag.includes("cpu")) {
|
|
779
|
+
cpu = Number(tag.split("::")[1].split("vCPU")[0]);
|
|
780
|
+
} else if (tag.includes("memory")) {
|
|
781
|
+
memory = Number(tag.split("::")[1].split("MB")[0]);
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
const item: MarketplaceItem = {
|
|
785
|
+
tenant: tenant.toString(),
|
|
786
|
+
name: (value as any).name,
|
|
787
|
+
logo: "https://gitlab.com/uploads/-/system/group/avatar/86481133/Axebow-Logo-2.jpeg?width=96",
|
|
788
|
+
description: (value as any).name,
|
|
789
|
+
version: (value as any).version,
|
|
790
|
+
requirements: {
|
|
791
|
+
cpu: cpu,
|
|
792
|
+
memory: memory,
|
|
793
|
+
},
|
|
794
|
+
status: "",
|
|
795
|
+
instances: [],
|
|
796
|
+
links: [],
|
|
797
|
+
resources: [],
|
|
798
|
+
domain: (value as any).domain,
|
|
799
|
+
type: (value as any).artifactTypes[0],
|
|
800
|
+
};
|
|
801
|
+
tenantItems.push(item);
|
|
802
|
+
});
|
|
803
|
+
tenant.marketplaceItems = tenantItems;
|
|
804
|
+
} catch (marketplaceError) {
|
|
805
|
+
console.error(
|
|
806
|
+
`Error obteniendo marketplace para tenant ${tenant.name}:`,
|
|
807
|
+
marketplaceError
|
|
808
|
+
);
|
|
809
|
+
tenant.marketplaceItems = [];
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
tenant.accounts = tenantAccounts;
|
|
813
|
+
tenant.environments = tenantEnvironments;
|
|
814
|
+
tenant.services = userServices;
|
|
815
|
+
} catch (tenantError) {
|
|
816
|
+
console.error(`Error procesando tenant ${tenant.name}:`, tenantError);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
try {
|
|
821
|
+
const organizationsResponse = await makeGlobalWebSocketRequest(
|
|
822
|
+
"organization:list_organizations",
|
|
823
|
+
{
|
|
824
|
+
strict: true,
|
|
825
|
+
},
|
|
826
|
+
30000,
|
|
827
|
+
"GET",
|
|
828
|
+
"ORGANIZATIONS"
|
|
829
|
+
);
|
|
830
|
+
const organizationsData = organizationsResponse.data;
|
|
831
|
+
const organizationsEntries = Object.entries(organizationsData);
|
|
832
|
+
for (const [, organizationValue] of organizationsEntries) {
|
|
833
|
+
const newOrg = {
|
|
834
|
+
id: (organizationValue as any).spec.companyName,
|
|
835
|
+
name: (organizationValue as any).id.name,
|
|
836
|
+
usersIds: Object.keys((organizationValue as any).spec.users),
|
|
837
|
+
tenantsIds: Object.keys((organizationValue as any).spec.tenants),
|
|
838
|
+
billingInformation: {
|
|
839
|
+
legalName: (organizationValue as any).spec.billing.companyname,
|
|
840
|
+
CIFNIF: (organizationValue as any).id.name,
|
|
841
|
+
email: (organizationValue as any).spec.billing.email,
|
|
842
|
+
language: (organizationValue as any).spec.billing.language,
|
|
843
|
+
country: (organizationValue as any).spec.billing.country,
|
|
844
|
+
region: (organizationValue as any).spec.billing.region,
|
|
845
|
+
city: (organizationValue as any).spec.billing.city,
|
|
846
|
+
address: (organizationValue as any).spec.billing.address,
|
|
847
|
+
zipcode: (organizationValue as any).spec.billing.zip,
|
|
848
|
+
},
|
|
849
|
+
invoices: [],
|
|
850
|
+
};
|
|
851
|
+
userOrganizations.push(newOrg);
|
|
852
|
+
}
|
|
853
|
+
} catch (organizationError) {
|
|
854
|
+
console.error("Error obteniendo organizaciones:", organizationError);
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
try {
|
|
858
|
+
const platformResponse = await makeGlobalWebSocketRequest(
|
|
859
|
+
"misc:info",
|
|
860
|
+
{},
|
|
861
|
+
30000,
|
|
862
|
+
"GET",
|
|
863
|
+
"PLATFORM"
|
|
864
|
+
);
|
|
865
|
+
|
|
866
|
+
const platformData: Platform = {
|
|
867
|
+
instanceName: String(platformResponse.instanceName),
|
|
868
|
+
platformVersion: String(platformResponse.platformVersion),
|
|
869
|
+
referenceDomain: String(platformResponse.referenceDomain),
|
|
870
|
+
apiVersions: Array.isArray(platformResponse.apiVersions)
|
|
871
|
+
? platformResponse.apiVersions.map(String)
|
|
872
|
+
: [],
|
|
873
|
+
oidProviders: Array.isArray(platformResponse.oidProviders)
|
|
874
|
+
? platformResponse.oidProviders.map(String)
|
|
875
|
+
: [],
|
|
876
|
+
iaasProviders:
|
|
877
|
+
typeof platformResponse.iaasProviders === "object" &&
|
|
878
|
+
platformResponse.iaasProviders !== null
|
|
879
|
+
? platformResponse.iaasProviders
|
|
880
|
+
: {},
|
|
881
|
+
freemiumAdvancedLimits: {
|
|
882
|
+
vcpu: {
|
|
883
|
+
lowmark: Number(
|
|
884
|
+
platformResponse.freemiumAdvancedLimits.vcpu.lowmark
|
|
885
|
+
),
|
|
886
|
+
highmark: Number(
|
|
887
|
+
platformResponse.freemiumAdvancedLimits.vcpu.highmark
|
|
888
|
+
),
|
|
889
|
+
unit: String(platformResponse.freemiumAdvancedLimits.vcpu.unit),
|
|
890
|
+
},
|
|
891
|
+
memory: {
|
|
892
|
+
lowmark: Number(
|
|
893
|
+
platformResponse.freemiumAdvancedLimits.memory.lowmark
|
|
894
|
+
),
|
|
895
|
+
highmark: Number(
|
|
896
|
+
platformResponse.freemiumAdvancedLimits.memory.highmark
|
|
897
|
+
),
|
|
898
|
+
unit: String(platformResponse.freemiumAdvancedLimits.memory.unit),
|
|
899
|
+
},
|
|
900
|
+
vstorage: {
|
|
901
|
+
lowmark: Number(
|
|
902
|
+
platformResponse.freemiumAdvancedLimits.vstorage.lowmark
|
|
903
|
+
),
|
|
904
|
+
highmark: Number(
|
|
905
|
+
platformResponse.freemiumAdvancedLimits.vstorage.highmark
|
|
906
|
+
),
|
|
907
|
+
unit: String(
|
|
908
|
+
platformResponse.freemiumAdvancedLimits.vstorage.unit
|
|
909
|
+
),
|
|
910
|
+
},
|
|
911
|
+
nrstorage: {
|
|
912
|
+
lowmark: Number(
|
|
913
|
+
platformResponse.freemiumAdvancedLimits.nrstorage.lowmark
|
|
914
|
+
),
|
|
915
|
+
highmark: Number(
|
|
916
|
+
platformResponse.freemiumAdvancedLimits.nrstorage.highmark
|
|
917
|
+
),
|
|
918
|
+
unit: String(
|
|
919
|
+
platformResponse.freemiumAdvancedLimits.nrstorage.unit
|
|
920
|
+
),
|
|
921
|
+
},
|
|
922
|
+
rstorage: {
|
|
923
|
+
lowmark: Number(
|
|
924
|
+
platformResponse.freemiumAdvancedLimits.rstorage.lowmark
|
|
925
|
+
),
|
|
926
|
+
highmark: Number(
|
|
927
|
+
platformResponse.freemiumAdvancedLimits.rstorage.highmark
|
|
928
|
+
),
|
|
929
|
+
unit: String(
|
|
930
|
+
platformResponse.freemiumAdvancedLimits.rstorage.unit
|
|
931
|
+
),
|
|
932
|
+
},
|
|
933
|
+
storage: {
|
|
934
|
+
lowmark: Number(
|
|
935
|
+
platformResponse.freemiumAdvancedLimits.storage.lowmark
|
|
936
|
+
),
|
|
937
|
+
highmark: Number(
|
|
938
|
+
platformResponse.freemiumAdvancedLimits.storage.highmark
|
|
939
|
+
),
|
|
940
|
+
unit: String(
|
|
941
|
+
platformResponse.freemiumAdvancedLimits.storage.unit
|
|
942
|
+
),
|
|
943
|
+
},
|
|
944
|
+
cost: {
|
|
945
|
+
lowmark: Number(
|
|
946
|
+
platformResponse.freemiumAdvancedLimits.cost.lowmark
|
|
947
|
+
),
|
|
948
|
+
highmark: Number(
|
|
949
|
+
platformResponse.freemiumAdvancedLimits.cost.highmark
|
|
950
|
+
),
|
|
951
|
+
unit: String(platformResponse.freemiumAdvancedLimits.cost.unit),
|
|
952
|
+
},
|
|
953
|
+
},
|
|
954
|
+
freemiumLimits: {
|
|
955
|
+
vcpu: {
|
|
956
|
+
lowmark: Number(platformResponse.freemiumLimits.vcpu.lowmark),
|
|
957
|
+
highmark: Number(platformResponse.freemiumLimits.vcpu.highmark),
|
|
958
|
+
unit: String(platformResponse.freemiumLimits.vcpu.unit),
|
|
959
|
+
},
|
|
960
|
+
memory: {
|
|
961
|
+
lowmark: Number(platformResponse.freemiumLimits.memory.lowmark),
|
|
962
|
+
highmark: Number(platformResponse.freemiumLimits.memory.highmark),
|
|
963
|
+
unit: String(platformResponse.freemiumLimits.memory.unit),
|
|
964
|
+
},
|
|
965
|
+
vstorage: {
|
|
966
|
+
lowmark: Number(platformResponse.freemiumLimits.vstorage.lowmark),
|
|
967
|
+
highmark: Number(
|
|
968
|
+
platformResponse.freemiumLimits.vstorage.highmark
|
|
969
|
+
),
|
|
970
|
+
unit: String(platformResponse.freemiumLimits.vstorage.unit),
|
|
971
|
+
},
|
|
972
|
+
nrstorage: {
|
|
973
|
+
lowmark: Number(
|
|
974
|
+
platformResponse.freemiumLimits.nrstorage.lowmark
|
|
975
|
+
),
|
|
976
|
+
highmark: Number(
|
|
977
|
+
platformResponse.freemiumLimits.nrstorage.highmark
|
|
978
|
+
),
|
|
979
|
+
unit: String(platformResponse.freemiumLimits.nrstorage.unit),
|
|
980
|
+
},
|
|
981
|
+
rstorage: {
|
|
982
|
+
lowmark: Number(platformResponse.freemiumLimits.rstorage.lowmark),
|
|
983
|
+
highmark: Number(
|
|
984
|
+
platformResponse.freemiumLimits.rstorage.highmark
|
|
985
|
+
),
|
|
986
|
+
unit: String(platformResponse.freemiumLimits.rstorage.unit),
|
|
987
|
+
},
|
|
988
|
+
storage: {
|
|
989
|
+
lowmark: Number(platformResponse.freemiumLimits.storage.lowmark),
|
|
990
|
+
highmark: Number(
|
|
991
|
+
platformResponse.freemiumLimits.storage.highmark
|
|
992
|
+
),
|
|
993
|
+
unit: String(platformResponse.freemiumLimits.storage.unit),
|
|
994
|
+
},
|
|
995
|
+
cost: {
|
|
996
|
+
lowmark: Number(platformResponse.freemiumLimits.cost.lowmark),
|
|
997
|
+
highmark: Number(platformResponse.freemiumLimits.cost.highmark),
|
|
998
|
+
unit: String(platformResponse.freemiumLimits.cost.unit),
|
|
999
|
+
},
|
|
1000
|
+
},
|
|
1001
|
+
portrange: Array.isArray(platformResponse.portrange)
|
|
1002
|
+
? platformResponse.portrange.map(Number)
|
|
1003
|
+
: [],
|
|
1004
|
+
};
|
|
1005
|
+
if (eventHelper.user) {
|
|
1006
|
+
eventHelper.user.publish.loaded(
|
|
1007
|
+
new User(userData, userTenants, userOrganizations, platformData)
|
|
1008
|
+
);
|
|
1009
|
+
} else {
|
|
1010
|
+
}
|
|
1011
|
+
} catch (error) {
|
|
1012
|
+
console.error("Error al obtener los datos del tenant:", error);
|
|
1013
|
+
throw error;
|
|
1014
|
+
}
|
|
1015
|
+
} catch (error) {
|
|
1016
|
+
console.error("Error al obtener los datos del usuario:", error);
|
|
1017
|
+
}
|
|
1018
|
+
} catch (err) {
|
|
1019
|
+
console.error(err);
|
|
1020
|
+
}
|
|
1021
|
+
};
|
|
1022
|
+
|
|
1023
|
+
const extractCloudProviderInfo = (accountSpec: any) => {
|
|
1024
|
+
const credentials = accountSpec.credentials;
|
|
1025
|
+
if (!credentials) {
|
|
1026
|
+
return {
|
|
1027
|
+
region: "",
|
|
1028
|
+
interface: "",
|
|
1029
|
+
apiVersion: "",
|
|
1030
|
+
authType: "",
|
|
1031
|
+
authUrl: "",
|
|
1032
|
+
credentialId: "",
|
|
1033
|
+
credentialSecret: "",
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
if (credentials.openstack) {
|
|
1037
|
+
return {
|
|
1038
|
+
region: credentials.openstack.region_name ?? "",
|
|
1039
|
+
interface: credentials.openstack.interface ?? "",
|
|
1040
|
+
apiVersion: credentials.openstack.identity_api_version ?? "",
|
|
1041
|
+
authType: credentials.openstack.auth_type ?? "",
|
|
1042
|
+
authUrl: credentials.openstack.auth?.auth_url ?? "",
|
|
1043
|
+
credentialId:
|
|
1044
|
+
credentials.openstack.auth?.credential_id ??
|
|
1045
|
+
credentials.openstack.auth?.application_credential_id ??
|
|
1046
|
+
"",
|
|
1047
|
+
credentialSecret:
|
|
1048
|
+
credentials.openstack.auth?.credential_secret ??
|
|
1049
|
+
credentials.openstack.auth?.application_credential_secret ??
|
|
1050
|
+
"",
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
return {
|
|
1054
|
+
region: "",
|
|
1055
|
+
interface: "",
|
|
1056
|
+
apiVersion: "",
|
|
1057
|
+
authType: credentials.method ?? "",
|
|
1058
|
+
authUrl: credentials.apiuri ?? "",
|
|
1059
|
+
credentialId: "",
|
|
1060
|
+
credentialSecret: "",
|
|
1061
|
+
};
|
|
1062
|
+
};
|
|
1063
|
+
export const updateUser = async (user: User) => {
|
|
1064
|
+
try {
|
|
1065
|
+
const userBody = {
|
|
1066
|
+
spec: {
|
|
1067
|
+
name: user.name,
|
|
1068
|
+
surname: user.surname,
|
|
1069
|
+
discoveryMethod: "work",
|
|
1070
|
+
companyName: user.companyName,
|
|
1071
|
+
companyRole: user.rol,
|
|
1072
|
+
},
|
|
1073
|
+
};
|
|
1074
|
+
const response = await makeGlobalWebSocketRequest(
|
|
1075
|
+
"user:modify_user_info",
|
|
1076
|
+
userBody,
|
|
1077
|
+
30000,
|
|
1078
|
+
"PUT",
|
|
1079
|
+
"UPDATE_USER"
|
|
1080
|
+
);
|
|
1081
|
+
eventHelper.user.publish.updated(user);
|
|
1082
|
+
const userUpdatedNotification: Notification = {
|
|
1083
|
+
type: "success",
|
|
1084
|
+
subtype: "user-updated",
|
|
1085
|
+
date: Date.now().toString(),
|
|
1086
|
+
status: "unread",
|
|
1087
|
+
callToAction: false,
|
|
1088
|
+
data: {
|
|
1089
|
+
user: user.name
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
eventHelper.notification.publish.creation(userUpdatedNotification);
|
|
1093
|
+
} catch (error) {
|
|
1094
|
+
console.error("Error updating user:", {
|
|
1095
|
+
error,
|
|
1096
|
+
errorMessage: error instanceof Error ? error.message : "Unknown error",
|
|
1097
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
1098
|
+
});
|
|
1099
|
+
eventHelper.user.publish.updateError(user);
|
|
1100
|
+
const userUpdatedNotificationError: Notification = {
|
|
1101
|
+
type: "error",
|
|
1102
|
+
subtype: "tenant-update-error",
|
|
1103
|
+
date: Date.now().toString(),
|
|
1104
|
+
status: "unread",
|
|
1105
|
+
callToAction: false,
|
|
1106
|
+
info_content:{
|
|
1107
|
+
code: (error as any).error.code,
|
|
1108
|
+
message: (error as any).error.content
|
|
1109
|
+
},
|
|
1110
|
+
data: {
|
|
1111
|
+
user: user.name
|
|
1112
|
+
}
|
|
1113
|
+
};
|
|
1114
|
+
eventHelper.notification.publish.creation(userUpdatedNotificationError);
|
|
1115
|
+
throw error;
|
|
1116
|
+
}
|
|
1117
|
+
};
|
|
1118
|
+
export const deleteUSer = async (user: User, security: string) => {
|
|
1119
|
+
try {
|
|
1120
|
+
await initializeGlobalWebSocketClient(security);
|
|
1121
|
+
const response = await makeGlobalWebSocketRequest(
|
|
1122
|
+
"user:delete_user",
|
|
1123
|
+
{},
|
|
1124
|
+
30000,
|
|
1125
|
+
"DELETE",
|
|
1126
|
+
"DELETE_USER",
|
|
1127
|
+
"user"
|
|
1128
|
+
);
|
|
1129
|
+
|
|
1130
|
+
const userDeletedNotification: Notification = {
|
|
1131
|
+
type: "success",
|
|
1132
|
+
subtype: "user-deleted",
|
|
1133
|
+
date: Date.now().toString(),
|
|
1134
|
+
status: "unread",
|
|
1135
|
+
callToAction: false,
|
|
1136
|
+
data: {
|
|
1137
|
+
user: user.name
|
|
1138
|
+
}
|
|
1139
|
+
};
|
|
1140
|
+
eventHelper.notification.publish.creation(userDeletedNotification);
|
|
1141
|
+
return response;
|
|
1142
|
+
} catch (error) {
|
|
1143
|
+
console.error("Error deleting user:", error);
|
|
1144
|
+
const userDeletedNotificationError: Notification = {
|
|
1145
|
+
type: "error",
|
|
1146
|
+
subtype: "user-delete-error",
|
|
1147
|
+
date: Date.now().toString(),
|
|
1148
|
+
status: "unread",
|
|
1149
|
+
callToAction: false,
|
|
1150
|
+
info_content:{
|
|
1151
|
+
code: (error as any).error.code,
|
|
1152
|
+
message: (error as any).error.content
|
|
1153
|
+
},
|
|
1154
|
+
data: {
|
|
1155
|
+
user: user.name
|
|
1156
|
+
}
|
|
1157
|
+
};
|
|
1158
|
+
eventHelper.notification.publish.creation(userDeletedNotificationError);
|
|
1159
|
+
throw error;
|
|
1160
|
+
}
|
|
1161
|
+
};
|