diff --git a/dist/index.js b/dist/index.js index f0f5b43a..b0c3e08c 100644 Binary files a/dist/index.js and b/dist/index.js differ diff --git a/dist/index.js.map b/dist/index.js.map index 815e1827..7a7ce7a1 100644 Binary files a/dist/index.js.map and b/dist/index.js.map differ diff --git a/dist/licenses.txt b/dist/licenses.txt index 497a23d4..8fe403fd 100644 Binary files a/dist/licenses.txt and b/dist/licenses.txt differ diff --git a/src/model/cloud-runner/providers/aws/services/garbage-collection-service.ts b/src/model/cloud-runner/providers/aws/services/garbage-collection-service.ts index 27d299da..ccdddf7a 100644 --- a/src/model/cloud-runner/providers/aws/services/garbage-collection-service.ts +++ b/src/model/cloud-runner/providers/aws/services/garbage-collection-service.ts @@ -1,4 +1,11 @@ -import AWS from 'aws-sdk'; +import { + CloudFormation, + DeleteStackCommand, + DeleteStackCommandInput, + DescribeStackResourcesCommand, +} from '@aws-sdk/client-cloudformation'; +import { CloudWatchLogs, DeleteLogGroupCommand } from '@aws-sdk/client-cloudwatch-logs'; +import { ECS, StopTaskCommand } from '@aws-sdk/client-ecs'; import Input from '../../../../input'; import CloudRunnerLogger from '../../../services/core/cloud-runner-logger'; import { TaskService } from './task-service'; @@ -12,9 +19,9 @@ export class GarbageCollectionService { public static async cleanup(deleteResources = false, OneDayOlderOnly: boolean = false) { process.env.AWS_REGION = Input.region; - const CF = new AWS.CloudFormation(); - const ecs = new AWS.ECS(); - const cwl = new AWS.CloudWatchLogs(); + const CF = new CloudFormation({ region: Input.region }); + const ecs = new ECS({ region: Input.region }); + const cwl = new CloudWatchLogs({ region: Input.region }); const taskDefinitionsInUse = new Array(); const tasks = await TaskService.getTasks(); @@ -23,14 +30,14 @@ export class GarbageCollectionService { taskDefinitionsInUse.push(taskElement.taskDefinitionArn); if (deleteResources && (!OneDayOlderOnly || GarbageCollectionService.isOlderThan1day(taskElement.createdAt!))) { CloudRunnerLogger.log(`Stopping task ${taskElement.containers?.[0].name}`); - await ecs.stopTask({ task: taskElement.taskArn || '', cluster: element }).promise(); + await ecs.send(new StopTaskCommand({ task: taskElement.taskArn || '', cluster: element })); } } const jobStacks = await TaskService.getCloudFormationJobStacks(); for (const element of jobStacks) { if ( - (await CF.describeStackResources({ StackName: element.StackName }).promise()).StackResources?.some( + (await CF.send(new DescribeStackResourcesCommand({ StackName: element.StackName }))).StackResources?.some( (x) => x.ResourceType === 'AWS::ECS::TaskDefinition' && taskDefinitionsInUse.includes(x.PhysicalResourceId), ) ) { @@ -39,7 +46,10 @@ export class GarbageCollectionService { return; } - if (deleteResources && (!OneDayOlderOnly || GarbageCollectionService.isOlderThan1day(element.CreationTime))) { + if ( + deleteResources && + (!OneDayOlderOnly || (element.CreationTime && GarbageCollectionService.isOlderThan1day(element.CreationTime))) + ) { if (element.StackName === 'game-ci' || element.TemplateDescription === 'Game-CI base stack') { CloudRunnerLogger.log(`Skipping ${element.StackName} ignore list`); @@ -47,8 +57,8 @@ export class GarbageCollectionService { } CloudRunnerLogger.log(`Deleting ${element.StackName}`); - const deleteStackInput: AWS.CloudFormation.DeleteStackInput = { StackName: element.StackName }; - await CF.deleteStack(deleteStackInput).promise(); + const deleteStackInput: DeleteStackCommandInput = { StackName: element.StackName }; + await CF.send(new DeleteStackCommand(deleteStackInput)); } } const logGroups = await TaskService.getLogGroups(); @@ -58,7 +68,7 @@ export class GarbageCollectionService { (!OneDayOlderOnly || GarbageCollectionService.isOlderThan1day(new Date(element.creationTime!))) ) { CloudRunnerLogger.log(`Deleting ${element.logGroupName}`); - await cwl.deleteLogGroup({ logGroupName: element.logGroupName || '' }).promise(); + await cwl.send(new DeleteLogGroupCommand({ logGroupName: element.logGroupName || '' })); } } diff --git a/src/model/cloud-runner/providers/aws/services/task-service.ts b/src/model/cloud-runner/providers/aws/services/task-service.ts index ee5fb5c0..e0ecfcd8 100644 --- a/src/model/cloud-runner/providers/aws/services/task-service.ts +++ b/src/model/cloud-runner/providers/aws/services/task-service.ts @@ -1,12 +1,31 @@ -import AWS from 'aws-sdk'; +import { + CloudFormation, + DescribeStackResourcesCommand, + DescribeStacksCommand, + ListStacksCommand, + StackSummary, +} from '@aws-sdk/client-cloudformation'; +import { + CloudWatchLogs, + DescribeLogGroupsCommand, + DescribeLogGroupsCommandInput, + LogGroup, +} from '@aws-sdk/client-cloudwatch-logs'; +import { + DescribeTasksCommand, + DescribeTasksCommandInput, + ECS, + ListClustersCommand, + ListTasksCommand, + ListTasksCommandInput, + Task, +} from '@aws-sdk/client-ecs'; +import { ListObjectsCommand, ListObjectsCommandInput, S3 } from '@aws-sdk/client-s3'; import Input from '../../../../input'; import CloudRunnerLogger from '../../../services/core/cloud-runner-logger'; import { BaseStackFormation } from '../cloud-formations/base-stack-formation'; import AwsTaskRunner from '../aws-task-runner'; -import { ListObjectsRequest } from 'aws-sdk/clients/s3'; import CloudRunner from '../../../cloud-runner'; -import { StackSummaries } from 'aws-sdk/clients/cloudformation'; -import { LogGroups } from 'aws-sdk/clients/cloudwatchlogs'; export class TaskService { static async watch() { @@ -20,20 +39,24 @@ export class TaskService { return output; } public static async getCloudFormationJobStacks() { - const result: StackSummaries = []; + const result: StackSummary[] = []; CloudRunnerLogger.log(``); CloudRunnerLogger.log(`List Cloud Formation Stacks`); process.env.AWS_REGION = Input.region; - const CF = new AWS.CloudFormation(); + const CF = new CloudFormation({ region: Input.region }); const stacks = - (await CF.listStacks().promise()).StackSummaries?.filter( + (await CF.send(new ListStacksCommand({}))).StackSummaries?.filter( (_x) => _x.StackStatus !== 'DELETE_COMPLETE' && _x.TemplateDescription !== BaseStackFormation.baseStackDecription, ) || []; CloudRunnerLogger.log(``); CloudRunnerLogger.log(`Cloud Formation Stacks ${stacks.length}`); for (const element of stacks) { - const ageDate: Date = new Date(Date.now() - element.CreationTime.getTime()); + if (!element.CreationTime) { + CloudRunnerLogger.log(`${element.StackName} due to undefined CreationTime`); + } + + const ageDate: Date = new Date(Date.now() - (element.CreationTime?.getTime() ?? 0)); CloudRunnerLogger.log( `Task Stack ${element.StackName} - Age D${Math.floor( @@ -43,14 +66,18 @@ export class TaskService { result.push(element); } const baseStacks = - (await CF.listStacks().promise()).StackSummaries?.filter( + (await CF.send(new ListStacksCommand({}))).StackSummaries?.filter( (_x) => _x.StackStatus !== 'DELETE_COMPLETE' && _x.TemplateDescription === BaseStackFormation.baseStackDecription, ) || []; CloudRunnerLogger.log(``); CloudRunnerLogger.log(`Base Stacks ${baseStacks.length}`); for (const element of baseStacks) { - const ageDate: Date = new Date(Date.now() - element.CreationTime.getTime()); + if (!element.CreationTime) { + CloudRunnerLogger.log(`${element.StackName} due to undefined CreationTime`); + } + + const ageDate: Date = new Date(Date.now() - (element.CreationTime?.getTime() ?? 0)); CloudRunnerLogger.log( `Task Stack ${element.StackName} - Age D${Math.floor( @@ -64,22 +91,22 @@ export class TaskService { return result; } public static async getTasks() { - const result: { taskElement: AWS.ECS.Task; element: string }[] = []; + const result: { taskElement: Task; element: string }[] = []; CloudRunnerLogger.log(``); CloudRunnerLogger.log(`List Tasks`); process.env.AWS_REGION = Input.region; - const ecs = new AWS.ECS(); - const clusters = (await ecs.listClusters().promise()).clusterArns || []; + const ecs = new ECS({ region: Input.region }); + const clusters = (await ecs.send(new ListClustersCommand({}))).clusterArns || []; CloudRunnerLogger.log(`Task Clusters ${clusters.length}`); for (const element of clusters) { - const input: AWS.ECS.ListTasksRequest = { + const input: ListTasksCommandInput = { cluster: element, }; - const list = (await ecs.listTasks(input).promise()).taskArns || []; + const list = (await ecs.send(new ListTasksCommand(input))).taskArns || []; if (list.length > 0) { - const describeInput: AWS.ECS.DescribeTasksRequest = { tasks: list, cluster: element }; - const describeList = (await ecs.describeTasks(describeInput).promise()).tasks || []; + const describeInput: DescribeTasksCommandInput = { tasks: list, cluster: element }; + const describeList = (await ecs.send(new DescribeTasksCommand(describeInput))).tasks || []; if (describeList.length === 0) { CloudRunnerLogger.log(`No Tasks`); continue; @@ -105,14 +132,18 @@ export class TaskService { } public static async awsDescribeJob(job: string) { process.env.AWS_REGION = Input.region; - const CF = new AWS.CloudFormation(); - const stack = (await CF.listStacks().promise()).StackSummaries?.find((_x) => _x.StackName === job) || undefined; - const stackInfo = (await CF.describeStackResources({ StackName: job }).promise()) || undefined; - const stackInfo2 = (await CF.describeStacks({ StackName: job }).promise()) || undefined; + const CF = new CloudFormation({ region: Input.region }); + const stack = + (await CF.send(new ListStacksCommand({}))).StackSummaries?.find((_x) => _x.StackName === job) || undefined; + const stackInfo = (await CF.send(new DescribeStackResourcesCommand({ StackName: job }))) || undefined; + const stackInfo2 = (await CF.send(new DescribeStacksCommand({ StackName: job }))) || undefined; if (stack === undefined) { throw new Error('stack not defined'); } - const ageDate: Date = new Date(Date.now() - stack.CreationTime.getTime()); + if (!stack.CreationTime) { + CloudRunnerLogger.log(`${stack.StackName} due to undefined CreationTime`); + } + const ageDate: Date = new Date(Date.now() - (stack.CreationTime?.getTime() ?? 0)); const message = ` Task Stack ${stack.StackName} Age D${Math.floor(ageDate.getHours() / 24)} H${ageDate.getHours()} M${ageDate.getMinutes()} @@ -125,17 +156,17 @@ export class TaskService { return message; } public static async getLogGroups() { - const result: LogGroups = []; + const result: Array = []; process.env.AWS_REGION = Input.region; - const ecs = new AWS.CloudWatchLogs(); - let logStreamInput: AWS.CloudWatchLogs.DescribeLogGroupsRequest = { + const ecs = new CloudWatchLogs(); + let logStreamInput: DescribeLogGroupsCommandInput = { /* logGroupNamePrefix: 'game-ci' */ }; - let logGroupsDescribe = await ecs.describeLogGroups(logStreamInput).promise(); + let logGroupsDescribe = await ecs.send(new DescribeLogGroupsCommand(logStreamInput)); const logGroups = logGroupsDescribe.logGroups || []; while (logGroupsDescribe.nextToken) { logStreamInput = { /* logGroupNamePrefix: 'game-ci',*/ nextToken: logGroupsDescribe.nextToken }; - logGroupsDescribe = await ecs.describeLogGroups(logStreamInput).promise(); + logGroupsDescribe = await ecs.send(new DescribeLogGroupsCommand(logStreamInput)); logGroups.push(...(logGroupsDescribe?.logGroups || [])); } @@ -159,11 +190,12 @@ export class TaskService { } public static async getLocks() { process.env.AWS_REGION = Input.region; - const s3 = new AWS.S3(); - const listRequest: ListObjectsRequest = { + const s3 = new S3({ region: Input.region }); + const listRequest: ListObjectsCommandInput = { Bucket: CloudRunner.buildParameters.awsStackName, }; - const results = await s3.listObjects(listRequest).promise(); + + const results = await s3.send(new ListObjectsCommand(listRequest)); return results.Contents || []; }