Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
*.tfstate.backup
*/**/dist
.terraform
functions/*/src/vendor
*/node_modules
*.js
!jest.config.js
*.d.ts
node_modules

# CDK asset staging directory
.cdk.staging
cdk.out

packages
6 changes: 6 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.ts
!*.d.ts

# CDK asset staging directory
.cdk.staging
cdk.out
40 changes: 0 additions & 40 deletions .terraform.lock.hcl

This file was deleted.

21 changes: 21 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
SOURCE_DIR := lambdas
DEST_DIR := packages
SUBDIRS := $(wildcard $(SOURCE_DIR)/*)
ZIP_TARGETS := $(patsubst $(SOURCE_DIR)/%,$(DEST_DIR)/%.zip,$(SUBDIRS))

all: package
package: $(ZIP_TARGETS)


$(DEST_DIR):
@mkdir -p $(DEST_DIR)

$(DEST_DIR)/%.zip: $(SOURCE_DIR)/%
@echo "Packaging $<..."
@cd $< && zip -r $(abspath $@) .

clean:
@echo "Cleaning up..."
@rm -rf $(DEST_DIR)/*.zip

.PHONY: all package clean
7 changes: 7 additions & 0 deletions bin/lambda-battle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { LambdaBattleStack } from '../lib/lambda-battle-stack';

const app = new cdk.App();
new LambdaBattleStack(app, 'LambdaBattleStack');
51 changes: 51 additions & 0 deletions cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"app": "npx ts-node --prefer-ts-exts bin/lambda-battle.ts",
"watch": {
"include": [
"**"
],
"exclude": [
"README.md",
"cdk*.json",
"**/*.d.ts",
"**/*.js",
"tsconfig.json",
"package*.json",
"yarn.lock",
"node_modules",
"test"
]
},
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:checkSecretUsage": true,
"@aws-cdk/core:target-partitions": [
"aws",
"aws-cn"
],
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
"@aws-cdk/aws-iam:minimizePolicies": true,
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
"@aws-cdk/core:enablePartitionLiterals": true,
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
"@aws-cdk/aws-iam:standardizedServicePrincipals": true,
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
"@aws-cdk/aws-route53-patters:useCertificate": true,
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
"@aws-cdk/aws-redshift:columnId": true,
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true
}
}
8 changes: 8 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
testEnvironment: 'node',
roots: ['<rootDir>/test'],
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.tsx?$': 'ts-jest'
}
};
1 change: 1 addition & 0 deletions ruby-2.7/src/func.rb → lambdas/ruby-2.7/src/func.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "aws-sdk-dynamodb"
require 'json'

DB = ::Aws::DynamoDB::Client.new
LANG = "ruby-2.7-x86"
Expand Down
19 changes: 19 additions & 0 deletions lib/lambda-battle-stack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { Lambdas, ApiGateway, Database } from './resources';

export class LambdaBattleStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);

const db = new Database(this, 'Database')

const lambdas = new Lambdas(this, 'Lambdas', {
baseTable: db.baseTable
})

new ApiGateway(this, 'ApiGateway', {
lambdas: lambdas.all()
})
}
}
36 changes: 36 additions & 0 deletions lib/resources/apigateway.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Construct } from "constructs";
import { TLambdas } from "./lambdas";
import { LambdaIntegration, RestApi } from "aws-cdk-lib/aws-apigateway";
import { IFunction } from "aws-cdk-lib/aws-lambda";


interface ApiGatewayProps {
lambdas: TLambdas
}

export default class ApiGateway extends Construct {
private battleApi: RestApi

constructor(scope: Construct, id: string, props: ApiGatewayProps) {
super(scope, id);

this.createLambdaBattleApi(props.lambdas);
}

private createLambdaBattleApi(funcs: TLambdas) {
this.battleApi ||= new RestApi(this, "lambda-battle-api", {
deploy: true,
restApiName: `Lambda Battle Api`
})

Object.entries(funcs).forEach(([k, w]) => this.addBattleLambdaEndpoint(k, w))
}

private addBattleLambdaEndpoint(name: string, func: IFunction) {
const lambdaIntegration = new LambdaIntegration(func)

this.battleApi.root
.addResource(name)
.addMethod("POST", lambdaIntegration)
}
}
29 changes: 29 additions & 0 deletions lib/resources/database.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { AttributeType, BillingMode, ITable, Table } from "aws-cdk-lib/aws-dynamodb";
import { Construct } from "constructs";

export default class Database extends Construct {
public readonly baseTable: ITable;

constructor(scope: Construct, id: string) {
super(scope, id);

this.baseTable = this.createBaseTable();
}

private createBaseTable(): ITable {
const baseTable = new Table(this, 'lambda-battle-data', {
tableName: 'lambda-battle-data',
partitionKey: {
name: 'langCase',
type: AttributeType.STRING
},
sortKey: {
name: "iteration",
type: AttributeType.NUMBER
},
billingMode: BillingMode.PAY_PER_REQUEST
});

return baseTable;
}
}
3 changes: 3 additions & 0 deletions lib/resources/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { default as Lambdas } from "./lambdas";
export { default as Database } from "./database";
export { default as ApiGateway } from "./apigateway";
60 changes: 60 additions & 0 deletions lib/resources/lambdas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Duration, StackProps } from "aws-cdk-lib";
import { Code, Runtime, Function, IFunction } from "aws-cdk-lib/aws-lambda";
import { Construct } from "constructs";
import { RetentionDays } from "aws-cdk-lib/aws-logs";
import * as ssm from 'aws-cdk-lib/aws-ssm';
import { ITable } from "aws-cdk-lib/aws-dynamodb";

export interface LambdasProps extends StackProps {
baseTable: ITable;
}

export type TLambdas = {
'ruby-2.7-x86': IFunction
}

type LambdaOptions = {
runtime: Runtime,
lpackage: string,
env?: { [key: string]: string }
}

export default class Lambdas extends Construct {
readonly Ruby2_7Lambda: Function;

private props: LambdasProps;

constructor(scope: Construct, id: string, props: LambdasProps) {
super(scope, id);

this.props = props
this.Ruby2_7Lambda = this.createRubyLambda({
runtime: Runtime.RUBY_2_7, lpackage: 'ruby-2.7.zip'
});
}

public all = (): TLambdas => ({
'ruby-2.7-x86': this.Ruby2_7Lambda
})

private createRubyLambda(opts: LambdaOptions) {
const name = opts.lpackage.replace('.zip', '').replace(/\W/g, '_').toUpperCase()

const lambdaProps = {
functionName: `${name}-Battle-Function`,
code: Code.fromAsset(`./packages/${opts.lpackage}`),
handler: 'src/func.handler',
runtime: opts.runtime,
environment: {
GEM_PATH: './vendor',
TABLE: this.props.baseTable.tableName
}
}

const rubyFunction = new Function(this, `${name}-lambda`, lambdaProps);

this.props.baseTable.grantReadWriteData(rubyFunction);

return rubyFunction
}
}
Loading