Skip to content

Commit

Permalink
CDK stack now includes optional lambda functions for monitoring serve…
Browse files Browse the repository at this point in the history
…r status, and starting and stopping the server
  • Loading branch information
DaveB93 authored and DaveB93 committed Mar 26, 2021
1 parent c72395e commit 72bee85
Show file tree
Hide file tree
Showing 10 changed files with 2,013 additions and 547 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,16 @@ npm i
SERVER_PORT: "2456",
```
5. Decide if you want the optional AWS App gateway lambda endpoints to start and stop your server and get the server status. If you do or don't want them, then update [here](bin/valheim-server-aws-cdk.ts#L29)
```typescript
new ValheimServer(app, "ValheimServer", {addAppGatewayStartStopStatus: true, appGatewayStartStopPassword: "changeme"});
```
5. Assuming you have already bootstrapped your account via the CDK (see [here](https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html) if not) - deploy the stack
```
npx cdk deploy
npx cdk deploy --all
```
6. enjoy accidentally chopping trees onto your friends powered by AWS!
Expand Down
25 changes: 24 additions & 1 deletion bin/valheim-server-aws-cdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@
import "source-map-support/register";
import * as cdk from "@aws-cdk/core";
import { ValheimServerAwsCdkStack } from "../lib/valheim-server-aws-cdk-stack";
import { LambdaEcsFargateUpdownstatusStack } from '../lib/lambda-ecs-fargate-updownstatus-stack';

class ValheimServerProps {
addAppGatewayStartStopStatus: boolean;
appGatewayStartStopPassword?: string;
}

class ValheimServer extends cdk.Construct {
constructor(scope: cdk.Construct, id: string, props?: ValheimServerProps) {
super(scope, id);
var ecsStack = new ValheimServerAwsCdkStack(app, "ValheimServerAwsCdkStack");
if( props?.addAppGatewayStartStopStatus )
{
var lambdaStack = new LambdaEcsFargateUpdownstatusStack(app, 'LambdaEcsFargateUpdownstatusStack', {
serviceArn: cdk.Fn.importValue("fargateServiceName"),
clusterArn: cdk.Fn.importValue("fargateClusterName"),
startStopPassword: props.appGatewayStartStopPassword === undefined ? "" : props.appGatewayStartStopPassword,
});
lambdaStack.addDependency(ecsStack);
}
}
}

const app = new cdk.App();
new ValheimServerAwsCdkStack(app, "ValheimServerAwsCdkStack");
new ValheimServer(app, "ValheimServer", {addAppGatewayStartStopStatus: true, appGatewayStartStopPassword: "changeme"});
app.synth();
3 changes: 2 additions & 1 deletion cdk.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true,
"@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true,
"@aws-cdk/aws-kms:defaultKeyPolicies": true,
"@aws-cdk/aws-s3:grantWriteWithoutAcl": true
"@aws-cdk/aws-s3:grantWriteWithoutAcl": true,
"@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true
}
}
95 changes: 95 additions & 0 deletions lib/lambda-ecs-fargate-updownstatus-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import * as core from "@aws-cdk/core";
import * as apigateway from "@aws-cdk/aws-apigateway";
import * as lambda from "@aws-cdk/aws-lambda";
import * as lambdanodejs from "@aws-cdk/aws-lambda-nodejs";
import { Policy, PolicyStatement, PolicyProps, Effect } from "@aws-cdk/aws-iam"
import { Stack, Arn } from "@aws-cdk/core";
import { EndpointType } from "@aws-cdk/aws-apigateway";

export interface LambdaEcsFargateUpDownServiceOptions {
region: string;
serviceArn: Arn;
clusterArn: Arn;
startStopPassword: string;
}

export class LambdaEcsFargateUpDownService extends core.Construct {
constructor(scope: core.Construct, id: string, props: LambdaEcsFargateUpDownServiceOptions) {
super(scope, id);

const serverStatusHandler = new lambdanodejs.NodejsFunction(this, "serverStatus", {
runtime: lambda.Runtime.NODEJS_10_X, // So we can use async
entry: 'resources/serverstatus.ts',
handler: "handler",
bundling: {
nodeModules: ['@aws-sdk/client-ecs', '@aws-sdk/client-ec2'],
},
environment: {
REGION: props.region,
SERVICE_ARN: props.serviceArn as string,
CLUSTER_ARN: props.clusterArn as string
}
});

const ecsStatusPolicy = new Policy(this, "ecsStatusPolicy", {
statements: [
new PolicyStatement({
resources: ['*'],
effect: Effect.ALLOW,
actions: [
"ecs:ListTasks",
"ecs:DescribeTasks",
"ec2:DescribeNetworkInterfaces"
]
})
]
});
serverStatusHandler.role?.attachInlinePolicy(ecsStatusPolicy);

const startStopHandler = new lambdanodejs.NodejsFunction(this, "startstop", {
runtime: lambda.Runtime.NODEJS_10_X, // So we can use async
entry: 'resources/startstopserver.ts',
handler: "handler",
bundling: {
nodeModules: ['@aws-sdk/client-ecs'],
},
environment: {
REGION: props.region,
SERVICE_NAME: props.serviceArn as string,
CLUSTER_ARN: props.clusterArn as string,
PASSWORD: props.startStopPassword,
}
});
const ecsStartStopPolicy = new Policy(this, "ecsStartStopPolicy", {
statements: [
new PolicyStatement({
resources: ['*'],
effect: Effect.ALLOW,
actions: [
"ecs:UpdateService",
]
})
]
});
startStopHandler.role?.attachInlinePolicy(ecsStartStopPolicy);


const api = new apigateway.RestApi(this, "startstopserver-api", {
restApiName: "Start Stop Status for ECS service",
description: "This service allows you to start / stop and get the status of an ECS task.",
endpointTypes: [ EndpointType.REGIONAL ]
});

const startStopResource = api.root.addResource("startstop");
const serverStatusResource = api.root.addResource("serverstatus");

const serverStatusIntegration = new apigateway.LambdaIntegration(serverStatusHandler, {
});

const startStopIntegration = new apigateway.LambdaIntegration(startStopHandler, {
});

serverStatusResource.addMethod("ANY", serverStatusIntegration); // GET /
startStopResource.addMethod("ANY", startStopIntegration);
}
}
22 changes: 22 additions & 0 deletions lib/lambda-ecs-fargate-updownstatus-stack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as cdk from '@aws-cdk/core';
import { Arn, Stack } from '@aws-cdk/core';
import * as lambda_service from '../lib/lambda-ecs-fargate-updownstatus-service';

interface MultiStackProps extends cdk.StackProps {
serviceArn: Arn;
clusterArn: Arn;
startStopPassword: string;
}

export class LambdaEcsFargateUpdownstatusStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props: MultiStackProps) {
super(scope, id, props);

new lambda_service.LambdaEcsFargateUpDownService(this, 'Status', {
region: cdk.Stack.of(this).region,
serviceArn: props.serviceArn,
clusterArn: props.clusterArn,
startStopPassword: props.startStopPassword,
});
}
}
4 changes: 3 additions & 1 deletion lib/valheim-server-aws-cdk-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,12 @@ export class ValheimServerAwsCdkStack extends cdk.Stack {

new cdk.CfnOutput(this, "serviceName", {
value: valheimService.serviceName,
exportName: "fargateServiceName",
});

new cdk.CfnOutput(this, "clusterArn", {
value: fargateCluster.clusterName
value: fargateCluster.clusterName,
exportName:"fargateClusterName"
});

new cdk.CfnOutput(this, "EFSId", {
Expand Down
Loading

0 comments on commit 72bee85

Please sign in to comment.