Add automatic cluster pool allocation.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -23,49 +23,35 @@ export class ApplicationsService {
|
||||
) {}
|
||||
|
||||
async create(userId: string, dto: CreateApplicationDto, userRole?: string): Promise<Application> {
|
||||
// Only admin/technical users can manually select cluster or pool
|
||||
// Regular users always get the default cluster assignment
|
||||
if (userRole !== UserRole.ADMIN && userRole !== UserRole.TECHNICAL) {
|
||||
// End users and technical staff cannot influence placement; only admins may manually assign.
|
||||
const isAdmin = userRole === UserRole.ADMIN;
|
||||
if (!isAdmin) {
|
||||
if (dto.clusterId || dto.poolId) {
|
||||
this.logger.warn(`Non-admin user ${userId} attempted manual cluster/pool selection — ignoring`);
|
||||
this.logger.warn(`Non-admin user ${userId} attempted manual cluster/pool selection - ignoring`);
|
||||
}
|
||||
dto.clusterId = undefined;
|
||||
dto.poolId = undefined;
|
||||
}
|
||||
|
||||
// Cluster assignment: 3 modes
|
||||
// 1. Manual: specific clusterId provided
|
||||
// 2. Pool-based LB: poolId provided → pick from pool using pool's strategy
|
||||
// 3. Default fallback: no clusterId/poolId → use default cluster
|
||||
|
||||
let clusterId = dto.clusterId;
|
||||
let poolId = dto.poolId;
|
||||
let allocationLogId: string | undefined;
|
||||
|
||||
if (!clusterId) {
|
||||
if (poolId) {
|
||||
// Mode 2: Pool-based load balancing
|
||||
try {
|
||||
const optimal = await this.clustersService.getOptimalClusterFromPool(poolId);
|
||||
clusterId = optimal.id;
|
||||
this.logger.log(`Pool-assigned cluster "${optimal.name}" to app "${dto.name}" (pool LB)`);
|
||||
} catch (err: any) {
|
||||
this.logger.warn(`Pool assignment failed for app "${dto.name}": ${err.message}`);
|
||||
poolId = undefined; // Clear invalid pool
|
||||
}
|
||||
}
|
||||
|
||||
// Mode 3: Default fallback (no manual cluster, no pool, or pool failed)
|
||||
if (!clusterId) {
|
||||
try {
|
||||
const defaultCluster = await this.clustersService.getDefault();
|
||||
clusterId = defaultCluster.id;
|
||||
this.logger.log(`Default-assigned cluster "${defaultCluster.name}" to app "${dto.name}"`);
|
||||
} catch {
|
||||
this.logger.warn('No cluster available — app will be created without cluster assignment');
|
||||
}
|
||||
}
|
||||
if (isAdmin && clusterId) {
|
||||
await this.clustersService.findOne(clusterId);
|
||||
this.logger.log(`Manual cluster assignment for app "${dto.name}" -> cluster ${clusterId}`);
|
||||
} else {
|
||||
this.logger.log(`Manual cluster assignment for app "${dto.name}" → cluster ${clusterId}`);
|
||||
const allocationDto = { ...dto };
|
||||
if (poolId) {
|
||||
allocationDto.poolId = poolId;
|
||||
}
|
||||
const allocation = await this.clustersService.selectClusterForApplication(allocationDto, userId);
|
||||
clusterId = allocation.cluster.id;
|
||||
poolId = allocation.pool?.id || (isAdmin ? poolId : undefined);
|
||||
allocationLogId = allocation.allocationLogId;
|
||||
if (!clusterId) {
|
||||
throw new BadRequestException('No eligible cluster available for this application');
|
||||
}
|
||||
}
|
||||
|
||||
// Generate database credentials if a database is requested
|
||||
@@ -109,7 +95,11 @@ export class ApplicationsService {
|
||||
platformDomain,
|
||||
),
|
||||
});
|
||||
return this.appsRepository.save(app);
|
||||
const saved = await this.appsRepository.save(app);
|
||||
if (allocationLogId) {
|
||||
await this.clustersService.attachAllocationToApplication(allocationLogId, saved.id);
|
||||
}
|
||||
return saved;
|
||||
}
|
||||
|
||||
async findAllByUser(userId: string): Promise<Application[]> {
|
||||
|
||||
Reference in New Issue
Block a user