@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/event-names.ts ADDED
@@ -0,0 +1,152 @@
1
+ export enum EventNames {
2
+ // * Tenant
3
+ CreateTenant = "createTenant",
4
+ TenantCreated = "tenantCreated",
5
+ TenantCreationError = "tenantCreationError",
6
+ UpdateTenant = "updateTenant",
7
+ TenantUpdated = "tenantUpdated",
8
+ TenantUpdateError = "tenantUpdateError",
9
+ DeleteTenant = "deleteTenant",
10
+ TenantDeleted = "tenantDeleted",
11
+ TenantDeletionError = "tenantDeletionError",
12
+ CreateRegistry = "createRegistry",
13
+ RegistryCreated = "registryCreated",
14
+ RegistryCreationError = "registryCreationError",
15
+ UpdateRegistry = "updateRegistry",
16
+ RegistryUpdated = "registryUpdated",
17
+ RegistryUpdateError = "registryUpdateError",
18
+ DeleteRegistry = "deleteRegistry",
19
+ RegistryDeleted = "registryDeleted",
20
+ RegistryDeletionError = "registryDeletionError",
21
+ InviteUser = "inviteUser",
22
+ UserInvited = "tenantInvited",
23
+ UserInviteError = "tenantInviteError",
24
+ RemoveUserFromTenant = "removeUserFromTenant",
25
+ UserRemovedFromTenant = "userRemovedFromTenant",
26
+ UserRemovalFromTenantError = "userRemovalFromTenantError",
27
+ AcceptInvite = "acceptInvite",
28
+ InviteAccepted = "inviteAccepted",
29
+ InviteAcceptError = "inviteAcceptError",
30
+ UpdateInvite = "updateInvite",
31
+ InviteUpdated = "inviteUpdated",
32
+ InviteUpdateError = "inviteUpdateError",
33
+ RejectInvite = "rejectInvite",
34
+ InviteRejected = "inviteRejected",
35
+ InviteRejectError = "inviteRejectError",
36
+ CreateToken = "createToken",
37
+ TokenCreated = "tokenCreated",
38
+ TokenCreationError = "tokenCreationError",
39
+ DeleteToken = "deleteToken",
40
+ TokenDeleted = "tokenDeleted",
41
+ TokenDeletionError = "tokenDeletionError",
42
+
43
+ // * User
44
+ CreateUser = "createUser",
45
+ UserCreated = "userCreated",
46
+ UserCreationError = "userCreationError",
47
+ UpdateUser = "updateUser",
48
+ UserUpdated = "userUpdated",
49
+ UserUpdateError = "userUpdateError",
50
+ LoadUser = "loadUser",
51
+ UserLoaded = "userLoaded",
52
+ UserLoadError = "userLoadError",
53
+ DeleteUser = "deleteUser",
54
+ UserDeleted = "userDeleted",
55
+ UserDeletionError = "userDeletionError",
56
+ AuthError = "authError",
57
+ // * Account
58
+ CreateAccount = "createAccount",
59
+ AccountCreated = "accountCreated",
60
+ AccountCreationError = "accountCreationError",
61
+ UpdateAccount = "updateAccount",
62
+ AccountUpdated = "accountUpdated",
63
+ AccountUpdateError = "accountUpdateError",
64
+ DeleteAccount = "deleteAccount",
65
+ AccountDeleted = "accountDeleted",
66
+ AccountDeletionError = "accountDeletionError",
67
+ CleanAccount = "cleanAccount",
68
+ AccountCleaned = "accountCleaned",
69
+ AccountCleanError = "accountCleanError",
70
+ // * Environment
71
+ CreateEnvironment = "createEnvironment",
72
+ EnvironmentCreated = "environmentCreated",
73
+ EnvironmentCreationError = "environmentCreationError",
74
+ UpdateEnvironment = "updateEnvironment",
75
+ EnvironmentUpdated = "environmentUpdated",
76
+ EnvironmentUpdateError = "environmentUpdateError",
77
+ DeleteEnvironment = "deleteEnvironment",
78
+ EnvironmentDeleted = "environmentDeleted",
79
+ EvironmentDeletionError = "environmentDeletionError",
80
+ CleanEnvironment = "cleanEnvironment",
81
+ EnvironmentCleaned = "environmentCleaned",
82
+ EnvironmentCleanError = "environmentCleanError",
83
+ ScaleEnvironment = "scaleEnvironmet",
84
+ EnvironmentScaled = "environmentScaled",
85
+ EnvironmentScaleError = "environmentScaleError",
86
+ // * Service
87
+ DeployService = "deployService",
88
+ ServiceDeployed = "serviceDeployed",
89
+ ServiceDeploymentError = "deploymentError",
90
+ UpdateService = "updateService",
91
+ ServiceUpdated = "serviceUpdated",
92
+ ServiceUpdateError = "serviceUpdateError",
93
+ DeleteService = "deleteService",
94
+ ServiceDeleted = "serviceDeleted",
95
+ ServiceDeletionError = "serviceDeletionError",
96
+ RequestLogs = "requestLogs",
97
+ RestartService = "restartService",
98
+ ServiceRestarted = "serviceRestarted",
99
+ ServiceRestartError = "serviceRestartError",
100
+ RequestRevisionData = "requestRevisionData",
101
+ updateServiceLinks = "updateServiceLinks",
102
+ ChangeRevision = "changeRevision",
103
+ RevisionChanged = "revisionChanged",
104
+ RevisionChangeError = "revisionChangeError",
105
+ // * Marketplace
106
+ DeployMarketplaceItem = "deployMarketplaceItem",
107
+ MarketplaceItemDeployed = "marketplaceItemDeployed",
108
+ MarketplaceItemDeploymentError = "marketplaceItemDeploymentError",
109
+ UpdateMarketplaceItem = "updateMarketplaceItem",
110
+ MarketplaceItemUpdated = "marketplaceItemUpdated",
111
+ MarketplaceItemUpdateError = "marketplaceItemUpdateError",
112
+ DeleteMarketplaceItem = "deleteMarketplaceItem",
113
+ MarketplaceItemDeleted = "marketplaceItemDeleted",
114
+ MarketplaceItemDeletionError = "marketplaceItemDeletionError",
115
+ LoadMarketplaceItems = "loadMarketplaceItems",
116
+ MarketplaceItemsLoaded = "marketplaceItemsLoaded",
117
+ // * Resource
118
+ CreateResource = "createResource",
119
+ ResourceCreated = "resourceCreated",
120
+ ResourceCreationError = "resourceCreationError",
121
+ UpdateResource = "updateResource",
122
+ ResourceUpdated = "resourceUpdated",
123
+ ResourceUpdateError = "resourceUpdateError",
124
+ DeleteResource = "deleteResource",
125
+ ResourceDeleted = "resourceDeleted",
126
+ ResourceDeletionError = "resourceDeletionError",
127
+ // * Plan
128
+ UpdatePlan = "updatePlan",
129
+ PlanUpdated = "planUpdated",
130
+ PlanUpdateError = "planUpdateError",
131
+ DowngradePlan = "downgradePlan",
132
+ PlanDowngraded = "planDowngraded",
133
+ PlanDowngradeError = "planDowngradeError",
134
+ // * Organizations
135
+ CreateOrganization = "createOrganization",
136
+ OrganizationCreated = "organizationCreated",
137
+ OrganizationCreationError = "organizationCreationError",
138
+ UpdateOrganization = "updateOrganization",
139
+ OrganizationUpdated = "organizationUpdated",
140
+ OrganizationUpdateError = "organizationUpdateError",
141
+ DeleteOrganization = "deleteOrganization",
142
+ OrganizationDeleted = "organizationDeleted",
143
+ OrganizationDeletionError = "organizationDeletionError",
144
+ // * Notificaitons
145
+ CreateNotification = "createNotification",
146
+ DeleteNotification = "deleteNotification",
147
+ NotificationRead = "notificationRead",
148
+ // * Plan providers
149
+ LoadPlanProviders = "loadPlanProviders",
150
+ PlanProvidersLoaded = "planProvidersLoaded",
151
+ PlanProvidersLoadError = "planProvidersLoadError"
152
+ }
@@ -0,0 +1,331 @@
1
+ import { Account, Notification } from "@hestekumori/aurora-interfaces";
2
+
3
+
4
+ interface HandleAccountEventParams {
5
+ entityId: string;
6
+ eventData: any;
7
+ parentParts: { [entity: string]: string };
8
+ accountsMap: Map<string, Account>;
9
+ }
10
+
11
+ interface HandleAccountEventResult {
12
+ account: Account;
13
+ isDeleted: boolean;
14
+ }
15
+ interface HandleAccountOperationSuccessParams {
16
+ action: string;
17
+ entityName: string;
18
+ originalData: Account;
19
+ }
20
+
21
+ interface HandleAccountOperationSuccessResult {
22
+ updatedAccount: Account | null;
23
+ shouldDelete: boolean;
24
+ notification: Notification;
25
+ eventType: "created" | "updated" | "deleted" | null;
26
+ }
27
+
28
+ interface HandleAccountOperationErrorParams {
29
+ action: string;
30
+ entityName: string;
31
+ originalData: any;
32
+ error: any;
33
+ }
34
+
35
+ interface HandleAccountOperationErrorResult {
36
+ updatedAccount: Account | null;
37
+ shouldDelete: boolean;
38
+ notification: Notification;
39
+ eventType: "creationError" | "updateError" | "deletionError";
40
+ }
41
+ /**
42
+ * Extract cloud provider credentials from event data
43
+ */
44
+ const extractCloudProviderCredentials = (
45
+ eventData: any
46
+ ): { providerType: string; credentials: any } => {
47
+ let providerType = "";
48
+ let credentials = {};
49
+
50
+ if (eventData.spec.credentials.openstack) {
51
+ providerType = "ovh";
52
+ credentials = {
53
+ region: eventData.spec.credentials.openstack?.region_name || "",
54
+ interface: eventData.spec.credentials.openstack?.interface || "",
55
+ apiVersion: eventData.spec.credentials.openstack?.identity_api_version || "",
56
+ authType: eventData.spec.credentials.openstack?.auth_type || "",
57
+ authUrl: eventData.spec.credentials.openstack?.auth?.auth_url || "",
58
+ credentialId:
59
+ eventData.spec.credentials.openstack?.auth?.application_credential_id || "",
60
+ credentialSecret:
61
+ eventData.spec.credentials.openstack?.auth?.application_credential_secret || "",
62
+ };
63
+ } else if (eventData.spec.credentials.aws) {
64
+ providerType = "aws";
65
+ credentials = {
66
+ region: eventData.spec.credentials.aws?.region || "",
67
+ credentialId: eventData.spec.credentials.aws?.aws_access_key_id || "",
68
+ credentialSecret: eventData.spec.credentials.aws?.aws_secret_access_key || "",
69
+ };
70
+ } else if (eventData.spec.credentials.azure) {
71
+ providerType = "azure";
72
+ credentials = {
73
+ region: eventData.spec.credentials.azure?.region || "",
74
+ subscriptionId: eventData.spec.credentials.azure?.subscription_id || "",
75
+ tenantId: eventData.spec.credentials.azure?.tenant_id || "",
76
+ clientId: eventData.spec.credentials.azure?.client_id || "",
77
+ clientSecret: eventData.spec.credentials.azure?.client_secret || "",
78
+ };
79
+ }
80
+
81
+ return { providerType, credentials };
82
+ };
83
+
84
+ /**
85
+ * Determine account status from event data
86
+ */
87
+ const determineAccountStatus = (
88
+ eventData: any,
89
+ existingAccount: Account | undefined
90
+ ): string => {
91
+ if (eventData.meta?.deleted) {
92
+ return "deleting";
93
+ }
94
+ if (eventData.status.validCredentials?.status) {
95
+ return eventData.status.validCredentials.status;
96
+ }
97
+ if (existingAccount?.status) {
98
+ return existingAccount.status;
99
+ }
100
+ return "pending";
101
+ };
102
+
103
+
104
+ /**
105
+ * Handles the "account" event from WebSocket messages
106
+ * Processes account data updates and cloud provider credentials
107
+ */
108
+ export const handleAccountEvent = ({
109
+ entityId,
110
+ eventData,
111
+ parentParts,
112
+ accountsMap,
113
+ }: HandleAccountEventParams): HandleAccountEventResult => {
114
+ const accountTenantId = parentParts.tenant;
115
+ const { providerType, credentials } = extractCloudProviderCredentials(eventData);
116
+ const accountLabels: Record<string, string> = eventData.meta.labels;
117
+ const hasCredentials = "__axebow::managedCredentials" in accountLabels;
118
+ const existingAccount = accountsMap.get(entityId);
119
+ const accountStatus = determineAccountStatus(eventData, existingAccount);
120
+ const newAccount: Account = {
121
+ id: entityId,
122
+ name: entityId,
123
+ tenant: accountTenantId,
124
+ cloudProvider: {
125
+ name: eventData.spec.api,
126
+ ...credentials,
127
+ },
128
+ logo: "",
129
+ environments: [],
130
+ services: [],
131
+ domains: [],
132
+ status: accountStatus,
133
+ usage: {
134
+ current: {
135
+ cpu: eventData.status.marks.vcpu.current / 1000,
136
+ memory: eventData.status.marks.memory.current / 1000,
137
+ storage: eventData.status.marks.storage.current / 1000,
138
+ volatileStorage: eventData.status.marks.vstorage.current / 1000,
139
+ nonReplicatedStorage: eventData.status.marks.nrstorage.current / 1000,
140
+ persistentStorage: eventData.status.marks.rstorage.current / 1000,
141
+ cpuConsuption: existingAccount?.usage.current.cpuConsuption || [],
142
+ memoryConsuption: existingAccount?.usage.current.memoryConsuption || [],
143
+ },
144
+ limit: {
145
+ cpu: {
146
+ max: eventData.spec.marks.vcpu.highmark / 1000,
147
+ min: eventData.spec.marks.vcpu.lowmark / 1000,
148
+ },
149
+ memory: {
150
+ max: eventData.spec.marks.memory.highmark / 1000,
151
+ min: eventData.spec.marks.memory.lowmark / 1000,
152
+ },
153
+ storage: {
154
+ max: eventData.spec.marks.storage.highmark / 1000,
155
+ min: eventData.spec.marks.storage.lowmark / 1000,
156
+ },
157
+ volatileStorage: {
158
+ max: eventData.spec.marks.vstorage.highmark / 1000,
159
+ min: eventData.spec.marks.vstorage.lowmark / 1000,
160
+ },
161
+ nonReplicatedStorage: {
162
+ max: eventData.spec.marks.nrstorage.highmark / 1000,
163
+ min: eventData.spec.marks.nrstorage.lowmark / 1000,
164
+ },
165
+ persistentStorage: {
166
+ max: eventData.spec.marks.rstorage.highmark / 1000,
167
+ min: eventData.spec.marks.rstorage.lowmark / 1000,
168
+ },
169
+ },
170
+ cost: 0,
171
+ },
172
+ flavors: {
173
+ small: [eventData.spec.iaasconfig.smallVMFlavor || ""],
174
+ medium: [eventData.spec.iaasconfig.mediumVMFlavor || ""],
175
+ large: [eventData.spec.iaasconfig.largeVMFlavor || ""],
176
+ volatile: [eventData.spec.iaasconfig.volatile || ""],
177
+ nonReplicated: [eventData.spec.iaasconfig.nonreplicated || ""],
178
+ persistent: [eventData.spec.iaasconfig.persistent || ""],
179
+ },
180
+ organization: "",
181
+ nodes: {
182
+ max: eventData.spec.marks.nodes.highmark,
183
+ min: 0,
184
+ },
185
+ credentials: hasCredentials,
186
+ };
187
+
188
+ return {
189
+ account: newAccount,
190
+ isDeleted: false,
191
+ };
192
+ };
193
+
194
+
195
+ /**
196
+ * Handles successful account operations (CREATE, UPDATE, DELETE)
197
+ */
198
+ export const handleAccountOperationSuccess = ({
199
+ action,
200
+ entityName,
201
+ originalData,
202
+ }: HandleAccountOperationSuccessParams): HandleAccountOperationSuccessResult => {
203
+ if (action === "DELETE") {
204
+ const accountNotification: Notification = {
205
+ type: "success",
206
+ subtype: "account-deleted",
207
+ date: Date.now().toString(),
208
+ status: "unread",
209
+ callToAction: false,
210
+ data: {
211
+ account: originalData.name,
212
+ tenant: originalData.tenant,
213
+ },
214
+ };
215
+
216
+ return {
217
+ updatedAccount: null,
218
+ shouldDelete: true,
219
+ notification: accountNotification,
220
+ eventType: "deleted",
221
+ };
222
+ }
223
+
224
+ if (originalData) {
225
+ const updatedAccount = { ...originalData, status: "active" };
226
+
227
+ let subtype: string;
228
+ let eventType: "created" | "updated" | null = null;
229
+
230
+ if (action === "CREATE") {
231
+ subtype = "account-created";
232
+ eventType = "created";
233
+ } else {
234
+ subtype = "account-updated";
235
+ eventType = "updated";
236
+ }
237
+
238
+ const accountNotification: Notification = {
239
+ type: "success",
240
+ subtype,
241
+ date: Date.now().toString(),
242
+ status: "unread",
243
+ callToAction: false,
244
+ data: {
245
+ account: updatedAccount.name,
246
+ tenant: updatedAccount.tenant,
247
+ },
248
+ };
249
+
250
+ return {
251
+ updatedAccount,
252
+ shouldDelete: false,
253
+ notification: accountNotification,
254
+ eventType,
255
+ };
256
+ }
257
+
258
+ return {
259
+ updatedAccount: null,
260
+ shouldDelete: false,
261
+ notification: {
262
+ type: "success",
263
+ subtype: "account-unknown",
264
+ date: Date.now().toString(),
265
+ status: "unread",
266
+ callToAction: false,
267
+ data: {},
268
+ },
269
+ eventType: null,
270
+ };
271
+ };
272
+
273
+
274
+ /**
275
+ * Handles failed account operations (CREATE, UPDATE, DELETE)
276
+ */
277
+ export const handleAccountOperationError = ({
278
+ action,
279
+ entityName,
280
+ originalData,
281
+ error,
282
+ }: HandleAccountOperationErrorParams): HandleAccountOperationErrorResult => {
283
+ let subtype: string;
284
+ let eventType: "creationError" | "updateError" | "deletionError";
285
+ let shouldDelete = false;
286
+
287
+ if (action === "CREATE") {
288
+ subtype = "account-creation-error";
289
+ eventType = "creationError";
290
+ shouldDelete = true;
291
+ } else if (action === "UPDATE") {
292
+ subtype = "account-update-error";
293
+ eventType = "updateError";
294
+ } else {
295
+ subtype = "account-deletion-error";
296
+ eventType = "deletionError";
297
+ }
298
+
299
+ const accountErrorNotification: Notification = {
300
+ type: "error",
301
+ subtype,
302
+ date: Date.now().toString(),
303
+ status: "unread",
304
+ info_content: {
305
+ code: error?.error?.code || "UNKNOWN_ERROR",
306
+ message: error?.error?.content || error?.error?.message || "Unknown error",
307
+ timestamp: error?.error?.timestamp || Date.now().toString(),
308
+ },
309
+ callToAction: false,
310
+ data: {
311
+ account: entityName || originalData?.name || originalData?.account || "unknown",
312
+ tenant: originalData?.tenant || "unknown",
313
+ },
314
+ };
315
+
316
+ let updatedAccount: Account | null = null;
317
+
318
+ if (!shouldDelete && originalData) {
319
+ updatedAccount = {
320
+ ...originalData,
321
+ status: "error",
322
+ };
323
+ }
324
+
325
+ return {
326
+ updatedAccount,
327
+ shouldDelete,
328
+ notification: accountErrorNotification,
329
+ eventType,
330
+ };
331
+ };