From 2b0e847f6c951da5a84af7f6af5904975fcc737a Mon Sep 17 00:00:00 2001 From: Leandro Rodrigues Date: Wed, 28 Apr 2021 17:53:40 -0300 Subject: [PATCH 1/2] Fix logs query aggregating all logs Signed-off-by: Leandro Rodrigues --- .../controller/deployments.controller.ts | 3 +-- .../deployments/repository/log.repository.ts | 18 ++++++++++-------- .../find-deployment-logs-by-id.usecase.ts | 4 ++-- .../use-cases/receive-notification.usecase.ts | 5 ----- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/butler/src/app/v2/api/deployments/controller/deployments.controller.ts b/butler/src/app/v2/api/deployments/controller/deployments.controller.ts index c7f23fb0c6..6696ead254 100644 --- a/butler/src/app/v2/api/deployments/controller/deployments.controller.ts +++ b/butler/src/app/v2/api/deployments/controller/deployments.controller.ts @@ -60,9 +60,8 @@ export class DeploymentsController { @UsePipes(new ValidationPipe({ transform: true })) public async findDeploymentEvents( @Param('id') deploymentId: string, - @Headers('x-workspace-id') workspaceId: string, ): Promise { - return this.findDeploymentLogsByIdUseCase.execute(deploymentId, workspaceId) + return this.findDeploymentLogsByIdUseCase.execute(deploymentId) } @Post('/:id/undeploy') diff --git a/butler/src/app/v2/api/deployments/repository/log.repository.ts b/butler/src/app/v2/api/deployments/repository/log.repository.ts index ff231063f3..f4511cf786 100644 --- a/butler/src/app/v2/api/deployments/repository/log.repository.ts +++ b/butler/src/app/v2/api/deployments/repository/log.repository.ts @@ -20,15 +20,17 @@ import { LogEntity } from '../entity/logs.entity' @EntityRepository(LogEntity) export class LogRepository extends Repository { - public async findDeploymentLogs(deploymentId: string, workspaceId?: string): Promise { - const queryBuilder = this.createQueryBuilder('v2logs') - .leftJoinAndSelect('v2logs.deployment', 'deployment') - .andWhere('deployment.id = :deploymentId', { deploymentId }) + public async findDeploymentLogs(deploymentId: string): Promise { + const logEntries = await this.query(` + SELECT l.deployment_id, json_agg((select * from jsonb_array_elements(l.logs))) as logs + FROM v2logs l + WHERE l.deployment_id = $1 + GROUP BY deployment_id`, [deploymentId]) - return workspaceId ? - queryBuilder.leftJoinAndSelect('deployment.cdConfiguration', 'c') - .andWhere('c.workspaceId = :workspaceId', { workspaceId }).getOne() : - queryBuilder.getOne() + return this.toLogEntity(deploymentId, logEntries) } + private toLogEntity(deploymentId: string, logEntries: LogEntity[]) { + return new LogEntity(deploymentId, logEntries ? logEntries.flatMap(e => e.logs) : []) + } } diff --git a/butler/src/app/v2/api/deployments/use-cases/find-deployment-logs-by-id.usecase.ts b/butler/src/app/v2/api/deployments/use-cases/find-deployment-logs-by-id.usecase.ts index a6fe10f1b7..308bb72413 100644 --- a/butler/src/app/v2/api/deployments/use-cases/find-deployment-logs-by-id.usecase.ts +++ b/butler/src/app/v2/api/deployments/use-cases/find-deployment-logs-by-id.usecase.ts @@ -25,8 +25,8 @@ export class FindDeploymentLogsByIdUsecase { private readonly logsRepository: LogRepository ){} - public async execute(deploymentId: string, workspaceId: string): Promise { - const deploymentLogs = await this.logsRepository.findDeploymentLogs(deploymentId, workspaceId) + public async execute(deploymentId: string): Promise { + const deploymentLogs = await this.logsRepository.findDeploymentLogs(deploymentId) if (!deploymentLogs) { throw new NotFoundException(`No logs found associated with the deployment: ${deploymentId}`) } diff --git a/butler/src/app/v2/api/deployments/use-cases/receive-notification.usecase.ts b/butler/src/app/v2/api/deployments/use-cases/receive-notification.usecase.ts index 6514943197..2759ae39c5 100644 --- a/butler/src/app/v2/api/deployments/use-cases/receive-notification.usecase.ts +++ b/butler/src/app/v2/api/deployments/use-cases/receive-notification.usecase.ts @@ -182,11 +182,6 @@ export class ReceiveNotificationUseCase { } private async getDeploymentLogs(deploymentNotificationDto: DeploymentNotificationRequestDto, deployment: DeploymentEntityV2) { - const deploymentLogs = await this.logRepository.findDeploymentLogs(deployment.id) - if (deploymentLogs) { - deploymentLogs.concatLogs(deploymentNotificationDto.logs) - return deploymentLogs - } return new LogEntity(deployment.id, deploymentNotificationDto.logs) } } From 1760f88c3acf18ae0aafc084154f047ebb83ffff Mon Sep 17 00:00:00 2001 From: Leandro Rodrigues Date: Thu, 29 Apr 2021 10:50:32 -0300 Subject: [PATCH 2/2] Add integration tests for logs endpoint Signed-off-by: Leandro Rodrigues --- .../deployment.controller.integration-spec.ts | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/butler/src/tests/v2/integration/controllers/deployment.controller.integration-spec.ts b/butler/src/tests/v2/integration/controllers/deployment.controller.integration-spec.ts index b5d946df9d..34b0a9c1fb 100644 --- a/butler/src/tests/v2/integration/controllers/deployment.controller.integration-spec.ts +++ b/butler/src/tests/v2/integration/controllers/deployment.controller.integration-spec.ts @@ -26,6 +26,7 @@ import { UrlConstants } from '../test-constants' import { TestSetupUtils } from '../test-setup-utils' import { EntityManager } from 'typeorm' import { ComponentEntityV2 } from '../../../../app/v2/api/deployments/entity/component.entity' +import { LogEntity } from '../../../../app/v2/api/deployments/entity/logs.entity' describe('DeploymentController v2', () => { let fixtureUtilsService: FixtureUtilsService @@ -1001,4 +1002,60 @@ BSAwlmwpOpK27k2yXj4g1x2VaF9GGl//Ere+xUY= expect(response.body).toEqual(errorResponse) }) }) + + it('returns logs from deployment id', async() => { + const deploymentId = '6d1e1881-72d3-4fb5-84da-8bd61bb8e2d3' + const deployment = new DeploymentEntityV2( + deploymentId, + '580a7726-a274-4fc3-9ec1-44e3563d58af', + 'ad03d665-f689-42aa-b1de-d19653e89b86', + UrlConstants.deploymentCallbackUrl, + [ + new ComponentEntityV2( + UrlConstants.helmRepository, + 'currenttag', + 'imageurl.com:currenttag', + 'my-component', + '777765f8-bb29-49f7-bf2b-3ec956a71583', + 'host-value-1', + 'gateway-name-1', + [] + ) + ], + true, + 'default', + 120, + ) + + await manager.save(deployment) + + const log = new LogEntity ( + deploymentId, + [ + { + type: 'INFO', + title: 'Created', + details: '{"message":"Container image "paulczar/gb-frontend:v5" already present on machine","object":"Pod/frontend-7cb5fb8b96-prqxv"}', + timestamp: '2021-04-29T10:17:24-03:00' + } + ] + ) + await manager.save(log) + + await request(app.getHttpServer()) + .get(`/v2/deployments/${deploymentId}/logs`) + .expect(200) + .expect(response => { + expect(response.body).toEqual({ + logs: [ + { + type: 'INFO', + title: 'Created', + details: '{"message":"Container image "paulczar/gb-frontend:v5" already present on machine","object":"Pod/frontend-7cb5fb8b96-prqxv"}', + timestamp: '2021-04-29T10:17:24-03:00' + } + ] + }) + }) + }) })