feat(deployment): Implement Deployment and DeploymentManager classes with CRUD operations and service integration
This commit is contained in:
		| @@ -23,6 +23,8 @@ import { CloudlyBaremetalManager } from './manager.baremetal/classes.baremetalma | |||||||
| import { ExternalApiManager } from './manager.status/statusmanager.js'; | import { ExternalApiManager } from './manager.status/statusmanager.js'; | ||||||
| import { ExternalRegistryManager } from './manager.externalregistry/index.js'; | import { ExternalRegistryManager } from './manager.externalregistry/index.js'; | ||||||
| import { ImageManager } from './manager.image/classes.imagemanager.js'; | import { ImageManager } from './manager.image/classes.imagemanager.js'; | ||||||
|  | import { ServiceManager } from './manager.service/classes.servicemanager.js'; | ||||||
|  | import { DeploymentManager } from './manager.deployment/classes.deploymentmanager.js'; | ||||||
| import { logger } from './logger.js'; | import { logger } from './logger.js'; | ||||||
| import { CloudlyAuthManager } from './manager.auth/classes.authmanager.js'; | import { CloudlyAuthManager } from './manager.auth/classes.authmanager.js'; | ||||||
| import { CloudlySettingsManager } from './manager.settings/classes.settingsmanager.js'; | import { CloudlySettingsManager } from './manager.settings/classes.settingsmanager.js'; | ||||||
| @@ -60,6 +62,8 @@ export class Cloudly { | |||||||
|   public externalApiManager: ExternalApiManager; |   public externalApiManager: ExternalApiManager; | ||||||
|   public externalRegistryManager: ExternalRegistryManager; |   public externalRegistryManager: ExternalRegistryManager; | ||||||
|   public imageManager: ImageManager; |   public imageManager: ImageManager; | ||||||
|  |   public serviceManager: ServiceManager; | ||||||
|  |   public deploymentManager: DeploymentManager; | ||||||
|   public taskManager: CloudlyTaskmanager; |   public taskManager: CloudlyTaskmanager; | ||||||
|   public nodeManager: CloudlyNodeManager; |   public nodeManager: CloudlyNodeManager; | ||||||
|   public baremetalManager: CloudlyBaremetalManager; |   public baremetalManager: CloudlyBaremetalManager; | ||||||
| @@ -89,6 +93,8 @@ export class Cloudly { | |||||||
|     this.externalApiManager = new ExternalApiManager(this); |     this.externalApiManager = new ExternalApiManager(this); | ||||||
|     this.externalRegistryManager = new ExternalRegistryManager(this); |     this.externalRegistryManager = new ExternalRegistryManager(this); | ||||||
|     this.imageManager = new ImageManager(this); |     this.imageManager = new ImageManager(this); | ||||||
|  |     this.serviceManager = new ServiceManager(this); | ||||||
|  |     this.deploymentManager = new DeploymentManager(this); | ||||||
|     this.taskManager = new CloudlyTaskmanager(this); |     this.taskManager = new CloudlyTaskmanager(this); | ||||||
|     this.secretManager = new CloudlySecretManager(this); |     this.secretManager = new CloudlySecretManager(this); | ||||||
|     this.nodeManager = new CloudlyNodeManager(this); |     this.nodeManager = new CloudlyNodeManager(this); | ||||||
| @@ -114,6 +120,8 @@ export class Cloudly { | |||||||
|     await this.secretManager.start(); |     await this.secretManager.start(); | ||||||
|     await this.nodeManager.start(); |     await this.nodeManager.start(); | ||||||
|     await this.baremetalManager.start(); |     await this.baremetalManager.start(); | ||||||
|  |     await this.serviceManager.start(); | ||||||
|  |     await this.deploymentManager.start(); | ||||||
|      |      | ||||||
|     await this.cloudflareConnector.init(); |     await this.cloudflareConnector.init(); | ||||||
|     await this.letsencryptConnector.init(); |     await this.letsencryptConnector.init(); | ||||||
| @@ -133,5 +141,7 @@ export class Cloudly { | |||||||
|     await this.letsencryptConnector.stop(); |     await this.letsencryptConnector.stop(); | ||||||
|     await this.mongodbConnector.stop(); |     await this.mongodbConnector.stop(); | ||||||
|     await this.secretManager.stop(); |     await this.secretManager.stop(); | ||||||
|  |     await this.serviceManager.stop(); | ||||||
|  |     await this.deploymentManager.stop(); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										97
									
								
								ts/manager.deployment/classes.deployment.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								ts/manager.deployment/classes.deployment.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | |||||||
|  | import * as plugins from '../plugins.js'; | ||||||
|  |  | ||||||
|  | export class Deployment extends plugins.smartdata.SmartDataDbDoc< | ||||||
|  |   Deployment, | ||||||
|  |   plugins.servezoneInterfaces.data.IDeployment | ||||||
|  | > { | ||||||
|  |   @plugins.smartdata.unI() | ||||||
|  |   public id: string = plugins.smartunique.uniSimple('deployment'); | ||||||
|  |  | ||||||
|  |   @plugins.smartdata.svDb() | ||||||
|  |   public serviceId: string; | ||||||
|  |  | ||||||
|  |   @plugins.smartdata.svDb() | ||||||
|  |   public nodeId: string; | ||||||
|  |  | ||||||
|  |   @plugins.smartdata.svDb() | ||||||
|  |   public containerId?: string; | ||||||
|  |  | ||||||
|  |   @plugins.smartdata.svDb() | ||||||
|  |   public usedImageId: string; | ||||||
|  |  | ||||||
|  |   @plugins.smartdata.svDb() | ||||||
|  |   public version: string; | ||||||
|  |  | ||||||
|  |   @plugins.smartdata.svDb() | ||||||
|  |   public deployedAt: number; | ||||||
|  |  | ||||||
|  |   @plugins.smartdata.svDb() | ||||||
|  |   public deploymentLog: string[] = []; | ||||||
|  |  | ||||||
|  |   @plugins.smartdata.svDb() | ||||||
|  |   public status: 'scheduled' | 'starting' | 'running' | 'stopping' | 'stopped' | 'failed'; | ||||||
|  |  | ||||||
|  |   @plugins.smartdata.svDb() | ||||||
|  |   public healthStatus?: 'healthy' | 'unhealthy' | 'unknown'; | ||||||
|  |  | ||||||
|  |   @plugins.smartdata.svDb() | ||||||
|  |   public resourceUsage?: { | ||||||
|  |     cpuUsagePercent: number; | ||||||
|  |     memoryUsedMB: number; | ||||||
|  |     lastUpdated: number; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   public static async createDeployment( | ||||||
|  |     deploymentData: Partial<plugins.servezoneInterfaces.data.IDeployment> | ||||||
|  |   ): Promise<Deployment> { | ||||||
|  |     const deployment = new Deployment(); | ||||||
|  |     if (deploymentData.serviceId) deployment.serviceId = deploymentData.serviceId; | ||||||
|  |     if (deploymentData.nodeId) deployment.nodeId = deploymentData.nodeId; | ||||||
|  |     if (deploymentData.containerId) deployment.containerId = deploymentData.containerId; | ||||||
|  |     if (deploymentData.usedImageId) deployment.usedImageId = deploymentData.usedImageId; | ||||||
|  |     if (deploymentData.version) deployment.version = deploymentData.version; | ||||||
|  |     if (deploymentData.deployedAt) deployment.deployedAt = deploymentData.deployedAt; | ||||||
|  |     if (deploymentData.deploymentLog) deployment.deploymentLog = deploymentData.deploymentLog; | ||||||
|  |     if (deploymentData.status) deployment.status = deploymentData.status; | ||||||
|  |     if (deploymentData.healthStatus) deployment.healthStatus = deploymentData.healthStatus; | ||||||
|  |     if (deploymentData.resourceUsage) deployment.resourceUsage = deploymentData.resourceUsage; | ||||||
|  |      | ||||||
|  |     await deployment.save(); | ||||||
|  |     return deployment; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public async updateHealthStatus(healthStatus: 'healthy' | 'unhealthy' | 'unknown') { | ||||||
|  |     this.healthStatus = healthStatus; | ||||||
|  |     await this.save(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public async updateResourceUsage(cpuUsagePercent: number, memoryUsedMB: number) { | ||||||
|  |     this.resourceUsage = { | ||||||
|  |       cpuUsagePercent, | ||||||
|  |       memoryUsedMB, | ||||||
|  |       lastUpdated: Date.now(), | ||||||
|  |     }; | ||||||
|  |     await this.save(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public async addLogEntry(entry: string) { | ||||||
|  |     this.deploymentLog.push(entry); | ||||||
|  |     await this.save(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public async createSavableObject(): Promise<plugins.servezoneInterfaces.data.IDeployment> { | ||||||
|  |     return { | ||||||
|  |       id: this.id, | ||||||
|  |       serviceId: this.serviceId, | ||||||
|  |       nodeId: this.nodeId, | ||||||
|  |       containerId: this.containerId, | ||||||
|  |       usedImageId: this.usedImageId, | ||||||
|  |       version: this.version, | ||||||
|  |       deployedAt: this.deployedAt, | ||||||
|  |       deploymentLog: this.deploymentLog, | ||||||
|  |       status: this.status, | ||||||
|  |       healthStatus: this.healthStatus, | ||||||
|  |       resourceUsage: this.resourceUsage, | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										303
									
								
								ts/manager.deployment/classes.deploymentmanager.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								ts/manager.deployment/classes.deploymentmanager.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,303 @@ | |||||||
|  | import type { Cloudly } from '../classes.cloudly.js'; | ||||||
|  | import * as plugins from '../plugins.js'; | ||||||
|  | import { Deployment } from './classes.deployment.js'; | ||||||
|  |  | ||||||
|  | export class DeploymentManager { | ||||||
|  |   public typedrouter = new plugins.typedrequest.TypedRouter(); | ||||||
|  |   public cloudlyRef: Cloudly; | ||||||
|  |  | ||||||
|  |   get db() { | ||||||
|  |     return this.cloudlyRef.mongodbConnector.smartdataDb; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public CDeployment = plugins.smartdata.setDefaultManagerForDoc(this, Deployment); | ||||||
|  |  | ||||||
|  |   constructor(cloudlyRef: Cloudly) { | ||||||
|  |     this.cloudlyRef = cloudlyRef; | ||||||
|  |      | ||||||
|  |     // Connect typedrouter to main router | ||||||
|  |     this.cloudlyRef.typedrouter.addTypedRouter(this.typedrouter); | ||||||
|  |  | ||||||
|  |     // Get all deployments | ||||||
|  |     this.typedrouter.addTypedHandler( | ||||||
|  |       new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.deployment.IReq_Any_Cloudly_GetDeployments>( | ||||||
|  |         'getDeployments', | ||||||
|  |         async (reqArg) => { | ||||||
|  |           await plugins.smartguard.passGuardsOrReject(reqArg, [ | ||||||
|  |             this.cloudlyRef.authManager.validIdentityGuard, | ||||||
|  |           ]); | ||||||
|  |  | ||||||
|  |           const deployments = await this.CDeployment.getInstances({}); | ||||||
|  |  | ||||||
|  |           return { | ||||||
|  |             deployments: await Promise.all( | ||||||
|  |               deployments.map((deployment) => deployment.createSavableObject()) | ||||||
|  |             ), | ||||||
|  |           }; | ||||||
|  |         } | ||||||
|  |       ) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     // Get deployment by ID | ||||||
|  |     this.typedrouter.addTypedHandler( | ||||||
|  |       new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.deployment.IReq_Any_Cloudly_GetDeploymentById>( | ||||||
|  |         'getDeploymentById', | ||||||
|  |         async (reqArg) => { | ||||||
|  |           await plugins.smartguard.passGuardsOrReject(reqArg, [ | ||||||
|  |             this.cloudlyRef.authManager.validIdentityGuard, | ||||||
|  |           ]); | ||||||
|  |  | ||||||
|  |           const deployment = await this.CDeployment.getInstance({ | ||||||
|  |             id: reqArg.deploymentId, | ||||||
|  |           }); | ||||||
|  |  | ||||||
|  |           if (!deployment) { | ||||||
|  |             throw new Error('Deployment not found'); | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           return { | ||||||
|  |             deployment: await deployment.createSavableObject(), | ||||||
|  |           }; | ||||||
|  |         } | ||||||
|  |       ) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     // Get deployments by service | ||||||
|  |     this.typedrouter.addTypedHandler( | ||||||
|  |       new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.deployment.IReq_Any_Cloudly_GetDeploymentsByService>( | ||||||
|  |         'getDeploymentsByService', | ||||||
|  |         async (reqArg) => { | ||||||
|  |           await plugins.smartguard.passGuardsOrReject(reqArg, [ | ||||||
|  |             this.cloudlyRef.authManager.validIdentityGuard, | ||||||
|  |           ]); | ||||||
|  |  | ||||||
|  |           const deployments = await this.CDeployment.getInstances({ | ||||||
|  |             serviceId: reqArg.serviceId, | ||||||
|  |           }); | ||||||
|  |  | ||||||
|  |           return { | ||||||
|  |             deployments: await Promise.all( | ||||||
|  |               deployments.map((deployment) => deployment.createSavableObject()) | ||||||
|  |             ), | ||||||
|  |           }; | ||||||
|  |         } | ||||||
|  |       ) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     // Get deployments by node | ||||||
|  |     this.typedrouter.addTypedHandler( | ||||||
|  |       new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.deployment.IReq_Any_Cloudly_GetDeploymentsByNode>( | ||||||
|  |         'getDeploymentsByNode', | ||||||
|  |         async (reqArg) => { | ||||||
|  |           await plugins.smartguard.passGuardsOrReject(reqArg, [ | ||||||
|  |             this.cloudlyRef.authManager.validIdentityGuard, | ||||||
|  |           ]); | ||||||
|  |  | ||||||
|  |           const deployments = await this.CDeployment.getInstances({ | ||||||
|  |             nodeId: reqArg.nodeId, | ||||||
|  |           }); | ||||||
|  |  | ||||||
|  |           return { | ||||||
|  |             deployments: await Promise.all( | ||||||
|  |               deployments.map((deployment) => deployment.createSavableObject()) | ||||||
|  |             ), | ||||||
|  |           }; | ||||||
|  |         } | ||||||
|  |       ) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     // Create deployment | ||||||
|  |     this.typedrouter.addTypedHandler( | ||||||
|  |       new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.deployment.IReq_Any_Cloudly_CreateDeployment>( | ||||||
|  |         'createDeployment', | ||||||
|  |         async (reqArg) => { | ||||||
|  |           await plugins.smartguard.passGuardsOrReject(reqArg, [ | ||||||
|  |             this.cloudlyRef.authManager.validIdentityGuard, | ||||||
|  |           ]); | ||||||
|  |  | ||||||
|  |           const deployment = await Deployment.createDeployment(reqArg.deploymentData); | ||||||
|  |  | ||||||
|  |           return { | ||||||
|  |             deployment: await deployment.createSavableObject(), | ||||||
|  |           }; | ||||||
|  |         } | ||||||
|  |       ) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     // Update deployment | ||||||
|  |     this.typedrouter.addTypedHandler( | ||||||
|  |       new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.deployment.IReq_Any_Cloudly_UpdateDeployment>( | ||||||
|  |         'updateDeployment', | ||||||
|  |         async (reqArg) => { | ||||||
|  |           await plugins.smartguard.passGuardsOrReject(reqArg, [ | ||||||
|  |             this.cloudlyRef.authManager.validIdentityGuard, | ||||||
|  |           ]); | ||||||
|  |  | ||||||
|  |           const deployment = await this.CDeployment.getInstance({ | ||||||
|  |             id: reqArg.deploymentId, | ||||||
|  |           }); | ||||||
|  |  | ||||||
|  |           if (!deployment) { | ||||||
|  |             throw new Error('Deployment not found'); | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           // Update fields | ||||||
|  |           if (reqArg.deploymentData.status !== undefined) { | ||||||
|  |             deployment.status = reqArg.deploymentData.status; | ||||||
|  |           } | ||||||
|  |           if (reqArg.deploymentData.healthStatus !== undefined) { | ||||||
|  |             deployment.healthStatus = reqArg.deploymentData.healthStatus; | ||||||
|  |           } | ||||||
|  |           if (reqArg.deploymentData.containerId !== undefined) { | ||||||
|  |             deployment.containerId = reqArg.deploymentData.containerId; | ||||||
|  |           } | ||||||
|  |           if (reqArg.deploymentData.resourceUsage !== undefined) { | ||||||
|  |             deployment.resourceUsage = reqArg.deploymentData.resourceUsage; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           await deployment.save(); | ||||||
|  |  | ||||||
|  |           return { | ||||||
|  |             deployment: await deployment.createSavableObject(), | ||||||
|  |           }; | ||||||
|  |         } | ||||||
|  |       ) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     // Delete deployment | ||||||
|  |     this.typedrouter.addTypedHandler( | ||||||
|  |       new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.deployment.IReq_Any_Cloudly_DeleteDeploymentById>( | ||||||
|  |         'deleteDeploymentById', | ||||||
|  |         async (reqArg) => { | ||||||
|  |           await plugins.smartguard.passGuardsOrReject(reqArg, [ | ||||||
|  |             this.cloudlyRef.authManager.validIdentityGuard, | ||||||
|  |           ]); | ||||||
|  |  | ||||||
|  |           const deployment = await this.CDeployment.getInstance({ | ||||||
|  |             id: reqArg.deploymentId, | ||||||
|  |           }); | ||||||
|  |  | ||||||
|  |           if (!deployment) { | ||||||
|  |             throw new Error('Deployment not found'); | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           await deployment.delete(); | ||||||
|  |  | ||||||
|  |           return { | ||||||
|  |             success: true, | ||||||
|  |           }; | ||||||
|  |         } | ||||||
|  |       ) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     // Restart deployment | ||||||
|  |     this.typedrouter.addTypedHandler( | ||||||
|  |       new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.deployment.IReq_Any_Cloudly_RestartDeployment>( | ||||||
|  |         'restartDeployment', | ||||||
|  |         async (reqArg) => { | ||||||
|  |           await plugins.smartguard.passGuardsOrReject(reqArg, [ | ||||||
|  |             this.cloudlyRef.authManager.validIdentityGuard, | ||||||
|  |           ]); | ||||||
|  |  | ||||||
|  |           const deployment = await this.CDeployment.getInstance({ | ||||||
|  |             id: reqArg.deploymentId, | ||||||
|  |           }); | ||||||
|  |  | ||||||
|  |           if (!deployment) { | ||||||
|  |             throw new Error('Deployment not found'); | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           // TODO: Implement actual restart logic with Docker/container runtime | ||||||
|  |           deployment.status = 'starting'; | ||||||
|  |           await deployment.save(); | ||||||
|  |  | ||||||
|  |           return { | ||||||
|  |             success: true, | ||||||
|  |             deployment: await deployment.createSavableObject(), | ||||||
|  |           }; | ||||||
|  |         } | ||||||
|  |       ) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     // Scale deployment | ||||||
|  |     this.typedrouter.addTypedHandler( | ||||||
|  |       new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.deployment.IReq_Any_Cloudly_ScaleDeployment>( | ||||||
|  |         'scaleDeployment', | ||||||
|  |         async (reqArg) => { | ||||||
|  |           await plugins.smartguard.passGuardsOrReject(reqArg, [ | ||||||
|  |             this.cloudlyRef.authManager.validIdentityGuard, | ||||||
|  |           ]); | ||||||
|  |  | ||||||
|  |           // TODO: Implement scaling logic | ||||||
|  |           // This would create/delete deployment instances based on replicas count | ||||||
|  |  | ||||||
|  |           const deployment = await this.CDeployment.getInstance({ | ||||||
|  |             id: reqArg.deploymentId, | ||||||
|  |           }); | ||||||
|  |  | ||||||
|  |           if (!deployment) { | ||||||
|  |             throw new Error('Deployment not found'); | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           return { | ||||||
|  |             success: true, | ||||||
|  |             deployment: await deployment.createSavableObject(), | ||||||
|  |           }; | ||||||
|  |         } | ||||||
|  |       ) | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Get all deployments | ||||||
|  |    */ | ||||||
|  |   public async getAllDeployments(): Promise<Deployment[]> { | ||||||
|  |     return await this.CDeployment.getInstances({}); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Get deployments for a specific service | ||||||
|  |    */ | ||||||
|  |   public async getDeploymentsForService(serviceId: string): Promise<Deployment[]> { | ||||||
|  |     return await this.CDeployment.getInstances({ | ||||||
|  |       serviceId, | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Get deployments for a specific node | ||||||
|  |    */ | ||||||
|  |   public async getDeploymentsForNode(nodeId: string): Promise<Deployment[]> { | ||||||
|  |     return await this.CDeployment.getInstances({ | ||||||
|  |       nodeId, | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Create a new deployment | ||||||
|  |    */ | ||||||
|  |   public async createDeployment( | ||||||
|  |     serviceId: string, | ||||||
|  |     nodeId: string, | ||||||
|  |     version: string = 'latest' | ||||||
|  |   ): Promise<Deployment> { | ||||||
|  |     return await Deployment.createDeployment({ | ||||||
|  |       serviceId, | ||||||
|  |       nodeId, | ||||||
|  |       version, | ||||||
|  |       status: 'scheduled', | ||||||
|  |       deployedAt: Date.now(), | ||||||
|  |       deploymentLog: [`Deployment created at ${new Date().toISOString()}`], | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public async start() { | ||||||
|  |     // DeploymentManager is ready - handlers are already registered in constructor | ||||||
|  |     console.log('DeploymentManager started'); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public async stop() { | ||||||
|  |     // Cleanup if needed | ||||||
|  |     console.log('DeploymentManager stopped'); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -15,6 +15,8 @@ export class ServiceManager { | |||||||
|   constructor(cloudlyRef: Cloudly) { |   constructor(cloudlyRef: Cloudly) { | ||||||
|     this.cloudlyRef = cloudlyRef; |     this.cloudlyRef = cloudlyRef; | ||||||
|      |      | ||||||
|  |     this.cloudlyRef.typedrouter.addTypedRouter(this.typedrouter); | ||||||
|  |  | ||||||
|     this.typedrouter.addTypedHandler( |     this.typedrouter.addTypedHandler( | ||||||
|       new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.service.IRequest_Any_Cloudly_GetServices>( |       new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.service.IRequest_Any_Cloudly_GetServices>( | ||||||
|         'getServices', |         'getServices', | ||||||
| @@ -97,4 +99,14 @@ export class ServiceManager { | |||||||
|       ) |       ) | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   public async start() { | ||||||
|  |     // ServiceManager is ready - handlers are already registered in constructor | ||||||
|  |     console.log('ServiceManager started'); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public async stop() { | ||||||
|  |     // Cleanup if needed | ||||||
|  |     console.log('ServiceManager stopped'); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -142,13 +142,21 @@ export const getAllDataAction = dataState.createAction(async (statePartArg) => { | |||||||
|       '/typedrequest', |       '/typedrequest', | ||||||
|       'getServices' |       'getServices' | ||||||
|     ); |     ); | ||||||
|   const responseServices = await trGetServices.fire({ |   try { | ||||||
|     identity: loginStatePart.getState().identity, |     const responseServices = await trGetServices.fire({ | ||||||
|   }); |       identity: loginStatePart.getState().identity, | ||||||
|   currentState = { |     }); | ||||||
|     ...currentState, |     currentState = { | ||||||
|     services: responseServices.services, |       ...currentState, | ||||||
|   }; |       services: responseServices?.services || [], | ||||||
|  |     }; | ||||||
|  |   } catch (error) { | ||||||
|  |     console.error('Failed to fetch services:', error); | ||||||
|  |     currentState = { | ||||||
|  |       ...currentState, | ||||||
|  |       services: [], | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Deployments |   // Deployments | ||||||
|   const trGetDeployments = |   const trGetDeployments = | ||||||
| @@ -156,13 +164,21 @@ export const getAllDataAction = dataState.createAction(async (statePartArg) => { | |||||||
|       '/typedrequest', |       '/typedrequest', | ||||||
|       'getDeployments' |       'getDeployments' | ||||||
|     ); |     ); | ||||||
|   const responseDeployments = await trGetDeployments.fire({ |   try { | ||||||
|     identity: loginStatePart.getState().identity, |     const responseDeployments = await trGetDeployments.fire({ | ||||||
|   }); |       identity: loginStatePart.getState().identity, | ||||||
|   currentState = { |     }); | ||||||
|     ...currentState, |     currentState = { | ||||||
|     deployments: responseDeployments.deployments, |       ...currentState, | ||||||
|   }; |       deployments: responseDeployments?.deployments || [], | ||||||
|  |     }; | ||||||
|  |   } catch (error) { | ||||||
|  |     console.error('Failed to fetch deployments:', error); | ||||||
|  |     currentState = { | ||||||
|  |       ...currentState, | ||||||
|  |       deployments: [], | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   return currentState; |   return currentState; | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -15,10 +15,7 @@ import * as appstate from '../appstate.js'; | |||||||
| @customElement('cloudly-view-clusters') | @customElement('cloudly-view-clusters') | ||||||
| export class CloudlyViewClusters extends DeesElement { | export class CloudlyViewClusters extends DeesElement { | ||||||
|   @state() |   @state() | ||||||
|   private data: appstate.IDataState = { |   private data: appstate.IDataState = {}; | ||||||
|     secretGroups: [], |  | ||||||
|     secretBundles: [], |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   constructor() { |   constructor() { | ||||||
|     super(); |     super(); | ||||||
|   | |||||||
| @@ -15,10 +15,7 @@ import * as appstate from '../appstate.js'; | |||||||
| @customElement('cloudly-view-deployments') | @customElement('cloudly-view-deployments') | ||||||
| export class CloudlyViewDeployments extends DeesElement { | export class CloudlyViewDeployments extends DeesElement { | ||||||
|   @state() |   @state() | ||||||
|   private data: appstate.IDataState = { |   private data: appstate.IDataState = {}; | ||||||
|     secretGroups: [], |  | ||||||
|     secretBundles: [], |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   constructor() { |   constructor() { | ||||||
|     super(); |     super(); | ||||||
|   | |||||||
| @@ -8,10 +8,7 @@ import * as appstate from '../appstate.js'; | |||||||
| @customElement('cloudly-view-images') | @customElement('cloudly-view-images') | ||||||
| export class CloudlyViewImages extends DeesElement { | export class CloudlyViewImages extends DeesElement { | ||||||
|   @state() |   @state() | ||||||
|   private data: appstate.IDataState = { |   private data: appstate.IDataState = {}; | ||||||
|     secretGroups: [], |  | ||||||
|     secretBundles: [], |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   constructor() { |   constructor() { | ||||||
|     super(); |     super(); | ||||||
|   | |||||||
| @@ -15,10 +15,7 @@ import * as appstate from '../appstate.js'; | |||||||
| @customElement('cloudly-view-secretbundles') | @customElement('cloudly-view-secretbundles') | ||||||
| export class CloudlyViewSecretBundles extends DeesElement { | export class CloudlyViewSecretBundles extends DeesElement { | ||||||
|   @state() |   @state() | ||||||
|   private data: appstate.IDataState = { |   private data: appstate.IDataState = {}; | ||||||
|     secretGroups: [], |  | ||||||
|     secretBundles: [], |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   constructor() { |   constructor() { | ||||||
|     super(); |     super(); | ||||||
| @@ -44,7 +41,7 @@ export class CloudlyViewSecretBundles extends DeesElement { | |||||||
|       <dees-table |       <dees-table | ||||||
|         .heading1=${'SecretBundles'} |         .heading1=${'SecretBundles'} | ||||||
|         .heading2=${'decoded in client'} |         .heading2=${'decoded in client'} | ||||||
|         .data=${this.data.secretBundles} |         .data=${this.data.secretBundles || []} | ||||||
|         .displayFunction=${(itemArg: plugins.interfaces.data.ISecretBundle) => { |         .displayFunction=${(itemArg: plugins.interfaces.data.ISecretBundle) => { | ||||||
|           return { |           return { | ||||||
|             name: itemArg.data.name, |             name: itemArg.data.name, | ||||||
|   | |||||||
| @@ -8,18 +8,16 @@ import * as appstate from '../appstate.js'; | |||||||
| @customElement('cloudly-view-secretsgroups') | @customElement('cloudly-view-secretsgroups') | ||||||
| export class CloudlyViewSecretGroups extends DeesElement { | export class CloudlyViewSecretGroups extends DeesElement { | ||||||
|   @state() |   @state() | ||||||
|   private data: appstate.IDataState = { |   private data: appstate.IDataState = {}; | ||||||
|     secretGroups: [], |  | ||||||
|     secretBundles: [], |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   constructor() { |   constructor() { | ||||||
|     super(); |     super(); | ||||||
|     appstate.dataState |     const subscription = appstate.dataState | ||||||
|       .select((stateArg) => stateArg) |       .select((stateArg) => stateArg) | ||||||
|       .subscribe((dataArg) => { |       .subscribe((dataArg) => { | ||||||
|         this.data = dataArg; |         this.data = dataArg; | ||||||
|       }); |       }); | ||||||
|  |     this.rxSubscriptions.push(subscription); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public static styles = [ |   public static styles = [ | ||||||
| @@ -36,7 +34,7 @@ export class CloudlyViewSecretGroups extends DeesElement { | |||||||
|       <dees-table |       <dees-table | ||||||
|         heading1="SecretGroups" |         heading1="SecretGroups" | ||||||
|         heading2="decoded in client" |         heading2="decoded in client" | ||||||
|         .data=${this.data.secretGroups} |         .data=${this.data.secretGroups || []} | ||||||
|         .displayFunction=${(secretGroup: plugins.interfaces.data.ISecretGroup) => { |         .displayFunction=${(secretGroup: plugins.interfaces.data.ISecretGroup) => { | ||||||
|           return { |           return { | ||||||
|             name: secretGroup.data.name, |             name: secretGroup.data.name, | ||||||
|   | |||||||
| @@ -15,10 +15,7 @@ import * as appstate from '../appstate.js'; | |||||||
| @customElement('cloudly-view-services') | @customElement('cloudly-view-services') | ||||||
| export class CloudlyViewServices extends DeesElement { | export class CloudlyViewServices extends DeesElement { | ||||||
|   @state() |   @state() | ||||||
|   private data: appstate.IDataState = { |   private data: appstate.IDataState = {}; | ||||||
|     secretGroups: [], |  | ||||||
|     secretBundles: [], |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   constructor() { |   constructor() { | ||||||
|     super(); |     super(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user