303 lines
9.0 KiB
TypeScript
303 lines
9.0 KiB
TypeScript
|
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');
|
||
|
}
|
||
|
}
|