f40ef6b7c0
Align Cloudly with the current typedserver, smartconfig, smartstate, and Docker tooling releases so builds and Docker output stay compatible with the upgraded stack.
200 lines
6.5 KiB
TypeScript
200 lines
6.5 KiB
TypeScript
import * as plugins from '../plugins.js';
|
|
import * as paths from '../paths.js';
|
|
import { Cloudly } from '../classes.cloudly.js';
|
|
import { logger } from '../logger.js';
|
|
|
|
import { Cluster } from './classes.cluster.js';
|
|
import { data } from '@serve.zone/interfaces';
|
|
|
|
export class ClusterManager {
|
|
public ready = plugins.smartpromise.defer();
|
|
|
|
public cloudlyRef: Cloudly;
|
|
public get db() {
|
|
return this.cloudlyRef.mongodbConnector.smartdataDb;
|
|
}
|
|
public typedrouter = new plugins.typedrequest.TypedRouter();
|
|
|
|
public CCluster = plugins.smartdata.setDefaultManagerForDoc(this, Cluster);
|
|
|
|
constructor(cloudlyRef: Cloudly) {
|
|
this.cloudlyRef = cloudlyRef;
|
|
this.cloudlyRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
|
|
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IRequest_CreateCluster>(
|
|
new plugins.typedrequest.TypedHandler('createCluster', async (dataArg, toolsArg) => {
|
|
await toolsArg!.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], dataArg);
|
|
const setupMode = dataArg.setupMode || 'manual'; // Default to manual if not specified
|
|
const cluster = await this.createCluster({
|
|
id: plugins.smartunique.uniSimple('cluster'),
|
|
data: {
|
|
userId: '', // this is created by the createCluster method
|
|
name: dataArg.clusterName,
|
|
setupMode: setupMode,
|
|
acmeInfo: {
|
|
serverAddress: '',
|
|
serverSecret: '',
|
|
},
|
|
cloudlyUrl: `https://${this.cloudlyRef.config.data.publicUrl}:${this.cloudlyRef.config.data.publicPort}/`,
|
|
nodes: [],
|
|
sshKeys: [],
|
|
},
|
|
});
|
|
console.log(await cluster.createSavableObject());
|
|
|
|
// Only auto-provision servers if setupMode is 'hetzner'
|
|
if (setupMode === 'hetzner') {
|
|
this.cloudlyRef.nodeManager.ensureNodeInfrastructure();
|
|
}
|
|
|
|
return {
|
|
cluster: await cluster.createSavableObject(),
|
|
};
|
|
}),
|
|
);
|
|
|
|
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IReq_Any_Cloudly_GetClusters>(
|
|
new plugins.typedrequest.TypedHandler('getClusters', async (dataArg, toolsArg) => {
|
|
await toolsArg!.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], dataArg);
|
|
const clusters = await this.getAllClusters();
|
|
return {
|
|
clusters: await Promise.all(
|
|
clusters.map((clusterArg) => clusterArg.createSavableObject()),
|
|
),
|
|
};
|
|
}),
|
|
);
|
|
|
|
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IReq_Any_Cloudly_GetClusterById>(
|
|
new plugins.typedrequest.TypedHandler('getClusterById', async (dataArg, toolsArg) => {
|
|
await toolsArg!.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], dataArg);
|
|
const cluster = await this.CCluster.getInstance({ id: (dataArg as any).clusterId });
|
|
if (!cluster) {
|
|
throw new plugins.typedrequest.TypedResponseError('Cluster not found');
|
|
}
|
|
return {
|
|
cluster: await cluster.createSavableObject(),
|
|
};
|
|
}),
|
|
);
|
|
|
|
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IReq_Any_Cloudly_UpdateCluster>(
|
|
new plugins.typedrequest.TypedHandler('updateCluster', async (dataArg, toolsArg) => {
|
|
await toolsArg!.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], dataArg);
|
|
const cluster = await this.CCluster.getInstance({ id: (dataArg as any).clusterId });
|
|
if (!cluster) {
|
|
throw new plugins.typedrequest.TypedResponseError('Cluster not found');
|
|
}
|
|
cluster.data = {
|
|
...cluster.data,
|
|
...dataArg.clusterData,
|
|
};
|
|
await cluster.save();
|
|
return {
|
|
resultCluster: await cluster.createSavableObject(),
|
|
};
|
|
}),
|
|
);
|
|
|
|
// delete cluster
|
|
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IReq_Any_Cloudly_DeleteClusterById>(
|
|
new plugins.typedrequest.TypedHandler('deleteClusterById', async (reqDataArg, toolsArg) => {
|
|
await toolsArg!.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], reqDataArg);
|
|
await this.deleteCluster(reqDataArg.clusterId);
|
|
return {
|
|
ok: true,
|
|
};
|
|
}),
|
|
);
|
|
}
|
|
|
|
public async init() {
|
|
// lets read the config folder
|
|
logger.log('info', 'config manager is now initializing');
|
|
this.ready.resolve();
|
|
}
|
|
|
|
/**
|
|
* gets a cluster config by Name
|
|
*/
|
|
public async getClusterConfigBy_ServerIP() {
|
|
await this.ready.promise;
|
|
// TODO: implement getclusterConfigByServerIp
|
|
}
|
|
|
|
public async getClusterBy_UserId(userIdArg: string) {
|
|
await this.ready.promise;
|
|
|
|
return await Cluster.getInstance({
|
|
data: {
|
|
userId: userIdArg,
|
|
},
|
|
});
|
|
}
|
|
|
|
public async getClusterBy_Identity(clusterIdentity: plugins.servezoneInterfaces.data.IIdentity) {
|
|
await this.ready.promise;
|
|
|
|
return await Cluster.getInstance({
|
|
data: {
|
|
userId: clusterIdentity.userId,
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* get config by id
|
|
*/
|
|
public async getConfigBy_ConfigID(configId: string) {
|
|
await this.ready.promise;
|
|
|
|
return await Cluster.getInstance({
|
|
id: configId,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* gets all cluster configs
|
|
*/
|
|
public async getAllClusters() {
|
|
await this.ready.promise;
|
|
|
|
return await Cluster.getInstances({});
|
|
}
|
|
|
|
/**
|
|
* creates a cluster (and a new user for it) and saves it
|
|
* @param configName
|
|
* @param configObjectArg
|
|
*/
|
|
public async createCluster(configObjectArg: plugins.servezoneInterfaces.data.ICluster) {
|
|
// lets create the cluster user
|
|
const clusterUser = new this.cloudlyRef.authManager.CUser({
|
|
id: await this.cloudlyRef.authManager.CUser.getNewId(),
|
|
data: {
|
|
username: `cluster-${configObjectArg.id}`,
|
|
role: 'cluster',
|
|
type: 'machine',
|
|
tokens: [
|
|
{
|
|
expiresAt: Date.now() + 3600 * 1000 * 24 * 365,
|
|
assignedRoles: ['cluster'],
|
|
token: await this.cloudlyRef.authManager.createNewSecureToken(),
|
|
},
|
|
],
|
|
},
|
|
});
|
|
await clusterUser.save();
|
|
configObjectArg.data.userId = clusterUser.id;
|
|
const clusterInstance = await Cluster.fromConfigObject(configObjectArg);
|
|
await clusterInstance.save();
|
|
return clusterInstance;
|
|
}
|
|
|
|
public async deleteCluster(clusterId: string) {
|
|
await this.ready.promise;
|
|
const clusterInstance = await Cluster.getInstance({ id: clusterId });
|
|
await clusterInstance.delete();
|
|
}
|
|
}
|