in back-end-resources/back-end.ts [12:234]
constructor(parent: Construct, name: string) {
super(parent, name);
// Creates Meetings table for storage of meeting information
const meetingsTable = new dynamodb.Table(this, 'meetings', {
partitionKey: {
name: 'Title',
type: dynamodb.AttributeType.STRING
},
tableName: 'meetings',
removalPolicy: cdk.RemovalPolicy.DESTROY,
timeToLiveAttribute: 'TTL',
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
});
// New to Breakout Rooms - adds a GSI that is used to correlate Parent Meeting with Breakout Meeting
meetingsTable.addGlobalSecondaryIndex ({
indexName: "ParentMeeting",
partitionKey: {
name: 'ParentMeeting',
type: dynamodb.AttributeType.STRING
}})
// Creates Attendee Table for storage of attendee information
const attendeeTable = new dynamodb.Table(this, 'attendees', {
partitionKey: {
name: 'AttendeeId',
type: dynamodb.AttributeType.STRING
},
tableName: 'attendees',
removalPolicy: cdk.RemovalPolicy.DESTROY,
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST
});
// IAM Role and Policy to be used by Lambda functions
const lambdaChimeRole = new iam.Role(this, 'LambdaChimeRole', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
});
lambdaChimeRole.addToPolicy(new iam.PolicyStatement({
resources: ['*'],
actions: ['chime:CreateMeeting',
'chime:CreateMeeting',
'chime:CreateMeeting',
'chime:DeleteMeeting',
'chime:GetMeeting',
'chime:ListMeetings',
'chime:BatchCreateAttendee',
'chime:CreateAttendee',
'chime:DeleteAttendee',
'chime:GetAttendee',
'chime:ListAttendees',
]}));
lambdaChimeRole.addToPolicy(new iam.PolicyStatement({
resources: ['*'],
actions: ['logs:CreateLogStream',
'logs:PutLogEvents',
'logs:DescribeLogStreams']
}));
lambdaChimeRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSLambdaBasicExecutionRole"));
const lambdaLogsRole = new iam.Role(this, 'LambdaLogRole', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
});
lambdaLogsRole.addToPolicy(new iam.PolicyStatement({
resources: ['*'],
actions: ['logs:CreateLogStream',
'logs:PutLogEvents',
'logs:DescribeLogStreams']
}));
lambdaLogsRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSLambdaBasicExecutionRole"));
// Creates Lambda Layer with Utility functions from lambda-layer/nodejs/node_modules/ directory
const layer = new lambda.LayerVersion(this, 'MeetingUtilsLayer', {
code: new lambda.AssetCode('back-end-resources/lambda-layer'),
compatibleRuntimes: [lambda.Runtime.NODEJS_12_X],
license: 'Apache-2.0',
description: 'Meeting Utils Layer',
});
// Creates Lambda functions from src directory for each different function
// Each function is created from a specific file
// A layer is attached to each function to provide utility functions
// Environment Variables are added for DynamoDB tables
// An approriate role is associated to each Lambda
const joinLambda = new lambda.Function(this, 'joinMeeting', {
code: lambda.Code.fromAsset("back-end-resources/src", {exclude: ["**", "!join.js"]}),
handler: 'join.handler',
runtime: lambda.Runtime.NODEJS_12_X,
environment: {
MEETINGS_TABLE_NAME: meetingsTable.tableName,
ATTENDEES_TABLE_NAME: attendeeTable.tableName,
},
layers: [layer],
role: lambdaChimeRole
});
const attendeeLambda = new lambda.Function(this, 'attendeeMeeting', {
code: lambda.Code.fromAsset("back-end-resources/src", {exclude: ["**", "!attendee.js"]}),
handler: 'attendee.handler',
runtime: lambda.Runtime.NODEJS_12_X,
environment: {
MEETINGS_TABLE_NAME: meetingsTable.tableName,
ATTENDEES_TABLE_NAME: attendeeTable.tableName,
},
layers: [layer],
role: lambdaChimeRole
});
const endLambda = new lambda.Function(this, 'end', {
code: lambda.Code.fromAsset("back-end-resources/src", {exclude: ["**", "!end.js"]}),
handler: 'end.handler',
runtime: lambda.Runtime.NODEJS_12_X,
environment: {
MEETINGS_TABLE_NAME: meetingsTable.tableName,
ATTENDEES_TABLE_NAME: attendeeTable.tableName,
},
layers: [layer],
role: lambdaChimeRole
});
const logsLambda = new lambda.Function(this, 'logs', {
code: lambda.Code.fromAsset("back-end-resources/src", {exclude: ["**", "!logs.js"]}),
handler: 'logs.handler',
runtime: lambda.Runtime.NODEJS_12_X,
environment: {
MEETINGS_TABLE_NAME: meetingsTable.tableName,
ATTENDEES_TABLE_NAME: attendeeTable.tableName,
},
layers: [layer],
role: lambdaLogsRole
});
const breakoutsLambda = new lambda.Function(this, 'breakout', {
code: lambda.Code.fromAsset("back-end-resources/src", { exclude: ["**", "!breakouts.js"] }),
handler: 'breakouts.handler',
runtime: lambda.Runtime.NODEJS_12_X,
environment: {
MEETINGS_TABLE_NAME: meetingsTable.tableName,
ATTENDEES_TABLE_NAME: attendeeTable.tableName,
},
layers: [layer],
role: lambdaChimeRole
});
const createLambda = new lambda.Function(this, 'create', {
code: lambda.Code.fromAsset("back-end-resources/src", {exclude: ["**", "!create.js"]}),
handler: 'create.handler',
runtime: lambda.Runtime.NODEJS_12_X,
environment: {
MEETINGS_TABLE_NAME: meetingsTable.tableName,
ATTENDEES_TABLE_NAME: attendeeTable.tableName,
},
layers: [layer],
role: lambdaChimeRole
});
// Permissions are granted to each Lambda to allow it to RW DynamoDB Tables
meetingsTable.grantReadWriteData(joinLambda);
attendeeTable.grantReadWriteData(joinLambda);
meetingsTable.grantReadWriteData(endLambda);
attendeeTable.grantReadWriteData(endLambda);
meetingsTable.grantReadWriteData(attendeeLambda);
attendeeTable.grantReadWriteData(attendeeLambda);
meetingsTable.grantReadWriteData(breakoutsLambda);
attendeeTable.grantReadWriteData(breakoutsLambda);
meetingsTable.grantReadWriteData(createLambda);
attendeeTable.grantReadWriteData(createLambda);
// Creates an API Gateway that is used by React App to make requests to Lambda functions
const api = new apigateway.RestApi(this, 'meetingApi', {
restApiName: 'Meeting BackEnd',
endpointConfiguration: {
types: [ apigateway.EndpointType.REGIONAL ]
}
});
// This URL will be used in the Front End deployment
const breakoutAPI = new cdk.CfnOutput(this, 'BreakoutAPIURL', {
value: api.url,
exportName: "BreakoutAPIURL"
});
breakoutAPI.overrideLogicalId('breakoutAPI')
// Adds Methods and CORS to API Gateway
const join = api.root.addResource('join');
const joinIntegration = new apigateway.LambdaIntegration(joinLambda);
join.addMethod('POST', joinIntegration);
addCorsOptions(join);
const attendee = api.root.addResource('attendee');
const attendeeIntegration = new apigateway.LambdaIntegration(attendeeLambda);
attendee.addMethod('GET', attendeeIntegration);
addCorsOptions(attendee);
const end = api.root.addResource('end');
const endIntegration = new apigateway.LambdaIntegration(endLambda);
end.addMethod('POST', endIntegration);
addCorsOptions(end);
const logs = api.root.addResource('logs');
const logsIntegration = new apigateway.LambdaIntegration(logsLambda);
logs.addMethod('POST', logsIntegration);
addCorsOptions(logs);
const breakouts = api.root.addResource('breakouts');
const breakoutsIntegration = new apigateway.LambdaIntegration(breakoutsLambda);
breakouts.addMethod('POST', breakoutsIntegration);
addCorsOptions(breakouts);
const create = api.root.addResource('create');
const createIntegration = new apigateway.LambdaIntegration(createLambda);
create.addMethod('POST', createIntegration);
addCorsOptions(create);
}