import { DeleteStackCommand, DescribeStackResourcesCommand } from '@aws-sdk/client-cloudformation'; import { DeleteLogGroupCommand } from '@aws-sdk/client-cloudwatch-logs'; import { StopTaskCommand } from '@aws-sdk/client-ecs'; import Input from '../../../../input'; import OrchestratorLogger from '../../../services/core/orchestrator-logger'; import { TaskService } from './task-service'; import { AwsClientFactory } from '../aws-client-factory'; export class GarbageCollectionService { static isOlderThan1day(date: Date) { const ageDate = new Date(date.getTime() - Date.now()); return ageDate.getDay() > 0; } public static async cleanup(deleteResources = false, OneDayOlderOnly: boolean = false) { process.env.AWS_REGION = Input.region; const CF = AwsClientFactory.getCloudFormation(); const ecs = AwsClientFactory.getECS(); const cwl = AwsClientFactory.getCloudWatchLogs(); const taskDefinitionsInUse = new Array(); const tasks = await TaskService.getTasks(); for (const task of tasks) { const { taskElement, element } = task; taskDefinitionsInUse.push(taskElement.taskDefinitionArn); if (deleteResources && (!OneDayOlderOnly || GarbageCollectionService.isOlderThan1day(taskElement.createdAt!))) { OrchestratorLogger.log(`Stopping task ${taskElement.containers?.[0].name}`); await ecs.send(new StopTaskCommand({ task: taskElement.taskArn || '', cluster: element })); } } const jobStacks = await TaskService.getCloudFormationJobStacks(); for (const element of jobStacks) { if ( (await CF.send(new DescribeStackResourcesCommand({ StackName: element.StackName }))).StackResources?.some( (x) => x.ResourceType === 'AWS::ECS::TaskDefinition' && taskDefinitionsInUse.includes(x.PhysicalResourceId), ) ) { OrchestratorLogger.log(`Skipping ${element.StackName} - active task was running not deleting`); return; } if ( deleteResources && (!OneDayOlderOnly || (element.CreationTime && GarbageCollectionService.isOlderThan1day(element.CreationTime))) ) { if (element.StackName === 'game-ci' || element.TemplateDescription === 'Game-CI base stack') { OrchestratorLogger.log(`Skipping ${element.StackName} ignore list`); return; } OrchestratorLogger.log(`Deleting ${element.StackName}`); await CF.send(new DeleteStackCommand({ StackName: element.StackName })); } } const logGroups = await TaskService.getLogGroups(); for (const element of logGroups) { if ( deleteResources && (!OneDayOlderOnly || GarbageCollectionService.isOlderThan1day(new Date(element.creationTime!))) ) { OrchestratorLogger.log(`Deleting ${element.logGroupName}`); await cwl.send(new DeleteLogGroupCommand({ logGroupName: element.logGroupName || '' })); } } const locks = await TaskService.getLocks(); for (const element of locks) { OrchestratorLogger.log(`Lock: ${element.Key}`); } } }