From 4cc117388708044e5b95c833170493523e0c351d Mon Sep 17 00:00:00 2001 From: "R. Duthie" <343584+rjaduthie@users.noreply.github.com> Date: Fri, 20 Jan 2023 00:20:59 +0000 Subject: [PATCH 1/4] Fix updownstatus API lambda handler export --- resources/serverstatus.ts | 3 +-- resources/startstopserver.ts | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/resources/serverstatus.ts b/resources/serverstatus.ts index 648acb1..4adb94a 100644 --- a/resources/serverstatus.ts +++ b/resources/serverstatus.ts @@ -35,7 +35,7 @@ const ec2Client = new EC2Client({ region: REGION }); /** * Everything here has the assumption there is only one task. */ -const handler: APIGatewayProxyHandler = async (event: APIGatewayEvent, context: Context) => { +export const handler: APIGatewayProxyHandler = async (event: APIGatewayEvent, context: Context) => { console.log(`New getServerStatus request: ${JSON.stringify(event)}`); console.log(`With context: ${JSON.stringify(context)}`); @@ -50,7 +50,6 @@ const handler: APIGatewayProxyHandler = async (event: APIGatewayEvent, context: }; }; -export default handler; async function getIPFunction() { diff --git a/resources/startstopserver.ts b/resources/startstopserver.ts index e20dd15..750c03a 100644 --- a/resources/startstopserver.ts +++ b/resources/startstopserver.ts @@ -26,7 +26,7 @@ const SERVICE_NAME = process.env.SERVICE_NAME; const CLUSTER_ARN = process.env.CLUSTER_ARN; const PASSWORD = process.env.PASSWORD; -const handler: APIGatewayProxyHandler = async (event: APIGatewayEvent, context: Context) => { +export const handler: APIGatewayProxyHandler = async (event: APIGatewayEvent, context: Context) => { console.log("request: " + JSON.stringify(event)); let responseCode = 400; let message = "authentication failed"; @@ -78,5 +78,3 @@ const handler: APIGatewayProxyHandler = async (event: APIGatewayEvent, context: body: JSON.stringify(responseBody) }; }; - -export default handler; From 34358eaa3887ec6972785fb07c2c06e2661513d9 Mon Sep 17 00:00:00 2001 From: "R. Duthie" <343584+rjaduthie@users.noreply.github.com> Date: Sun, 22 Jan 2023 00:01:44 +0000 Subject: [PATCH 2/4] Fix startstop lambda ECS update command --- resources/startstopserver.ts | 101 ++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/resources/startstopserver.ts b/resources/startstopserver.ts index 750c03a..83c9a8b 100644 --- a/resources/startstopserver.ts +++ b/resources/startstopserver.ts @@ -1,4 +1,4 @@ -/* +/* ABOUT THIS NODE.JS EXAMPLE: This example works with AWS SDK for JavaScript version 3 (v3), which is available at https://github.com/aws/aws-sdk-js-v3. This example is in the 'AWS SDK for JavaScript v3 Developer Guide' at @@ -16,65 +16,68 @@ Inputs (into code): */ "use strict"; -import { ECSClient, UpdateServiceCommand } from '@aws-sdk/client-ecs'; -import { APIGatewayEvent, APIGatewayProxyHandler, Context } from 'aws-lambda'; +import {ECSClient, UpdateServiceCommand} from '@aws-sdk/client-ecs'; +import {APIGatewayEvent, APIGatewayProxyHandler, Context} from 'aws-lambda'; //Set the AWS Region -const REGION = process.env.REGION; +const REGION = process.env.REGION; -const SERVICE_NAME = process.env.SERVICE_NAME; -const CLUSTER_ARN = process.env.CLUSTER_ARN; +const SERVICE_NAME = process.env.SERVICE_NAME; +const CLUSTER_ARN = process.env.CLUSTER_ARN; const PASSWORD = process.env.PASSWORD; export const handler: APIGatewayProxyHandler = async (event: APIGatewayEvent, context: Context) => { - console.log("request: " + JSON.stringify(event)); - let responseCode = 400; - let message = "authentication failed"; - - const params = { - desiredCount: 1, - service: SERVICE_NAME, - cluster: CLUSTER_ARN - } - - if (event.queryStringParameters && event.queryStringParameters.desiredCount !== undefined) { - let count = Math.min(Math.max(+event.queryStringParameters.desiredCount, 0), 1); - params.desiredCount = count; - console.log("changing desiredCount to " + count); - } + console.log("request: " + JSON.stringify(event)); + let responseCode = 400; + let message = "authentication failed"; + + const params = { + desiredCount: 1, + service: SERVICE_NAME, + cluster: CLUSTER_ARN + } + + if (event.queryStringParameters && event.queryStringParameters.desiredCount !== undefined) { + let count = Math.min(Math.max(+event.queryStringParameters.desiredCount, 0), 1); + params.desiredCount = count; + console.log("changing desiredCount to " + count); + } - if (event.queryStringParameters && event.queryStringParameters.key) { - let key = event.queryStringParameters.key; - if (key == PASSWORD) { - const client = new ECSClient({ region: REGION }); - console.log("starting service " + JSON.stringify(params)); - message = "authentication success"; - responseCode = 200; + if (event.queryStringParameters && event.queryStringParameters.key) { + let key = event.queryStringParameters.key; + if (key == PASSWORD) { + const client = new ECSClient({region: REGION}); + console.log("starting service " + JSON.stringify(params)); + message = "authentication success"; + responseCode = 200; - const updateCommand = new UpdateServiceCommand(params); + const updateCommand = new UpdateServiceCommand(params); - client.send(updateCommand).then( - (data) => {console.log(data);}, - (err) => { console.log(err);} - ); + await client.send(updateCommand).then( + (data) => { + console.log(`OK! ${JSON.stringify(data, null, 2)}`); + }, + (err) => { + console.log(`Error! ${JSON.stringify(err, null, 2)}`); } + ); } + } - let responseBody = { - message: message, - }; - - // The output from a Lambda proxy integration must be - // in the following JSON object. The 'headers' property - // is for custom response headers in addition to standard - // ones. The 'body' property must be a JSON string. For - // base64-encoded payload, you must also set the 'isBase64Encoded' - // property to 'true'. - return { - statusCode: responseCode, - headers: { - }, - body: JSON.stringify(responseBody) - }; + let responseBody = { + message: message, + }; + + // The output from a Lambda proxy integration must be + // in the following JSON object. The 'headers' property + // is for custom response headers in addition to standard + // ones. The 'body' property must be a JSON string. For + // base64-encoded payload, you must also set the 'isBase64Encoded' + // property to 'true'. + return { + statusCode: responseCode, + headers: {}, + body: JSON.stringify(responseBody) + }; }; From 99e8c8f520128299e8109ef3d968d2dfb9a511cd Mon Sep 17 00:00:00 2001 From: "R. Duthie" <343584+rjaduthie@users.noreply.github.com> Date: Sun, 22 Jan 2023 00:01:59 +0000 Subject: [PATCH 3/4] Add .nvmrc --- .nvmrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 .nvmrc diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..3c03207 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +18 From 24814bc7975f2c9b992d3e941b4de142ca49e021 Mon Sep 17 00:00:00 2001 From: "R. Duthie" <343584+rjaduthie@users.noreply.github.com> Date: Sun, 22 Jan 2023 00:33:26 +0000 Subject: [PATCH 4/4] Improve server status logging and response --- resources/serverstatus.ts | 12 ++++++------ resources/startstopserver.ts | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/resources/serverstatus.ts b/resources/serverstatus.ts index 4adb94a..00c009a 100644 --- a/resources/serverstatus.ts +++ b/resources/serverstatus.ts @@ -1,4 +1,4 @@ -/* +/* This code was created from sample code provided for the AWS SDK for JavaScript version 3 (v3), which is available at https://github.com/aws/aws-sdk-js-v3. This example is in the 'AWS SDK for JavaScript v3 Developer Guide' at @@ -61,15 +61,15 @@ async function getIPFunction() { try { - const listTasksCommandInput: ListTasksCommandInput = { + const listTasksCommandInput: ListTasksCommandInput = { serviceName: SERVICE_ARN, cluster: CLUSTER_ARN, desiredStatus: "RUNNING" } const listTasksCommandResult = await ecsClient.send(new ListTasksCommand(listTasksCommandInput)); - console.log(listTasksCommandResult); + console.log("ECS List Tasks Command Result: " + listTasksCommandResult); - if (!listTasksCommandResult.taskArns || listTasksCommandResult.taskArns.length <= 0) return; + if (!listTasksCommandResult.taskArns || listTasksCommandResult.taskArns.length <= 0) return statusResults; const networkInterfaceId = await getNetworkInterfaceId(CLUSTER_ARN, listTasksCommandResult.taskArns); @@ -78,7 +78,7 @@ async function getIPFunction() { } const describeNetworkInterfacesResult = await ec2Client.send(new DescribeNetworkInterfacesCommand(describeNetworkInterfacesInput)); - if (!describeNetworkInterfacesResult.NetworkInterfaces || describeNetworkInterfacesResult.NetworkInterfaces.length <= 0) return; + if (!describeNetworkInterfacesResult.NetworkInterfaces || describeNetworkInterfacesResult.NetworkInterfaces.length <= 0) return statusResults; const publicIp = describeNetworkInterfacesResult.NetworkInterfaces.find(x => x.Association != undefined)?.Association?.PublicIp; console.log("found public IP " + publicIp); @@ -110,7 +110,7 @@ const getNetworkInterfaceId = async (cluster: string, tasks: string[]): Promise< const networkInterfaceId = firstAttachment.details?.find(d => d.name === 'networkInterfaceId')?.value; if (!networkInterfaceId) throw new Error(`Could not find a network interface on given attachment: ${JSON.stringify(firstAttachment)}`); - + console.debug(`Found interface "${networkInterfaceId}"`); return networkInterfaceId; } catch (err) { diff --git a/resources/startstopserver.ts b/resources/startstopserver.ts index 83c9a8b..490f5dc 100644 --- a/resources/startstopserver.ts +++ b/resources/startstopserver.ts @@ -16,8 +16,8 @@ Inputs (into code): */ "use strict"; -import {ECSClient, UpdateServiceCommand} from '@aws-sdk/client-ecs'; -import {APIGatewayEvent, APIGatewayProxyHandler, Context} from 'aws-lambda'; +import { ECSClient, UpdateServiceCommand } from '@aws-sdk/client-ecs'; +import { APIGatewayEvent, APIGatewayProxyHandler, Context } from 'aws-lambda'; //Set the AWS Region const REGION = process.env.REGION;