This repository was archived by the owner on May 15, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathwebapp.ts
More file actions
108 lines (96 loc) · 4.29 KB
/
Copy pathwebapp.ts
File metadata and controls
108 lines (96 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { CfnOutput, Duration, IgnoreMode, Stack } from 'aws-cdk-lib';
import { Platform } from 'aws-cdk-lib/aws-ecr-assets';
import { DockerImageCode, DockerImageFunction } from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';
import { Database } from './database';
import { HttpApi } from 'aws-cdk-lib/aws-apigatewayv2';
import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
import { AllowedMethods, CachePolicy, Distribution, OriginRequestPolicy, ViewerProtocolPolicy } from 'aws-cdk-lib/aws-cloudfront';
import { HttpOrigin } from 'aws-cdk-lib/aws-cloudfront-origins';
import { readFileSync } from 'fs';
import { join } from 'path';
import { Trigger } from 'aws-cdk-lib/triggers';
export interface WebAppProps {
database: Database;
}
export class WebApp extends Construct {
constructor(scope: Construct, id: string, props: WebAppProps) {
super(scope, id);
const { database } = props;
const databaseName = 'main';
const handler = new DockerImageFunction(this, 'Handler', {
code: DockerImageCode.fromImageAsset(join('..', 'webapp'), {
file: 'Dockerfile',
platform: Platform.LINUX_AMD64,
ignoreMode: IgnoreMode.DOCKER,
exclude: readFileSync('../webapp/.dockerignore').toString().split('\n'),
}),
timeout: Duration.seconds(30),
environment: {
...database.getLambdaEnvironment(databaseName),
},
vpc: database.cluster.vpc,
memorySize: 512,
// architecture: Architecture.ARM_64,
});
database.allowInboundAccess(handler.connections);
const integration = new HttpLambdaIntegration('Integration', handler, {});
const api = new HttpApi(this, 'Api', {});
api.addRoutes({
path: '/{proxy+}',
integration,
});
const cachedPathPatterns = ['/_next/static/*', '/favicon.ico', '/api/trpc/*'];
const origin = new HttpOrigin(`${api.apiId}.execute-api.${Stack.of(this).region}.amazonaws.com`);
const distribution = new Distribution(this, 'Distribution', {
defaultBehavior: {
origin,
cachePolicy: CachePolicy.CACHING_DISABLED,
viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
// https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/add-origin-custom-headers.html#add-origin-custom-headers-forward-authorization
originRequestPolicy: OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER,
allowedMethods: AllowedMethods.ALLOW_ALL,
},
additionalBehaviors: {
...Object.fromEntries(
cachedPathPatterns.map((pathPattern) => [
pathPattern,
{
origin,
cachePolicy: CachePolicy.CACHING_OPTIMIZED,
viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
originRequestPolicy: OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER,
allowedMethods: AllowedMethods.ALLOW_ALL,
},
])
),
},
});
// new CfnOutput(this, 'HttpApiUrl', { value: api.url! });
new CfnOutput(this, 'CloudFrontUrl', { value: `https://${distribution.domainName}` });
const migration = new DockerImageFunction(this, 'MigrationRunner', {
code: DockerImageCode.fromImageAsset('../webapp', {
file: 'migration.Dockerfile',
platform: Platform.LINUX_AMD64,
}),
timeout: Duration.minutes(3),
environment: {
...props.database.getLambdaEnvironment(databaseName),
},
vpc: database.cluster.vpc,
});
database.allowInboundAccess(migration.connections);
// Run a database migration during CDK deployment
// Note that, in production, you may want to run a DB migration separately from an app deployment to prevent from
// possible outage due to a migration failure or timeout.
const trigger = new Trigger(this, "MigrationTrigger", {
handler: migration,
});
// make sure a migration is executed after the database cluster is available.
trigger.node.addDependency(database.cluster);
new CfnOutput(this, 'MigrationCommand', {
value: `aws lambda invoke --function-name ${migration.functionName} --cli-binary-format raw-in-base64-out --payload '{"command":"deploy"}' response.json`,
});
new CfnOutput(Stack.of(this), 'MigrationFunctionName', { value: migration.functionName });
}
}