feat: per-workload resources, storage GiB metrics, optional service disks

- Expose DB/Redis/RabbitMQ usage plus sidecars in getResourceUsage
- Storage API: GiB fields, Redis/Rabbit PVC usage, fix du/exec container names
- PATCH /resources accepts workload; persist entity fields only for app
- App detail: workload cards, disk bars, DB expand, scale target select

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
keyhan
2026-05-14 16:28:01 +03:30
parent 0c0a6cd5be
commit b24d1505b6
5 changed files with 734 additions and 291 deletions
@@ -239,18 +239,28 @@ export class ApplicationsController {
const isStaff = req.user.role === UserRole.ADMIN || req.user.role === UserRole.TECHNICAL;
const app = await this.applicationsService.findOne(id, isStaff ? undefined : req.user.id);
const workload = dto.workload || 'app';
if (dto.replicas !== undefined && workload !== 'app') {
throw new BadRequestException('Replicas can only be changed for the main application workload.');
}
// Update in K8s (live)
await this.kubernetesService.updateResources(app, dto);
await this.kubernetesService.updateResources(app, dto, workload);
// Update in DB
// Update in DB — only main app resources are stored on the Application entity
const updateFields: any = {};
if (dto.cpuRequest) updateFields.cpuRequest = dto.cpuRequest;
if (dto.cpuLimit) updateFields.cpuLimit = dto.cpuLimit;
if (dto.memoryRequest) updateFields.memoryRequest = dto.memoryRequest;
if (dto.memoryLimit) updateFields.memoryLimit = dto.memoryLimit;
if (dto.replicas !== undefined) updateFields.replicas = dto.replicas;
if (workload === 'app') {
if (dto.cpuRequest) updateFields.cpuRequest = dto.cpuRequest;
if (dto.cpuLimit) updateFields.cpuLimit = dto.cpuLimit;
if (dto.memoryRequest) updateFields.memoryRequest = dto.memoryRequest;
if (dto.memoryLimit) updateFields.memoryLimit = dto.memoryLimit;
if (dto.replicas !== undefined) updateFields.replicas = dto.replicas;
}
const updated = await this.applicationsService.update(id, app.userId, updateFields);
const updated =
Object.keys(updateFields).length > 0
? await this.applicationsService.update(id, app.userId, updateFields)
: app;
this.logger.log(`Updated resources for ${app.name}: ${JSON.stringify(dto)}`);
return updated;
}