garbage collect all older than 1d as part of cleanup

pull/387/head
Frostebite 2022-04-19 19:24:53 +01:00
parent 8543c3ca5a
commit 04808b449d
6 changed files with 66 additions and 16 deletions

View File

@ -12,3 +12,20 @@ jobs:
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
expire-in: 21 days expire-in: 21 days
cleanupCloudRunner:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
if: github.event.event_type != 'pull_request_target'
with:
lfs: true
- uses: actions/setup-node@v2
with:
node-version: 12.x
- run: yarn
- run: yarn run cli -m aws-garbage-collect-all-1d-older
env:
AWS_REGION: eu-west-2
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: eu-west-2

27
dist/index.js vendored
View File

@ -1451,7 +1451,12 @@ class AwsCliCommands {
yield AwsCliCommands.cleanup(true); yield AwsCliCommands.cleanup(true);
}); });
} }
static cleanup(deleteResources = false) { static garbageCollectAwsAllOlderThanOneDay() {
return __awaiter(this, void 0, void 0, function* () {
yield AwsCliCommands.cleanup(true, 24);
});
}
static cleanup(deleteResources = false, olderThanAgeInHours = 0) {
var _a; var _a;
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
process.env.AWS_REGION = input_1.default.region; process.env.AWS_REGION = input_1.default.region;
@ -1480,20 +1485,27 @@ class AwsCliCommands {
taskElement.overrides = {}; taskElement.overrides = {};
taskElement.attachments = []; taskElement.attachments = [];
cloud_runner_logger_1.default.log(JSON.stringify(taskElement, undefined, 4)); cloud_runner_logger_1.default.log(JSON.stringify(taskElement, undefined, 4));
if (deleteResources) { if (taskElement.createdAt === undefined) {
cloud_runner_logger_1.default.log(`Skipping ${taskElement.taskDefinitionArn} no createdAt date`);
continue;
}
if (deleteResources &&
new Date(Date.now()).getUTCMilliseconds() - taskElement.createdAt.getUTCMilliseconds() > olderThanAgeInHours) {
yield ecs.stopTask({ task: taskElement.taskArn || '', cluster: element }).promise(); yield ecs.stopTask({ task: taskElement.taskArn || '', cluster: element }).promise();
} }
} }
} }
if (deleteResources) {
yield ecs.deleteCluster({ cluster: element }).promise();
}
} }
const stacks = ((_a = (yield CF.listStacks().promise()).StackSummaries) === null || _a === void 0 ? void 0 : _a.filter((_x) => _x.StackStatus !== 'DELETE_COMPLETE')) || []; const stacks = ((_a = (yield CF.listStacks().promise()).StackSummaries) === null || _a === void 0 ? void 0 : _a.filter((_x) => _x.StackStatus !== 'DELETE_COMPLETE')) || [];
for (const element of stacks) { for (const element of stacks) {
cloud_runner_logger_1.default.log(JSON.stringify(element, undefined, 4)); cloud_runner_logger_1.default.log(JSON.stringify(element, undefined, 4));
const deleteStackInput = { StackName: element.StackName }; const deleteStackInput = { StackName: element.StackName };
if (deleteResources) { if (element.StackName === 'game-ci' || element.TemplateDescription === 'Game-CI base stack') {
cloud_runner_logger_1.default.log(`Skipping ${element.StackName} ignore list`);
continue;
}
if (deleteResources &&
new Date(Date.now()).getUTCMilliseconds() - element.CreationTime.getUTCMilliseconds() > olderThanAgeInHours) {
yield CF.deleteStack(deleteStackInput).promise(); yield CF.deleteStack(deleteStackInput).promise();
} }
} }
@ -1509,6 +1521,9 @@ __decorate([
__decorate([ __decorate([
cli_functions_repository_1.CliFunction(`aws-garbage-collect-all`, `garbage collect aws`) cli_functions_repository_1.CliFunction(`aws-garbage-collect-all`, `garbage collect aws`)
], AwsCliCommands, "garbageCollectAwsAll", null); ], AwsCliCommands, "garbageCollectAwsAll", null);
__decorate([
cli_functions_repository_1.CliFunction(`aws-garbage-collect-all-1d-older`, `garbage collect aws`)
], AwsCliCommands, "garbageCollectAwsAllOlderThanOneDay", null);
exports.AwsCliCommands = AwsCliCommands; exports.AwsCliCommands = AwsCliCommands;

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -71,6 +71,7 @@ class AWSTaskRunner {
const wasSuccessful = exitCode === 0 || (exitCode === undefined && taskData.lastStatus === 'RUNNING'); const wasSuccessful = exitCode === 0 || (exitCode === undefined && taskData.lastStatus === 'RUNNING');
if (wasSuccessful) { if (wasSuccessful) {
CloudRunnerLogger.log(`Cloud runner job has finished successfully`); CloudRunnerLogger.log(`Cloud runner job has finished successfully`);
return { output, shouldCleanup }; return { output, shouldCleanup };
} else { } else {
if (taskData.stoppedReason === 'Essential container in task exited' && exitCode === 1) { if (taskData.stoppedReason === 'Essential container in task exited' && exitCode === 1) {
@ -144,6 +145,7 @@ class AWSTaskRunner {
shouldCleanup, shouldCleanup,
)); ));
} }
return { output, shouldCleanup }; return { output, shouldCleanup };
} }
@ -169,6 +171,7 @@ class AWSTaskRunner {
output, output,
shouldCleanup, shouldCleanup,
)); ));
return { iterator, shouldReadLogs, output, shouldCleanup }; return { iterator, shouldReadLogs, output, shouldCleanup };
} }
@ -187,6 +190,7 @@ class AWSTaskRunner {
} }
CloudRunnerLogger.log(`## Status of job: ${taskData.lastStatus}`); CloudRunnerLogger.log(`## Status of job: ${taskData.lastStatus}`);
} }
return { timestamp, shouldReadLogs }; return { timestamp, shouldReadLogs };
} }
@ -232,6 +236,7 @@ class AWSTaskRunner {
} }
} }
} }
return { shouldReadLogs, output, shouldCleanup }; return { shouldReadLogs, output, shouldCleanup };
} }

View File

@ -1,7 +1,5 @@
AWSTemplateFormatVersion: '2010-09-09' AWSTemplateFormatVersion: '2010-09-09'
Description: AWS Fargate cluster that can span public and private subnets. Supports Description: Game-CI base stack
public facing load balancers, private internal load balancers, and
both internal and external service discovery namespaces.
Parameters: Parameters:
EnvironmentName: EnvironmentName:
Type: String Type: String

View File

@ -12,8 +12,12 @@ export class AwsCliCommands {
static async garbageCollectAwsAll() { static async garbageCollectAwsAll() {
await AwsCliCommands.cleanup(true); await AwsCliCommands.cleanup(true);
} }
@CliFunction(`aws-garbage-collect-all-1d-older`, `garbage collect aws`)
static async garbageCollectAwsAllOlderThanOneDay() {
await AwsCliCommands.cleanup(true, 24);
}
private static async cleanup(deleteResources = false) { private static async cleanup(deleteResources = false, olderThanAgeInHours = 0) {
process.env.AWS_REGION = Input.region; process.env.AWS_REGION = Input.region;
CloudRunnerLogger.log(`Cloud Formation stacks`); CloudRunnerLogger.log(`Cloud Formation stacks`);
const CF = new AWS.CloudFormation(); const CF = new AWS.CloudFormation();
@ -40,21 +44,32 @@ export class AwsCliCommands {
taskElement.overrides = {}; taskElement.overrides = {};
taskElement.attachments = []; taskElement.attachments = [];
CloudRunnerLogger.log(JSON.stringify(taskElement, undefined, 4)); CloudRunnerLogger.log(JSON.stringify(taskElement, undefined, 4));
if (deleteResources) { if (taskElement.createdAt === undefined) {
CloudRunnerLogger.log(`Skipping ${taskElement.taskDefinitionArn} no createdAt date`);
continue;
}
if (
deleteResources &&
new Date(Date.now()).getUTCMilliseconds() - taskElement.createdAt.getUTCMilliseconds() > olderThanAgeInHours
) {
await ecs.stopTask({ task: taskElement.taskArn || '', cluster: element }).promise(); await ecs.stopTask({ task: taskElement.taskArn || '', cluster: element }).promise();
} }
} }
} }
if (deleteResources) {
await ecs.deleteCluster({ cluster: element }).promise();
}
} }
const stacks = const stacks =
(await CF.listStacks().promise()).StackSummaries?.filter((_x) => _x.StackStatus !== 'DELETE_COMPLETE') || []; (await CF.listStacks().promise()).StackSummaries?.filter((_x) => _x.StackStatus !== 'DELETE_COMPLETE') || [];
for (const element of stacks) { for (const element of stacks) {
CloudRunnerLogger.log(JSON.stringify(element, undefined, 4)); CloudRunnerLogger.log(JSON.stringify(element, undefined, 4));
const deleteStackInput: AWS.CloudFormation.DeleteStackInput = { StackName: element.StackName }; const deleteStackInput: AWS.CloudFormation.DeleteStackInput = { StackName: element.StackName };
if (deleteResources) { if (element.StackName === 'game-ci' || element.TemplateDescription === 'Game-CI base stack') {
CloudRunnerLogger.log(`Skipping ${element.StackName} ignore list`);
continue;
}
if (
deleteResources &&
new Date(Date.now()).getUTCMilliseconds() - element.CreationTime.getUTCMilliseconds() > olderThanAgeInHours
) {
await CF.deleteStack(deleteStackInput).promise(); await CF.deleteStack(deleteStackInput).promise();
} }
} }