1+ import {
2+ Stack ,
3+ aws_iam as iam ,
4+ aws_ec2 as ec2 ,
5+ aws_rds as rds ,
6+ aws_lambda as lambda ,
7+ aws_secretsmanager as secretsmanager ,
8+ CfnOutput ,
9+ Duration ,
10+ aws_logs ,
11+ } from "aws-cdk-lib" ;
12+ import { HttpApi } from "@aws-cdk/aws-apigatewayv2-alpha" ;
13+ import { HttpLambdaIntegration } from "@aws-cdk/aws-apigatewayv2-integrations-alpha" ;
14+ import { Construct } from "constructs" ;
15+
16+ export class TitilerPgstacApiLambda extends Construct {
17+ readonly url : string ;
18+ public titilerPgstacLambdaFunction : lambda . Function ;
19+
20+ constructor ( scope : Construct , id : string , props : TitilerPgStacApiLambdaProps ) {
21+ super ( scope , id ) ;
22+
23+ const titilerPgstacEnv = {
24+ "CPL_VSIL_CURL_ALLOWED_EXTENSIONS" : ".tif,.TIF,.tiff" ,
25+ "GDAL_CACHEMAX" : "200" ,
26+ "GDAL_DISABLE_READDIR_ON_OPEN" : "EMPTY_DIR" ,
27+ "GDAL_INGESTED_BYTES_AT_OPEN" : "32768" ,
28+ "GDAL_HTTP_MERGE_CONSECUTIVE_RANGES" : "YES" ,
29+ "GDAL_HTTP_MULTIPLEX" : "YES" ,
30+ "GDAL_HTTP_VERSION" : "2" ,
31+ "PYTHONWARNINGS" : "ignore" ,
32+ "VSI_CACHE" : "TRUE" ,
33+ "VSI_CACHE_SIZE" : "5000000" ,
34+ "DB_MIN_CONN_SIZE" : "1" ,
35+ "DB_MAX_CONN_SIZE" : "1" ,
36+ "PGSTAC_SECRET_ARN" : props . dbSecret . secretArn ,
37+ }
38+
39+
40+ this . titilerPgstacLambdaFunction = new lambda . Function ( this , "lambda" , {
41+ handler : "handler.handler" ,
42+ runtime : lambda . Runtime . PYTHON_3_8 ,
43+ code : lambda . Code . fromDockerBuild ( __dirname , {
44+ file : "runtime/Dockerfile" ,
45+ buildArgs : { PYTHON_VERSION : '3.10' } ,
46+ } ) ,
47+ timeout : Duration . seconds ( 30 ) ,
48+ vpc : props . vpc ,
49+ vpcSubnets : props . subnetSelection ,
50+ allowPublicSubnet : true ,
51+ memorySize : 3008 ,
52+ logRetention : aws_logs . RetentionDays . ONE_WEEK ,
53+ environment : titilerPgstacEnv ,
54+ } ) ;
55+
56+ // grant access to buckets using addToRolePolicy
57+ if ( props . buckets ) {
58+ props . buckets . forEach ( bucket => {
59+ this . titilerPgstacLambdaFunction . addToRolePolicy ( new iam . PolicyStatement ( {
60+ actions : [ "s3:GetObject" ] ,
61+ resources : [ `arn:aws:s3:::${ bucket } /*` ] ,
62+ } ) ) ;
63+ } ) ;
64+ }
65+
66+ props . dbSecret . grantRead ( this . titilerPgstacLambdaFunction ) ;
67+ this . titilerPgstacLambdaFunction . connections . allowTo ( props . db , ec2 . Port . tcp ( 5432 ) , "allow connections from titiler" ) ;
68+
69+ const stacApi = new HttpApi ( this , `${ Stack . of ( this ) . stackName } -titiler-pgstac-api` , {
70+ defaultIntegration : new HttpLambdaIntegration ( "integration" , this . titilerPgstacLambdaFunction ) ,
71+ } ) ;
72+
73+ this . url = stacApi . url ! ;
74+
75+ new CfnOutput ( this , "titiler-pgstac-api-output" , {
76+ exportName : `${ Stack . of ( this ) . stackName } -titiler-pgstac-url` ,
77+ value : this . url ,
78+ } ) ;
79+ }
80+ }
81+
82+ export interface TitilerPgStacApiLambdaProps {
83+
84+ /**
85+ * VPC into which the lambda should be deployed.
86+ */
87+ readonly vpc : ec2 . IVpc ;
88+
89+ /**
90+ * RDS Instance with installed pgSTAC.
91+ */
92+ readonly db : rds . IDatabaseInstance ;
93+
94+ /**
95+ * Subnet into which the lambda should be deployed.
96+ */
97+ readonly subnetSelection : ec2 . SubnetSelection ;
98+
99+ /**
100+ * Secret containing connection information for pgSTAC database.
101+ */
102+ readonly dbSecret : secretsmanager . ISecret ;
103+
104+ /**
105+ * Customized environment variables to send to titiler-pgstac runtime.
106+ */
107+ readonly apiEnv ?: Record < string , string > ;
108+
109+ /**
110+ * list of buckets the lambda will be granted access to.
111+ */
112+ readonly buckets ?: string [ ] ;
113+
114+ }
0 commit comments