From fffb27bc3112ce386439ebf1c2d23f63b5ce3d45 Mon Sep 17 00:00:00 2001 From: anitarua Date: Tue, 20 Aug 2024 16:09:01 -0700 Subject: [PATCH] use api gateway url by default, domain name only if hosted zone exists --- infrastructure/README.md | 22 ++++- infrastructure/build-and-deploy.sh | 8 +- infrastructure/lib/translation-api.ts | 130 ++++++++++++++++---------- 3 files changed, 107 insertions(+), 53 deletions(-) diff --git a/infrastructure/README.md b/infrastructure/README.md index 9f4a20d..6e5acaf 100644 --- a/infrastructure/README.md +++ b/infrastructure/README.md @@ -44,11 +44,31 @@ Or you can manually run each of these steps: npm run build ``` -3. Specify environment variables and deploy. +3. Specify the API_DOMAIN environment variable. ```bash + # The default is to use the API gateway URL that is provided when you deploy the backend stack. + export API_DOMAIN="default" + + # Specifying your own domain name will direct your CDK stack to find an existing AWS Route53 + # hosted zone in your account and create a 'chat-api' subdomain for it. export API_DOMAIN=${API_DOMAIN:-your-chosen-domain-name.com} + ``` + +4. Deploy your backend stack. + + ```bash AWS_PROFILE= AWS_REGION= npx cdk deploy ``` Once deployed, you can test your application using any of the client applications. + +If you used the `API_DOMAIN="default"` option, you'll want to save the API gateway URL that was printed out. +This will be the base API URL you'll provide to the client applications. + +```bash +Outputs: +moderated-chat-translation-api-stack.moderatedchatrestapiEndpoint23439914 = https://something.something.something.amazonaws.com/prod/ +``` + +If you used your own API domain name, you'll provide something like `https://chat-api.your-domain-name.com` to the client applications. diff --git a/infrastructure/build-and-deploy.sh b/infrastructure/build-and-deploy.sh index 05aa738..56f9e04 100755 --- a/infrastructure/build-and-deploy.sh +++ b/infrastructure/build-and-deploy.sh @@ -12,6 +12,12 @@ rm -f cdk.context.json npm i npm run build -export API_DOMAIN=${API_DOMAIN:-your-chosen-domain-name.com} +# For Momento developers, to deploy to your dev account, you will need to have gone through the cell bootstrap +# process at least once. Alternately, you can use a teammate's endpoint or use the preprod endpoint +# (search for Route53 hosted zones in the appropriate AWS accounts). +# export API_DOMAIN=${API_DOMAIN:-your-chosen-domain-name.com} + +# The default is to use the API gateway URL that is provided when you deploy the backend stack. +export API_DOMAIN="default" AWS_PROFILE=dev AWS_REGION=us-west-2 npx cdk deploy --require-approval never diff --git a/infrastructure/lib/translation-api.ts b/infrastructure/lib/translation-api.ts index cd3a7ce..d8698ee 100644 --- a/infrastructure/lib/translation-api.ts +++ b/infrastructure/lib/translation-api.ts @@ -40,58 +40,86 @@ export class TranslationApiStack extends cdk.Stack { : RemovalPolicy.RETAIN, }); - // Register the subdomain and create a certificate for it - const hostedZone = route53.HostedZone.fromLookup( - this, - 'moderated-chat-api-hosted-zone', - { - domainName: props.apiDomain, - } - ); - const certificate = new certmgr.Certificate(this, 'moderated-chat-api-cert', { - domainName: `${props.apiSubdomain}.${props.apiDomain}`, - validation: certmgr.CertificateValidation.fromDns(hostedZone), - }); - const defaultRestApiProps: apigw.RestApiProps = { - restApiName, - endpointTypes: [apigw.EndpointType.REGIONAL], - deploy: true, - description: "Rest api that contains the backend code/logic for the moderated chat demo", - deployOptions: { - stageName: 'prod', - accessLogDestination: new apigw.LogGroupLogDestination(logGroup), - accessLogFormat: apigw.AccessLogFormat.jsonWithStandardFields(), - throttlingRateLimit: 10, - throttlingBurstLimit: 25, - metricsEnabled: true, - loggingLevel: MethodLoggingLevel.INFO, - description: 'translation endpoint for momento console', - }, - defaultCorsPreflightOptions: { - allowOrigins: apigw.Cors.ALL_ORIGINS, - allowHeaders: apigw.Cors.DEFAULT_HEADERS, - allowMethods: apigw.Cors.ALL_METHODS, - }, - domainName: { + // Register the subdomain and create a certificate for it if using a custom domain + if (props.apiDomain !== "default") { + const hostedZone = route53.HostedZone.fromLookup( + this, + 'moderated-chat-api-hosted-zone', + { + domainName: props.apiDomain, + } + ); + const certificate = new certmgr.Certificate(this, 'moderated-chat-api-cert', { domainName: `${props.apiSubdomain}.${props.apiDomain}`, - endpointType: apigw.EndpointType.REGIONAL, - certificate, - }, - cloudWatchRole: true, // allows api gateway to write logs to cloudwatch - }; - - this.restApi = new apigw.RestApi(this, 'moderated-chat-rest-api', { - ...defaultRestApiProps, - }); - - new route53.ARecord(this, "moderated-chat-rest-api-dns", { - zone: hostedZone, - recordName: props.apiSubdomain, - comment: "This is the A Record used for the moderated chat api backend", - target: route53.RecordTarget.fromAlias( - new route53Targets.ApiGateway(this.restApi) - ), - }); + validation: certmgr.CertificateValidation.fromDns(hostedZone), + }); + const defaultRestApiProps: apigw.RestApiProps = { + restApiName, + endpointTypes: [apigw.EndpointType.REGIONAL], + deploy: true, + description: "Rest api that contains the backend code/logic for the moderated chat demo", + deployOptions: { + stageName: 'prod', + accessLogDestination: new apigw.LogGroupLogDestination(logGroup), + accessLogFormat: apigw.AccessLogFormat.jsonWithStandardFields(), + throttlingRateLimit: 10, + throttlingBurstLimit: 25, + metricsEnabled: true, + loggingLevel: MethodLoggingLevel.INFO, + description: 'translation endpoint for momento console', + }, + defaultCorsPreflightOptions: { + allowOrigins: apigw.Cors.ALL_ORIGINS, + allowHeaders: apigw.Cors.DEFAULT_HEADERS, + allowMethods: apigw.Cors.ALL_METHODS, + }, + domainName: { + domainName: `${props.apiSubdomain}.${props.apiDomain}`, + endpointType: apigw.EndpointType.REGIONAL, + certificate, + }, + cloudWatchRole: true, // allows api gateway to write logs to cloudwatch + }; + + this.restApi = new apigw.RestApi(this, 'moderated-chat-rest-api', { + ...defaultRestApiProps, + }); + + new route53.ARecord(this, "moderated-chat-rest-api-dns", { + zone: hostedZone, + recordName: props.apiSubdomain, + comment: "This is the A Record used for the moderated chat api backend", + target: route53.RecordTarget.fromAlias( + new route53Targets.ApiGateway(this.restApi) + ), + }); + } else { + const defaultRestApiProps: apigw.RestApiProps = { + restApiName, + endpointTypes: [apigw.EndpointType.REGIONAL], + deploy: true, + description: "Rest api that contains the backend code/logic for the moderated chat demo", + deployOptions: { + stageName: 'prod', + accessLogDestination: new apigw.LogGroupLogDestination(logGroup), + accessLogFormat: apigw.AccessLogFormat.jsonWithStandardFields(), + throttlingRateLimit: 10, + throttlingBurstLimit: 25, + metricsEnabled: true, + loggingLevel: MethodLoggingLevel.INFO, + description: 'translation endpoint for momento console', + }, + defaultCorsPreflightOptions: { + allowOrigins: apigw.Cors.ALL_ORIGINS, + allowHeaders: apigw.Cors.DEFAULT_HEADERS, + allowMethods: apigw.Cors.ALL_METHODS, + }, + cloudWatchRole: true, // allows api gateway to write logs to cloudwatch + }; + this.restApi = new apigw.RestApi(this, 'moderated-chat-rest-api', { + ...defaultRestApiProps, + }); + } const secretsPath = 'moderated-chat/demo/secrets'; const v1TranslationApi = new lambda.Function(this, 'moderated-chat-translation-lambda-function', {