import { Controller, Get, Post, Patch, Delete, Body, Param, UseGuards, } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger'; import { ClustersService } from './clusters.service'; import { CreateClusterDto, UpdateClusterDto } from './dto/cluster.dto'; import { CreateClusterPoolDto, UpdateClusterPoolDto } from './dto/cluster-pool.dto'; import { RolesGuard } from '../common/guards/roles.guard'; import { Roles } from '../common/decorators/roles.decorator'; import { UserRole } from '../common/enums'; @ApiTags('Clusters') @ApiBearerAuth() @Controller('clusters') @UseGuards(AuthGuard('jwt'), RolesGuard) export class ClustersController { constructor(private readonly clustersService: ClustersService) {} // ─── Admin-safe lookup endpoints (no end-user exposure) ─────────── @Get('public') @Roles(UserRole.ADMIN) @ApiOperation({ summary: 'List available clusters (public info, no kubeconfig)' }) async findAllPublic() { return this.clustersService.findAllPublic(); } @Get('pools/public') @Roles(UserRole.ADMIN) @ApiOperation({ summary: 'List active cluster pools with resolved cluster names' }) async findAllPoolsPublic() { return this.clustersService.findAllPoolsPublic(); } // ─── Cluster admin endpoints ────────────────────────────────────── @Post() @Roles(UserRole.ADMIN) @ApiOperation({ summary: 'Register a new Kubernetes cluster (Admin)' }) async create(@Body() dto: CreateClusterDto) { return this.clustersService.create(dto); } @Get() @Roles(UserRole.ADMIN) @ApiOperation({ summary: 'List all clusters (Admin)' }) async findAll() { return this.clustersService.findAll(); } // ─── Cluster Pool admin endpoints ───────────────────────────────── @Post('pools') @Roles(UserRole.ADMIN) @ApiOperation({ summary: 'Create a cluster pool for load balancing (Admin)' }) async createPool(@Body() dto: CreateClusterPoolDto) { return this.clustersService.createPool(dto); } @Get('pools') @Roles(UserRole.ADMIN) @ApiOperation({ summary: 'List all cluster pools (Admin)' }) async findAllPools() { return this.clustersService.findAllPools(); } @Get('pools/:id') @Roles(UserRole.ADMIN) @ApiOperation({ summary: 'Get cluster pool details (Admin)' }) async findOnePool(@Param('id') id: string) { return this.clustersService.findOnePool(id); } @Patch('pools/:id') @Roles(UserRole.ADMIN) @ApiOperation({ summary: 'Update cluster pool (Admin)' }) async updatePool(@Param('id') id: string, @Body() dto: UpdateClusterPoolDto) { return this.clustersService.updatePool(id, dto); } @Delete('pools/:id') @Roles(UserRole.ADMIN) @ApiOperation({ summary: 'Delete a cluster pool (Admin)' }) async deletePool(@Param('id') id: string) { await this.clustersService.deletePool(id); return { message: 'Cluster pool deleted' }; } @Get('allocation-logs') @Roles(UserRole.ADMIN) @ApiOperation({ summary: 'List recent cluster allocation decisions (Admin)' }) async listAllocationLogs() { return this.clustersService.listAllocationLogs(); } @Get(':id/resources') @Roles(UserRole.ADMIN) @ApiOperation({ summary: 'Get cluster resource usage - nodes, CPU, memory, pods (Admin)' }) async getClusterResources(@Param('id') id: string) { return this.clustersService.getClusterResources(id); } @Get(':id') @Roles(UserRole.ADMIN) @ApiOperation({ summary: 'Get cluster details (Admin)' }) async findOne(@Param('id') id: string) { const { kubeconfig, ...cluster } = await this.clustersService.findOne(id); return cluster; } @Patch(':id') @Roles(UserRole.ADMIN) @ApiOperation({ summary: 'Update cluster configuration (Admin)' }) async update(@Param('id') id: string, @Body() dto: UpdateClusterDto) { return this.clustersService.update(id, dto); } @Post(':id/test') @Roles(UserRole.ADMIN) @ApiOperation({ summary: 'Test connectivity to a registered cluster (Admin)' }) async testConnection(@Param('id') id: string) { return this.clustersService.testClusterById(id); } @Delete(':id') @Roles(UserRole.ADMIN) @ApiOperation({ summary: 'Remove a cluster (Admin)' }) async delete(@Param('id') id: string) { await this.clustersService.delete(id); return { message: 'Cluster deleted' }; } }