Cleanup log streaming dependencies to enable cli option

pull/419/head
Frostebite 2022-08-02 20:21:46 +01:00
parent 6ffc4c6508
commit 824f017b0b
6 changed files with 95 additions and 107 deletions

93
dist/index.js vendored
View File

@ -1354,7 +1354,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const AWS = __importStar(__nccwpck_require__(71786));
const core = __importStar(__nccwpck_require__(42186));
const zlib = __importStar(__nccwpck_require__(59796));
const cloud_runner_logger_1 = __importDefault(__nccwpck_require__(22855));
@ -1363,7 +1362,7 @@ const cloud_runner_1 = __importDefault(__nccwpck_require__(79144));
const cloud_runner_custom_hooks_1 = __nccwpck_require__(58873);
const follow_log_stream_service_1 = __nccwpck_require__(64121);
class AWSTaskRunner {
static runTask(taskDef, ECS, CF, environment, buildGuid, commands) {
static runTask(taskDef, environment, commands) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
return __awaiter(this, void 0, void 0, function* () {
const cluster = ((_b = (_a = taskDef.baseResources) === null || _a === void 0 ? void 0 : _a.find((x) => x.LogicalResourceId === 'ECSCluster')) === null || _b === void 0 ? void 0 : _b.PhysicalResourceId) || '';
@ -1372,7 +1371,7 @@ class AWSTaskRunner {
const SubnetTwo = ((_h = (_g = taskDef.baseResources) === null || _g === void 0 ? void 0 : _g.find((x) => x.LogicalResourceId === 'PublicSubnetTwo')) === null || _h === void 0 ? void 0 : _h.PhysicalResourceId) || '';
const ContainerSecurityGroup = ((_k = (_j = taskDef.baseResources) === null || _j === void 0 ? void 0 : _j.find((x) => x.LogicalResourceId === 'ContainerSecurityGroup')) === null || _k === void 0 ? void 0 : _k.PhysicalResourceId) || '';
const streamName = ((_m = (_l = taskDef.taskDefResources) === null || _l === void 0 ? void 0 : _l.find((x) => x.LogicalResourceId === 'KinesisStream')) === null || _m === void 0 ? void 0 : _m.PhysicalResourceId) || '';
const task = yield ECS.runTask({
const task = yield AWSTaskRunner.ECS.runTask({
cluster,
taskDefinition,
platformVersion: '1.4.0',
@ -1396,10 +1395,10 @@ class AWSTaskRunner {
}).promise();
const taskArn = ((_o = task.tasks) === null || _o === void 0 ? void 0 : _o[0].taskArn) || '';
cloud_runner_logger_1.default.log('Cloud runner job is starting');
yield AWSTaskRunner.waitUntilTaskRunning(ECS, taskArn, cluster);
cloud_runner_logger_1.default.log(`Cloud runner job status is running ${(_p = (yield AWSTaskRunner.describeTasks(ECS, cluster, taskArn))) === null || _p === void 0 ? void 0 : _p.lastStatus}`);
const { output, shouldCleanup } = yield this.streamLogsUntilTaskStops(ECS, CF, taskDef, cluster, taskArn, streamName);
const taskData = yield AWSTaskRunner.describeTasks(ECS, cluster, taskArn);
yield AWSTaskRunner.waitUntilTaskRunning(taskArn, cluster);
cloud_runner_logger_1.default.log(`Cloud runner job status is running ${(_p = (yield AWSTaskRunner.describeTasks(cluster, taskArn))) === null || _p === void 0 ? void 0 : _p.lastStatus}`);
const { output, shouldCleanup } = yield this.streamLogsUntilTaskStops(cluster, taskArn, streamName);
const taskData = yield AWSTaskRunner.describeTasks(cluster, taskArn);
const exitCode = (_q = taskData.containers) === null || _q === void 0 ? void 0 : _q[0].exitCode;
const wasSuccessful = exitCode === 0 || (exitCode === undefined && taskData.lastStatus === 'RUNNING');
if (wasSuccessful) {
@ -1418,25 +1417,25 @@ class AWSTaskRunner {
}
});
}
static waitUntilTaskRunning(ECS, taskArn, cluster) {
static waitUntilTaskRunning(taskArn, cluster) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
try {
yield ECS.waitFor('tasksRunning', { tasks: [taskArn], cluster }).promise();
yield AWSTaskRunner.ECS.waitFor('tasksRunning', { tasks: [taskArn], cluster }).promise();
}
catch (error_) {
const error = error_;
yield new Promise((resolve) => setTimeout(resolve, 3000));
cloud_runner_logger_1.default.log(`Cloud runner job has ended ${(_a = (yield AWSTaskRunner.describeTasks(ECS, cluster, taskArn)).containers) === null || _a === void 0 ? void 0 : _a[0].lastStatus}`);
cloud_runner_logger_1.default.log(`Cloud runner job has ended ${(_a = (yield AWSTaskRunner.describeTasks(cluster, taskArn)).containers) === null || _a === void 0 ? void 0 : _a[0].lastStatus}`);
core.setFailed(error);
core.error(error);
}
});
}
static describeTasks(ECS, clusterName, taskArn) {
static describeTasks(clusterName, taskArn) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const tasks = yield ECS.describeTasks({
const tasks = yield AWSTaskRunner.ECS.describeTasks({
cluster: clusterName,
tasks: [taskArn],
}).promise();
@ -1448,11 +1447,10 @@ class AWSTaskRunner {
}
});
}
static streamLogsUntilTaskStops(ECS, CF, taskDef, clusterName, taskArn, kinesisStreamName) {
static streamLogsUntilTaskStops(clusterName, taskArn, kinesisStreamName) {
return __awaiter(this, void 0, void 0, function* () {
const kinesis = new AWS.Kinesis();
const stream = yield AWSTaskRunner.getLogStream(kinesis, kinesisStreamName);
let iterator = yield AWSTaskRunner.getLogIterator(kinesis, stream);
const stream = yield AWSTaskRunner.getLogStream(kinesisStreamName);
let iterator = yield AWSTaskRunner.getLogIterator(stream);
const logBaseUrl = `https://${__1.Input.region}.console.aws.amazon.com/cloudwatch/home?region=${__1.Input.region}#logsV2:log-groups/log-group/${cloud_runner_1.default.buildParameters.awsBaseStackName}-${cloud_runner_1.default.buildParameters.buildGuid}`;
cloud_runner_logger_1.default.log(`You view the log stream on AWS Cloud Watch: ${logBaseUrl}`);
let shouldReadLogs = true;
@ -1461,22 +1459,20 @@ class AWSTaskRunner {
let output = '';
while (shouldReadLogs) {
yield new Promise((resolve) => setTimeout(resolve, 1500));
const taskData = yield AWSTaskRunner.describeTasks(ECS, clusterName, taskArn);
const taskData = yield AWSTaskRunner.describeTasks(clusterName, taskArn);
({ timestamp, shouldReadLogs } = AWSTaskRunner.checkStreamingShouldContinue(taskData, timestamp, shouldReadLogs));
({ iterator, shouldReadLogs, output, shouldCleanup } = yield AWSTaskRunner.handleLogStreamIteration(kinesis, iterator, shouldReadLogs, taskDef, output, shouldCleanup));
({ iterator, shouldReadLogs, output, shouldCleanup } = yield AWSTaskRunner.handleLogStreamIteration(iterator, shouldReadLogs, output, shouldCleanup));
}
return { output, shouldCleanup };
});
}
static handleLogStreamIteration(kinesis, iterator, shouldReadLogs, taskDef, output, shouldCleanup) {
static handleLogStreamIteration(iterator, shouldReadLogs, output, shouldCleanup) {
return __awaiter(this, void 0, void 0, function* () {
const records = yield kinesis
.getRecords({
const records = yield AWSTaskRunner.Kinesis.getRecords({
ShardIterator: iterator,
})
.promise();
}).promise();
iterator = records.NextShardIterator || '';
({ shouldReadLogs, output, shouldCleanup } = AWSTaskRunner.logRecords(records, iterator, taskDef, shouldReadLogs, output, shouldCleanup));
({ shouldReadLogs, output, shouldCleanup } = AWSTaskRunner.logRecords(records, iterator, shouldReadLogs, output, shouldCleanup));
return { iterator, shouldReadLogs, output, shouldCleanup };
});
}
@ -1497,7 +1493,7 @@ class AWSTaskRunner {
}
return { timestamp, shouldReadLogs };
}
static logRecords(records, iterator, taskDef, shouldReadLogs, output, shouldCleanup) {
static logRecords(records, iterator, shouldReadLogs, output, shouldCleanup) {
if (records.Records.length > 0 && iterator) {
for (let index = 0; index < records.Records.length; index++) {
const json = JSON.parse(zlib.gunzipSync(Buffer.from(records.Records[index].Data, 'base64')).toString('utf8'));
@ -1511,24 +1507,20 @@ class AWSTaskRunner {
}
return { shouldReadLogs, output, shouldCleanup };
}
static getLogStream(kinesis, kinesisStreamName) {
static getLogStream(kinesisStreamName) {
return __awaiter(this, void 0, void 0, function* () {
return yield kinesis
.describeStream({
return yield AWSTaskRunner.Kinesis.describeStream({
StreamName: kinesisStreamName,
})
.promise();
}).promise();
});
}
static getLogIterator(kinesis, stream) {
static getLogIterator(stream) {
return __awaiter(this, void 0, void 0, function* () {
return ((yield kinesis
.getShardIterator({
return ((yield AWSTaskRunner.Kinesis.getShardIterator({
ShardIteratorType: 'TRIM_HORIZON',
StreamName: stream.StreamDescription.StreamName,
ShardId: stream.StreamDescription.Shards[0].ShardId,
})
.promise()).ShardIterator || '');
}).promise()).ShardIterator || '');
});
}
}
@ -2168,11 +2160,6 @@ class AwsCliCommands {
return task_service_1.TaskService.awsListJobs(perResultCallback);
});
}
static listTasks(perResultCallback = false) {
return __awaiter(this, void 0, void 0, function* () {
return task_service_1.TaskService.awsListJobs(perResultCallback);
});
}
static awsListLogGroups(perResultCallback = false) {
return __awaiter(this, void 0, void 0, function* () {
yield tertiary_resources_service_1.TertiaryResourcesService.AwsListLogGroups(perResultCallback);
@ -2183,6 +2170,16 @@ class AwsCliCommands {
return task_service_1.TaskService.awsListJobs(perResultCallback);
});
}
static listTasks(perResultCallback = false) {
return __awaiter(this, void 0, void 0, function* () {
return task_service_1.TaskService.awsListJobs(perResultCallback);
});
}
static watchTasks() {
return __awaiter(this, void 0, void 0, function* () {
return task_service_1.TaskService.watch();
});
}
}
__decorate([
cli_functions_repository_1.CliFunction(`aws-list-all`, `List all resources`)
@ -2202,15 +2199,18 @@ __decorate([
__decorate([
cli_functions_repository_1.CliFunction(`aws-list-tasks`, `List tasks`)
], AwsCliCommands, "awsListTasks", null);
__decorate([
cli_functions_repository_1.CliFunction(`list-tasks`, `List tasks`)
], AwsCliCommands, "listTasks", null);
__decorate([
cli_functions_repository_1.CliFunction(`aws-list-log-groups`, `List tasks`)
], AwsCliCommands, "awsListLogGroups", null);
__decorate([
cli_functions_repository_1.CliFunction(`aws-list-jobs`, `List tasks`)
], AwsCliCommands, "awsListJobs", null);
__decorate([
cli_functions_repository_1.CliFunction(`list-tasks`, `List tasks`)
], AwsCliCommands, "listTasks", null);
__decorate([
cli_functions_repository_1.CliFunction(`watch`, `List tasks`)
], AwsCliCommands, "watchTasks", null);
exports.AwsCliCommands = AwsCliCommands;
@ -2317,6 +2317,8 @@ class AWSBuildEnvironment {
process.env.AWS_REGION = __1.Input.region;
const ECS = new SDK.ECS();
const CF = new SDK.CloudFormation();
aws_task_runner_1.default.ECS = ECS;
aws_task_runner_1.default.Kinesis = new SDK.Kinesis();
cloud_runner_logger_1.default.log(`AWS Region: ${CF.config.region}`);
const entrypoint = ['/bin/sh'];
const startTimeMs = Date.now();
@ -2326,7 +2328,7 @@ class AWSBuildEnvironment {
try {
const postSetupStacksTimeMs = Date.now();
cloud_runner_logger_1.default.log(`Setup job time: ${Math.floor((postSetupStacksTimeMs - startTimeMs) / 1000)}s`);
const { output, shouldCleanup } = yield aws_task_runner_1.default.runTask(taskDef, ECS, CF, environment, buildGuid, commands);
const { output, shouldCleanup } = yield aws_task_runner_1.default.runTask(taskDef, environment, commands);
postRunTaskTimeMs = Date.now();
cloud_runner_logger_1.default.log(`Run job time: ${Math.floor((postRunTaskTimeMs - postSetupStacksTimeMs) / 1000)}s`);
if (shouldCleanup) {
@ -2491,6 +2493,9 @@ const input_1 = __importDefault(__nccwpck_require__(91933));
const cloud_runner_logger_1 = __importDefault(__nccwpck_require__(22855));
const base_stack_formation_1 = __nccwpck_require__(29643);
class TaskService {
static watch() {
throw new Error('Method not implemented.');
}
static awsListStacks(perResultCallback = false) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -10,12 +10,11 @@ import { CloudRunnerCustomHooks } from '../../services/cloud-runner-custom-hooks
import { FollowLogStreamService } from '../../services/follow-log-stream-service';
class AWSTaskRunner {
public static ECS: AWS.ECS;
public static Kinesis: AWS.Kinesis;
static async runTask(
taskDef: CloudRunnerAWSTaskDef,
ECS: AWS.ECS,
CF: AWS.CloudFormation,
environment: CloudRunnerEnvironmentVariable[],
buildGuid: string,
commands: string,
) {
const cluster = taskDef.baseResources?.find((x) => x.LogicalResourceId === 'ECSCluster')?.PhysicalResourceId || '';
@ -30,7 +29,7 @@ class AWSTaskRunner {
const streamName =
taskDef.taskDefResources?.find((x) => x.LogicalResourceId === 'KinesisStream')?.PhysicalResourceId || '';
const task = await ECS.runTask({
const task = await AWSTaskRunner.ECS.runTask({
cluster,
taskDefinition,
platformVersion: '1.4.0',
@ -54,19 +53,12 @@ class AWSTaskRunner {
}).promise();
const taskArn = task.tasks?.[0].taskArn || '';
CloudRunnerLogger.log('Cloud runner job is starting');
await AWSTaskRunner.waitUntilTaskRunning(ECS, taskArn, cluster);
await AWSTaskRunner.waitUntilTaskRunning(taskArn, cluster);
CloudRunnerLogger.log(
`Cloud runner job status is running ${(await AWSTaskRunner.describeTasks(ECS, cluster, taskArn))?.lastStatus}`,
`Cloud runner job status is running ${(await AWSTaskRunner.describeTasks(cluster, taskArn))?.lastStatus}`,
);
const { output, shouldCleanup } = await this.streamLogsUntilTaskStops(
ECS,
CF,
taskDef,
cluster,
taskArn,
streamName,
);
const taskData = await AWSTaskRunner.describeTasks(ECS, cluster, taskArn);
const { output, shouldCleanup } = await this.streamLogsUntilTaskStops(cluster, taskArn, streamName);
const taskData = await AWSTaskRunner.describeTasks(cluster, taskArn);
const exitCode = taskData.containers?.[0].exitCode;
const wasSuccessful = exitCode === 0 || (exitCode === undefined && taskData.lastStatus === 'RUNNING');
if (wasSuccessful) {
@ -85,15 +77,15 @@ class AWSTaskRunner {
}
}
private static async waitUntilTaskRunning(ECS: AWS.ECS, taskArn: string, cluster: string) {
private static async waitUntilTaskRunning(taskArn: string, cluster: string) {
try {
await ECS.waitFor('tasksRunning', { tasks: [taskArn], cluster }).promise();
await AWSTaskRunner.ECS.waitFor('tasksRunning', { tasks: [taskArn], cluster }).promise();
} catch (error_) {
const error = error_ as Error;
await new Promise((resolve) => setTimeout(resolve, 3000));
CloudRunnerLogger.log(
`Cloud runner job has ended ${
(await AWSTaskRunner.describeTasks(ECS, cluster, taskArn)).containers?.[0].lastStatus
(await AWSTaskRunner.describeTasks(cluster, taskArn)).containers?.[0].lastStatus
}`,
);
@ -102,8 +94,8 @@ class AWSTaskRunner {
}
}
static async describeTasks(ECS: AWS.ECS, clusterName: string, taskArn: string) {
const tasks = await ECS.describeTasks({
static async describeTasks(clusterName: string, taskArn: string) {
const tasks = await AWSTaskRunner.ECS.describeTasks({
cluster: clusterName,
tasks: [taskArn],
}).promise();
@ -114,17 +106,9 @@ class AWSTaskRunner {
}
}
static async streamLogsUntilTaskStops(
ECS: AWS.ECS,
CF: AWS.CloudFormation,
taskDef: CloudRunnerAWSTaskDef,
clusterName: string,
taskArn: string,
kinesisStreamName: string,
) {
const kinesis = new AWS.Kinesis();
const stream = await AWSTaskRunner.getLogStream(kinesis, kinesisStreamName);
let iterator = await AWSTaskRunner.getLogIterator(kinesis, stream);
static async streamLogsUntilTaskStops(clusterName: string, taskArn: string, kinesisStreamName: string) {
const stream = await AWSTaskRunner.getLogStream(kinesisStreamName);
let iterator = await AWSTaskRunner.getLogIterator(stream);
const logBaseUrl = `https://${Input.region}.console.aws.amazon.com/cloudwatch/home?region=${Input.region}#logsV2:log-groups/log-group/${CloudRunner.buildParameters.awsBaseStackName}-${CloudRunner.buildParameters.buildGuid}`;
CloudRunnerLogger.log(`You view the log stream on AWS Cloud Watch: ${logBaseUrl}`);
@ -134,13 +118,11 @@ class AWSTaskRunner {
let output = '';
while (shouldReadLogs) {
await new Promise((resolve) => setTimeout(resolve, 1500));
const taskData = await AWSTaskRunner.describeTasks(ECS, clusterName, taskArn);
const taskData = await AWSTaskRunner.describeTasks(clusterName, taskArn);
({ timestamp, shouldReadLogs } = AWSTaskRunner.checkStreamingShouldContinue(taskData, timestamp, shouldReadLogs));
({ iterator, shouldReadLogs, output, shouldCleanup } = await AWSTaskRunner.handleLogStreamIteration(
kinesis,
iterator,
shouldReadLogs,
taskDef,
output,
shouldCleanup,
));
@ -150,23 +132,18 @@ class AWSTaskRunner {
}
private static async handleLogStreamIteration(
kinesis: AWS.Kinesis,
iterator: string,
shouldReadLogs: boolean,
taskDef: CloudRunnerAWSTaskDef,
output: string,
shouldCleanup: boolean,
) {
const records = await kinesis
.getRecords({
ShardIterator: iterator,
})
.promise();
const records = await AWSTaskRunner.Kinesis.getRecords({
ShardIterator: iterator,
}).promise();
iterator = records.NextShardIterator || '';
({ shouldReadLogs, output, shouldCleanup } = AWSTaskRunner.logRecords(
records,
iterator,
taskDef,
shouldReadLogs,
output,
shouldCleanup,
@ -197,7 +174,6 @@ class AWSTaskRunner {
private static logRecords(
records,
iterator: string,
taskDef: CloudRunnerAWSTaskDef,
shouldReadLogs: boolean,
output: string,
shouldCleanup: boolean,
@ -224,24 +200,20 @@ class AWSTaskRunner {
return { shouldReadLogs, output, shouldCleanup };
}
private static async getLogStream(kinesis: AWS.Kinesis, kinesisStreamName: string) {
return await kinesis
.describeStream({
StreamName: kinesisStreamName,
})
.promise();
private static async getLogStream(kinesisStreamName: string) {
return await AWSTaskRunner.Kinesis.describeStream({
StreamName: kinesisStreamName,
}).promise();
}
private static async getLogIterator(kinesis: AWS.Kinesis, stream) {
private static async getLogIterator(stream) {
return (
(
await kinesis
.getShardIterator({
ShardIteratorType: 'TRIM_HORIZON',
StreamName: stream.StreamDescription.StreamName,
ShardId: stream.StreamDescription.Shards[0].ShardId,
})
.promise()
await AWSTaskRunner.Kinesis.getShardIterator({
ShardIteratorType: 'TRIM_HORIZON',
StreamName: stream.StreamDescription.StreamName,
ShardId: stream.StreamDescription.Shards[0].ShardId,
}).promise()
).ShardIterator || ''
);
}

View File

@ -34,10 +34,6 @@ export class AwsCliCommands {
static async awsListTasks(perResultCallback: any = false) {
return TaskService.awsListJobs(perResultCallback);
}
@CliFunction(`list-tasks`, `List tasks`)
static async listTasks(perResultCallback: any = false) {
return TaskService.awsListJobs(perResultCallback);
}
@CliFunction(`aws-list-log-groups`, `List tasks`)
static async awsListLogGroups(perResultCallback: any = false) {
@ -48,4 +44,14 @@ export class AwsCliCommands {
public static async awsListJobs(perResultCallback: any = false) {
return TaskService.awsListJobs(perResultCallback);
}
@CliFunction(`list-tasks`, `List tasks`)
static async listTasks(perResultCallback: any = false) {
return TaskService.awsListJobs(perResultCallback);
}
@CliFunction(`watch`, `List tasks`)
static async watchTasks() {
return TaskService.watch();
}
}

View File

@ -79,6 +79,8 @@ class AWSBuildEnvironment implements ProviderInterface {
process.env.AWS_REGION = Input.region;
const ECS = new SDK.ECS();
const CF = new SDK.CloudFormation();
AWSTaskRunner.ECS = ECS;
AWSTaskRunner.Kinesis = new SDK.Kinesis();
CloudRunnerLogger.log(`AWS Region: ${CF.config.region}`);
const entrypoint = ['/bin/sh'];
const startTimeMs = Date.now();
@ -99,7 +101,7 @@ class AWSBuildEnvironment implements ProviderInterface {
try {
const postSetupStacksTimeMs = Date.now();
CloudRunnerLogger.log(`Setup job time: ${Math.floor((postSetupStacksTimeMs - startTimeMs) / 1000)}s`);
const { output, shouldCleanup } = await AWSTaskRunner.runTask(taskDef, ECS, CF, environment, buildGuid, commands);
const { output, shouldCleanup } = await AWSTaskRunner.runTask(taskDef, environment, commands);
postRunTaskTimeMs = Date.now();
CloudRunnerLogger.log(`Run job time: ${Math.floor((postRunTaskTimeMs - postSetupStacksTimeMs) / 1000)}s`);
if (shouldCleanup) {

View File

@ -4,6 +4,9 @@ import CloudRunnerLogger from '../../../services/cloud-runner-logger';
import { BaseStackFormation } from '../cloud-formations/base-stack-formation';
export class TaskService {
static watch() {
throw new Error('Method not implemented.');
}
public static async awsListStacks(perResultCallback: any = false) {
process.env.AWS_REGION = Input.region;
const CF = new AWS.CloudFormation();