Skip to content
This repository was archived by the owner on Mar 27, 2025. It is now read-only.

Commit 2dfa43b

Browse files
committed
Add resource name utility and update DynamoDB table names based on environment
1 parent aeed806 commit 2dfa43b

File tree

11 files changed

+233
-213
lines changed

11 files changed

+233
-213
lines changed

.github/workflows/deploy.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,16 @@ jobs:
3434
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
3535
aws-region: ap-south-1
3636

37+
- name: Determine Environment Name
38+
run: |
39+
if [[ $GITHUB_REF == refs/heads/main ]]; then
40+
ENV_NAME="prod"
41+
elif [[ $GITHUB_REF == refs/heads/stage ]]; then
42+
ENV_NAME="stg"
43+
else
44+
ENV_NAME="dev"
45+
fi
46+
echo "ENV_NAME=$ENV_NAME" >> $GITHUB_ENV
47+
3748
- name: Deploy CDK
38-
run: cdk deploy --all --require-approval never
49+
run: cdk deploy --all -c env=${{ env.ENV_NAME }} --require-approval never

bin/backend.ts

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,30 @@ import 'source-map-support/register';
33
import * as cdk from 'aws-cdk-lib';
44
import { S3Stack } from '../lib/s3-stack';
55
import { DynamoTableStack } from '../lib/dynamo-stack';
6-
import { WebSocketStack } from '../lib/webSocket-stack';
76
import { AuthStack } from '../lib/auth-stack';
87
import { OrderStack } from '../lib/order-stack';
98
import { RestaurantStack } from '../lib/restaurant-stack';
109
import { HttpStack } from '../lib/httpAPI-stack';
10+
import { CertificateStack } from '../lib/certificate-stack';
1111

1212
const app = new cdk.App();
13-
// new BackendStack(app, 'BackendStack', {
14-
// /* If you don't specify 'env', this stack will be environment-agnostic.
15-
// * Account/Region-dependent features and context lookups will not work,
16-
// * but a single synthesized template can be deployed anywhere. */
1713

18-
// /* Uncomment the next line to specialize this stack for the AWS Account
19-
// * and Region that are implied by the current CLI configuration. */
20-
// // env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
14+
const envName = app.node.tryGetContext('env');
15+
if (!envName) {
16+
throw new Error('env is required')
17+
}
2118

22-
// /* Uncomment the next line if you know exactly what Account and Region you
23-
// * want to deploy the stack to. */
24-
// // env: { account: '123456789012', region: 'us-east-1' },
2519

26-
// /* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
27-
// });
2820
const env = {
2921
account: process.env.CDK_DEFAULT_ACCOUNT,
3022
region: process.env.CDK_DEFAULT_REGION,
3123
};
32-
new HttpStack(app, 'HttpStack', { env });
33-
new DynamoTableStack(app, 'DynamoStack', { env, terminationProtection: true });
34-
new AuthStack(app, 'AuthStack', { env });
35-
new S3Stack(app, 'S3Stack', { env, terminationProtection: true });
36-
new OrderStack(app, 'OrderStack', { env });
37-
new RestaurantStack(app, 'RestaurantStack', { env });
38-
// new WebSocketStack(app, 'WebSocketStack', {
39-
// // liveRestaurantConnectionsTable,
40-
// env,
41-
// });
24+
25+
new CertificateStack(app, 'CertificateStack', { env });
26+
new HttpStack(app, 'HttpStack', { env, envName });
27+
new DynamoTableStack(app, 'DynamoStack', { env, terminationProtection: true, envName });
28+
new AuthStack(app, 'AuthStack', { env, envName });
29+
new S3Stack(app, 'S3Stack', { env, terminationProtection: true, envName });
30+
new OrderStack(app, 'OrderStack', { env, envName });
31+
new RestaurantStack(app, 'RestaurantStack', { env, envName });
4232

lib/auth-stack.ts

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,35 @@ import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations
77
import { RetentionDays } from 'aws-cdk-lib/aws-logs';
88
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
99
import { ServicePrincipal } from 'aws-cdk-lib/aws-iam';
10+
import { getResourceName } from '../utils/getResourceName';
1011

12+
interface AuthStackProps extends cdk.StackProps {
13+
envName: string;
14+
}
1115

1216
export class AuthStack extends cdk.Stack {
13-
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
17+
constructor(scope: Construct, id: string, props: AuthStackProps) {
1418
super(scope, id, props);
1519

16-
const httpApiId = cdk.Fn.importValue('BeejhoHttpApiId');
17-
const httpApi = HttpApi.fromHttpApiAttributes(this, 'BeejhoHttpApi', {
20+
const { envName } = props;
21+
22+
const httpApiId = cdk.Fn.importValue(getResourceName(envName, 'BeejhoHttpApiId'));
23+
const httpApi = HttpApi.fromHttpApiAttributes(this, getResourceName(envName, 'BeejhoHttpApiId'), {
1824
httpApiId
19-
})
25+
});
2026

21-
const userTable = dynamodb.Table.fromTableName(this, 'OrderTable', 'users')
22-
const restaurantTable = dynamodb.Table.fromTableName(this, 'RestaurantTable', 'restaurants')
27+
const userTable = dynamodb.Table.fromTableName(this, getResourceName(envName, 'UsersTable'), getResourceName(envName, 'users'));
28+
const restaurantTable = dynamodb.Table.fromTableName(this, getResourceName(envName, 'RestaurantTable'), getResourceName(envName, 'restaurants'));
2329

24-
const userLoginLambda = new NodejsFunction(this, 'LoginUser', {
30+
const userLoginLambda = new NodejsFunction(this, getResourceName(envName, 'LoginUser'), {
2531
runtime: lambda.Runtime.NODEJS_LATEST,
2632
entry: './src/lambdas/auth.ts',
2733
handler: 'userLoginHandler',
28-
functionName: 'loginUser',
34+
functionName: getResourceName(envName, 'LoginUser'),
2935
architecture: lambda.Architecture.ARM_64,
3036
environment: {
3137
JWT_SECRET: 'Abhi2199@321#',
38+
envName,
3239
},
3340
logRetention: RetentionDays.ONE_DAY,
3441
bundling: {
@@ -37,59 +44,64 @@ export class AuthStack extends cdk.Stack {
3744
});
3845
userTable.grantReadWriteData(userLoginLambda);
3946

40-
new HttpRoute(this, 'LoginRoute', {
47+
new HttpRoute(this, getResourceName(envName, 'LoginRoute'), {
4148
httpApi,
4249
routeKey: HttpRouteKey.with('/v0/login', HttpMethod.POST),
43-
integration: new HttpLambdaIntegration('LoginrUserLambdaIntegration', userLoginLambda),
50+
integration: new HttpLambdaIntegration(getResourceName(envName, 'LoginUserLambdaIntegration'), userLoginLambda),
4451
});
4552

46-
const generateOTPLambda = new NodejsFunction(this, 'GenerateOTP', {
53+
const generateOTPLambda = new NodejsFunction(this, getResourceName(envName, 'GenerateOTP'), {
4754
runtime: lambda.Runtime.NODEJS_LATEST,
4855
entry: './src/lambdas/auth.ts',
4956
handler: 'generateOTPHandler',
50-
functionName: 'generateOTP',
57+
functionName: getResourceName(envName, 'GenerateOTP'),
5158
architecture: lambda.Architecture.ARM_64,
59+
environment: {
60+
JWT_SECRET: 'Abhi2199@321#',
61+
envName,
62+
},
5263
logRetention: RetentionDays.ONE_DAY,
5364
bundling: {
5465
externalModules: ['aws-sdk']
5566
},
5667
});
57-
userTable.grantWriteData(generateOTPLambda);
5868

59-
new HttpRoute(this, 'GenerateOTPRoute', {
69+
new HttpRoute(this, getResourceName(envName, 'GenerateOTPRoute'), {
6070
httpApi,
6171
routeKey: HttpRouteKey.with('/v0/generateOTP', HttpMethod.POST),
62-
integration: new HttpLambdaIntegration('GenerateOTPLambdaIntegration', generateOTPLambda),
63-
})
72+
integration: new HttpLambdaIntegration(getResourceName(envName, 'GenerateOTPLambdaIntegration'), generateOTPLambda),
73+
});
74+
userTable.grantWriteData(generateOTPLambda);
6475

65-
const userAuthorizerLambda = new NodejsFunction(this, 'UserAuthorizerLambda', {
76+
const userAuthorizerLambda = new NodejsFunction(this, getResourceName(envName, 'UserAuthorizerLambda'), {
6677
runtime: lambda.Runtime.NODEJS_LATEST,
6778
entry: './src/lambdas/auth.ts',
6879
handler: 'userAuthorizerHandler',
69-
functionName: 'userAuthorizer',
80+
functionName: getResourceName(envName, 'UserAuthorizer'),
7081
architecture: lambda.Architecture.ARM_64,
7182
environment: {
7283
JWT_SECRET: 'Abhi2199@321#',
84+
envName,
7385
},
7486
logRetention: RetentionDays.ONE_DAY,
7587
bundling: {
7688
externalModules: ['aws-sdk']
7789
},
7890
});
7991

80-
const userAuthorizer = new HttpAuthorizer(this, 'UserAuthorizer', {
92+
const userAuthorizer = new HttpAuthorizer(this, getResourceName(envName, 'UserAuthorizer'), {
8193
httpApi,
8294
type: HttpAuthorizerType.LAMBDA,
8395
identitySource: ['$request.header.Authorization'],
8496
enableSimpleResponses: true,
8597
payloadFormatVersion: AuthorizerPayloadVersion.VERSION_2_0,
8698
authorizerUri: `arn:aws:apigateway:${this.region}:lambda:path/2015-03-31/functions/${userAuthorizerLambda.functionArn}/invocations`,
87-
})
99+
});
88100

89101
// Export the authorizer ID
90-
new cdk.CfnOutput(this, 'UserAuthorizerId', {
102+
new cdk.CfnOutput(this, getResourceName(envName, 'UserAuthorizerId'), {
91103
value: userAuthorizer.authorizerId,
92-
exportName: 'UserAuthorizerId',
104+
exportName: getResourceName(envName, 'UserAuthorizerId'),
93105
});
94106

95107
// Grant permission to API Gateway to invoke the Lambda authorizer
@@ -99,37 +111,39 @@ export class AuthStack extends cdk.Stack {
99111
sourceArn: `arn:aws:execute-api:${this.region}:${this.account}:${httpApiId}/*`,
100112
});
101113

102-
const restaurantLoginLambda = new NodejsFunction(this, 'RestaurantLogin', {
114+
const restaurantLoginLambda = new NodejsFunction(this, getResourceName(envName, 'RestaurantLogin'), {
103115
runtime: lambda.Runtime.NODEJS_LATEST,
104116
entry: './src/lambdas/auth.ts',
105117
handler: 'restaurantLoginHandler',
106-
functionName: 'restaurantLogin',
118+
functionName: getResourceName(envName, 'RestaurantLogin'),
107119
architecture: lambda.Architecture.ARM_64,
108120
logRetention: RetentionDays.ONE_DAY,
109121
bundling: {
110122
externalModules: ['aws-sdk']
111123
},
112124
environment: {
113125
JWT_SECRET: 'Abhi2199@321#',
126+
envName,
114127
},
115128
memorySize: 512 //bcrypt comparison is expensive
116129
});
117130
restaurantTable.grantReadData(restaurantLoginLambda);
118131

119-
new HttpRoute(this, 'RestaurantLoginRoute', {
132+
new HttpRoute(this, getResourceName(envName, 'RestaurantLoginRoute'), {
120133
httpApi,
121134
routeKey: HttpRouteKey.with('/v0/restaurantLogin', HttpMethod.POST),
122-
integration: new HttpLambdaIntegration('RestaurantLoginLambdaIntegration', restaurantLoginLambda),
123-
})
135+
integration: new HttpLambdaIntegration(getResourceName(envName, 'RestaurantLoginLambdaIntegration'), restaurantLoginLambda),
136+
});
124137

125-
const restaurantAuthorizerLambda = new NodejsFunction(this, 'RestaurantAuthorizerLambda', {
138+
const restaurantAuthorizerLambda = new NodejsFunction(this, getResourceName(envName, 'RestaurantAuthorizerLambda'), {
126139
runtime: lambda.Runtime.NODEJS_LATEST,
127140
entry: './src/lambdas/auth.ts',
128141
handler: 'restaurantAuthorizerHandler',
129-
functionName: 'restaurantAuthorizer',
142+
functionName: getResourceName(envName, 'RestaurantAuthorizer'),
130143
architecture: lambda.Architecture.ARM_64,
131144
environment: {
132145
JWT_SECRET: 'Abhi2199@321#',
146+
envName,
133147
},
134148
logRetention: RetentionDays.ONE_DAY,
135149
bundling: {
@@ -138,25 +152,25 @@ export class AuthStack extends cdk.Stack {
138152
});
139153

140154

141-
const restaurantAuthorizer = new HttpAuthorizer(this, 'RestaurantAuthorizer', {
155+
const restaurantAuthorizer = new HttpAuthorizer(this, getResourceName(envName, 'RestaurantAuthorizer'), {
142156
httpApi,
143157
type: HttpAuthorizerType.LAMBDA,
144158
identitySource: ['$request.header.Authorization'],
145159
enableSimpleResponses: true,
146160
payloadFormatVersion: AuthorizerPayloadVersion.VERSION_2_0,
147161
authorizerUri: `arn:aws:apigateway:${this.region}:lambda:path/2015-03-31/functions/${restaurantAuthorizerLambda.functionArn}/invocations`,
148-
})
162+
});
149163

150-
restaurantAuthorizerLambda.addPermission('InvokeRestaurantAuthorizerLambda', {
164+
restaurantAuthorizerLambda.addPermission(getResourceName(envName, 'InvokeRestaurantAuthorizerLambda'), {
151165
principal: new ServicePrincipal('apigateway.amazonaws.com'),
152166
action: 'lambda:InvokeFunction',
153167
sourceArn: `arn:aws:execute-api:${this.region}:${this.account}:${httpApiId}/*`,
154168
});
155169

156170
// Export the authorizer ID
157-
new cdk.CfnOutput(this, 'RestaurantAuthorizerId', {
171+
new cdk.CfnOutput(this, getResourceName(envName, 'RestaurantAuthorizerId'), {
158172
value: restaurantAuthorizer.authorizerId,
159-
exportName: 'RestaurantAuthorizerId',
173+
exportName: getResourceName(envName, 'RestaurantAuthorizerId'),
160174
});
161175
}
162176
}

lib/certificate-stack.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import * as cdk from 'aws-cdk-lib';
2+
import { Certificate, CertificateValidation } from 'aws-cdk-lib/aws-certificatemanager';
3+
import { HostedZone } from 'aws-cdk-lib/aws-route53';
4+
import { Construct } from 'constructs';
5+
6+
export class CertificateStack extends cdk.Stack {
7+
constructor(scope: Construct, id: string, props: cdk.StackProps) {
8+
super(scope, id, props);
9+
10+
const hostedZone = HostedZone.fromLookup(this, 'HostedZone', {
11+
domainName: 'beejho.in',
12+
});
13+
14+
const certificate = new Certificate(this, 'BeejhoBackendCertificate', {
15+
domainName: 'api.beejho.in',
16+
subjectAlternativeNames: [
17+
'api-stg.beejho.in',
18+
'api-dev.beejho.in',
19+
],
20+
validation: CertificateValidation.fromDns(hostedZone),
21+
});
22+
23+
new cdk.CfnOutput(this, 'BeejhoBackendCertificateOutput', {
24+
value: certificate.certificateArn,
25+
exportName: `${this.stackName}-CertificateArn`,
26+
});
27+
}
28+
}

lib/dynamo-stack.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,46 @@
11
import * as cdk from 'aws-cdk-lib';
22
import { Construct } from 'constructs';
33
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
4+
import { getResourceName } from '../utils/getResourceName';
5+
6+
interface DynamoTableStackProps extends cdk.StackProps {
7+
envName: string;
8+
}
49

510
export class DynamoTableStack extends cdk.Stack {
6-
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
11+
constructor(scope: Construct, id: string, props: DynamoTableStackProps) {
712
super(scope, id, props);
813

9-
new dynamodb.Table(this, 'Menu', {
10-
tableName: 'menu',
14+
const { envName } = props;
15+
16+
new dynamodb.Table(this, getResourceName(envName, 'Menu'), {
17+
tableName: getResourceName(envName, 'menu'),
1118
partitionKey: { name: 'restaurantId', type: dynamodb.AttributeType.STRING },
1219
sortKey: { name: 'itemId', type: dynamodb.AttributeType.STRING },
1320
});
1421

15-
const ordersTable = new dynamodb.Table(this, 'Orders', {
16-
tableName: 'orders',
22+
const ordersTable = new dynamodb.Table(this, getResourceName(envName, 'Orders'), {
23+
tableName: getResourceName(envName, 'orders'),
1724
partitionKey: { name: 'restaurantId', type: dynamodb.AttributeType.STRING },
1825
sortKey: { name: 'orderId', type: dynamodb.AttributeType.STRING },
1926
});
2027

2128
ordersTable.addLocalSecondaryIndex({
22-
indexName: 'restaurantId-resourceId-index',
29+
indexName: getResourceName(envName, 'restaurantId-resourceId-index'),
2330
sortKey: {
2431
name: 'resourceId',
2532
type: dynamodb.AttributeType.STRING,
2633
},
2734
});
2835

29-
new dynamodb.Table(this, 'Users', {
30-
tableName: 'users',
36+
new dynamodb.Table(this, getResourceName(envName, 'Users'), {
37+
tableName: getResourceName(envName, 'users'),
3138
partitionKey: { name: 'userId', type: dynamodb.AttributeType.STRING },
3239
});
3340

34-
new dynamodb.Table(this, 'Restaurants', {
35-
tableName: 'restaurants',
41+
new dynamodb.Table(this, getResourceName(envName, 'Restaurants'), {
42+
tableName: getResourceName(envName, 'restaurants'),
3643
partitionKey: { name: 'restaurantId', type: dynamodb.AttributeType.STRING },
3744
});
38-
39-
new dynamodb.Table(this, 'LiveRestaurantConnectionsTable', {
40-
tableName: 'live-restaurant-connections',
41-
partitionKey: { name: 'connectionId', type: dynamodb.AttributeType.STRING },
42-
});
4345
}
4446
}

0 commit comments

Comments
 (0)