Skip to content

Commit

Permalink
Reorg script
Browse files Browse the repository at this point in the history
  • Loading branch information
alukach committed Oct 26, 2024
1 parent 4961203 commit fa18345
Showing 1 changed file with 78 additions and 123 deletions.
201 changes: 78 additions & 123 deletions config/apply-config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,138 +9,93 @@ import {
GetLogEventsCommand,
} from "@aws-sdk/client-cloudwatch-logs";

async function main() {
const [_, __, lambdaArn] = process.argv;
let exitCode = null;

// Set up AWS clients
const lambda = new LambdaClient({});
async function main() {
const [, , lambdaArn] = process.argv;
const { taskArn, clusterArn } = await invokeLambda(lambdaArn);
const ecs = new ECSClient({});
const logs = new CloudWatchLogsClient({});

// Step 1: Invoke the Lambda function
let taskArn, clusterArn;
try {
const response = await lambda.send(
new InvokeCommand({
FunctionName: lambdaArn,
InvocationType: "RequestResponse",
Payload: new TextEncoder().encode(JSON.stringify({})),
})
);

const payload = JSON.parse(new TextDecoder().decode(response.Payload));
taskArn = payload.taskArn;
clusterArn = payload.clusterArn;
console.log(
`Invoked Lambda function. Received taskArn=${taskArn}, clusterArn=${clusterArn}`
);
} catch (error) {
console.error(`Error invoking Lambda function: ${error}`);
process.exit(1);
}

// Step 2: Poll the ECS task until it reaches 'STOPPED' status
let task;
try {
while (true) {
const response = await ecs.send(
new DescribeTasksCommand({
cluster: clusterArn,
tasks: [taskArn],
})
);

if (!response.tasks || response.tasks.length === 0) {
console.error(`No tasks found with taskArn: ${taskArn}`);
process.exit(1);
}

task = response.tasks[0];
const lastStatus = task.lastStatus;
console.log(`Task status: ${lastStatus}`);

if (lastStatus === "STOPPED") break;
await new Promise((resolve) => setTimeout(resolve, 5000));
}
} catch (error) {
console.error(`Error polling ECS task: ${error}`);
process.exit(1);
}

// Retrieve the exit code from the task's containers
const exitCode = task.containers.find(
(container) => "exitCode" in container
)?.exitCode;
const task = await pollEcsTask(ecs, taskArn, clusterArn);
exitCode = task.containers[0]?.exitCode ?? null;
if (exitCode === null)
throw new Error("Could not retrieve exit code from the ECS task.");

const { logGroup, logStreamPrefix, region, containerName } =
await getLogConfig(ecs, task.taskDefinitionArn);
const taskId = taskArn.split("/").pop();
const logStreamName = `${logStreamPrefix}/${containerName}/${taskId}`;
return fetchCloudWatchLogs(logGroup, logStreamName, region);
}

if (exitCode === undefined) {
console.error("Could not retrieve exit code from the ECS task.");
process.exit(1);
}
main()
.then((logs) => {
console.log("Output logs:");
logs.forEach(console.log);
})
.catch((error) => {
console.error(`Error: ${error}`);
exitCode = 1;
})
.finally(() => process.exit(exitCode));

async function invokeLambda(lambdaArn) {
const lambda = new LambdaClient({});
const response = await lambda.send(
new InvokeCommand({
FunctionName: lambdaArn,
InvocationType: "RequestResponse",
Payload: new TextEncoder().encode(JSON.stringify({})),
})
);
return JSON.parse(new TextDecoder().decode(response.Payload));
}

// Step 3: Retrieve log configuration from the task definition
let logGroup, logStreamName, region;
try {
const taskDefinitionArn = task.taskDefinitionArn;
const response = await ecs.send(
new DescribeTaskDefinitionCommand({
taskDefinition: taskDefinitionArn,
})
async function pollEcsTask(ecs, taskArn, clusterArn) {
while (true) {
const { tasks } = await ecs.send(
new DescribeTasksCommand({ cluster: clusterArn, tasks: [taskArn] })
);

const containerDefinition = response.taskDefinition.containerDefinitions[0];
const logConfiguration = containerDefinition.logConfiguration || {};

if (logConfiguration.logDriver !== "awslogs") {
console.error("Log driver is not 'awslogs'.");
process.exit(1);
}

const options = logConfiguration.options || {};
logGroup = options["awslogs-group"];
const logStreamPrefix = options["awslogs-stream-prefix"];
region = options["awslogs-region"];

const containerName = containerDefinition.name;
const taskId = taskArn.split("/").pop();
logStreamName = `${logStreamPrefix}/${containerName}/${taskId}`;
} catch (error) {
console.error(`Error retrieving log configuration: ${error}`);
process.exit(1);
const task = tasks?.[0];
if (!task) throw new Error(`No tasks found with taskArn: ${taskArn}`);
console.log(`Task status: ${task.lastStatus}`);
if (task.lastStatus === "STOPPED") return task;
await new Promise((resolve) => setTimeout(resolve, 5000));
}
}

// Step 4: Retrieve and print the CloudWatch logs
try {
const logsClient = new CloudWatchLogsClient({ region });
let nextToken;
const events = [];
async function getLogConfig(ecs, taskDefinitionArn) {
const { taskDefinition } = await ecs.send(
new DescribeTaskDefinitionCommand({ taskDefinition: taskDefinitionArn })
);
const containerDef = taskDefinition.containerDefinitions[0];
if (containerDef.logConfiguration?.logDriver !== "awslogs")
throw new Error("Log driver is not 'awslogs'.");
return {
logGroup: containerDef.logConfiguration.options["awslogs-group"],
logStreamPrefix:
containerDef.logConfiguration.options["awslogs-stream-prefix"],
region: containerDef.logConfiguration.options["awslogs-region"],
containerName: containerDef.name,
};
}

while (true) {
const params = {
async function fetchCloudWatchLogs(logGroup, logStreamName, region) {
const logsClient = new CloudWatchLogsClient({ region });
let nextToken,
events = [];
do {
const { events: newEvents, nextForwardToken } = await logsClient.send(
new GetLogEventsCommand({
logGroupName: logGroup,
logStreamName: logStreamName,
logStreamName,
startFromHead: true,
...(nextToken && { nextToken }),
};

const response = await logsClient.send(new GetLogEventsCommand(params));
events.push(...response.events);

if (!response.nextForwardToken || response.nextForwardToken === nextToken)
break;
nextToken = response.nextForwardToken;
}

events.forEach((event) => console.log(event.message));
} catch (error) {
console.error(`Error retrieving CloudWatch logs: ${error}`);
process.exit(1);
}
nextToken,
})
);
console.log(`${{ nextToken, nextForwardToken }}`);

// Exit with the exit code from the ECS task
process.exit(exitCode);
events.push(...newEvents);
nextToken = nextForwardToken;
} while (nextToken);
return events.map((event) => event.message);
}

main().catch((error) => {
console.error(error);
process.exit(1);
});

0 comments on commit fa18345

Please sign in to comment.