in consumers/online/infrastructure/lib/websiteConstruct.ts [41:161]
constructor(scope: cdk.Construct, id: string, props: WebsiteConstructProps) {
super(scope, id);
const cloudFrontOia = new cloudfront.CfnCloudFrontOriginAccessIdentity(this, 'OIA', {
cloudFrontOriginAccessIdentityConfig: {
comment: 'OIA for website.',
},
});
const originAccessIdentity = cloudfront.OriginAccessIdentity.fromOriginAccessIdentityName(
this,
'OriginAccessIdentity',
cloudFrontOia.ref
);
const sourceBucket = new s3.Bucket(this, 'WebsiteBucket', {
websiteIndexDocument: 'index.html',
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
encryption: s3.BucketEncryption.S3_MANAGED,
});
const cloudFrontLoggingBucket = new s3.Bucket(this, 'S3BucketForWebsiteLogging', {
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
encryption: s3.BucketEncryption.S3_MANAGED
});
const cloudFrontDistribution = new cloudfront.CloudFrontWebDistribution(this, 'WebsiteCloudFront', {
priceClass: cloudfront.PriceClass.PRICE_CLASS_ALL,
defaultRootObject: 'index.html',
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
loggingConfig: {
bucket: cloudFrontLoggingBucket,
},
originConfigs: [
{
s3OriginSource: {
s3BucketSource: sourceBucket,
originAccessIdentity,
},
behaviors: [{ isDefaultBehavior: true }],
},
],
errorConfigurations: [
{
errorCode: 404,
responseCode: 200,
responsePagePath: `/index.html`,
errorCachingMinTtl: 0,
},
],
});
/**S3 bucket storing the dynamically generated index files.*/
const websiteIndexBucket = new s3.Bucket(this, 'WebsiteIndexBucket', {
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
encryption: s3.BucketEncryption.S3_MANAGED
});
const buildWebsiteIndexFunction = new lambdaNodeJs.NodejsFunction(this, 'BuildWebsiteIndexFunction', {
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'handler',
entry: path.join(__dirname, '../customResources/websiteIndex/index.ts'),
timeout: cdk.Duration.minutes(1),
reservedConcurrentExecutions: 1,
});
websiteIndexBucket.grantReadWrite(buildWebsiteIndexFunction);
const buildWebsiteIndexCustomResourceProvider = new customResource.Provider(
this,
'BuildWebsiteIndexCustomResourceProvider',
{
onEventHandler: buildWebsiteIndexFunction,
logRetention: logs.RetentionDays.ONE_DAY,
}
);
const indexFile = fs.readFileSync(path.join(props.websiteDistPath, 'index.html'), 'utf8');
const buildWebsiteIndexCustomResource = new cdk.CustomResource(this, 'BuildWebsiteIndexCustomResource', {
serviceToken: buildWebsiteIndexCustomResourceProvider.serviceToken,
properties: {
s3BucketName: websiteIndexBucket.bucketName,
template: indexFile,
apiUrl: props.api.url,
},
});
buildWebsiteIndexCustomResource.node.addDependency(websiteIndexBucket, props.api);
const cachedDeployment = new s3Deployment.BucketDeployment(this, 'CachedDeployWebsite', {
sources: [
s3Deployment.Source.asset(props.websiteDistPath, {
exclude: ['index.html', 'config.js', 'config.*.js'],
}),
],
prune: false,
destinationBucket: sourceBucket,
distribution: cloudFrontDistribution,
});
const uncachedDeployment = new s3Deployment.BucketDeployment(this, 'UncachedDeployWebsite', {
sources: [s3Deployment.Source.bucket(websiteIndexBucket, buildWebsiteIndexCustomResource.ref)],
destinationBucket: sourceBucket,
prune: false,
distribution: cloudFrontDistribution,
cacheControl: [s3Deployment.CacheControl.noCache()],
});
uncachedDeployment.node.addDependency(cachedDeployment, buildWebsiteIndexCustomResource);
new cdk.CfnOutput(this, 'ModelConsumerOnlineWebsiteCloudfrontDistributionId', {
value: cloudFrontDistribution.distributionId,
exportName: `ModelConsumerOnlineWebsiteCloudfrontDistributionId`,
});
new cdk.CfnOutput(this, 'ModelConsumerOnlineCloudfrontDistributionDomainName', {
value: cloudFrontDistribution.distributionDomainName,
exportName: `ModelConsumerOnlineWebsiteCloudfrontDistributionDomainName`,
});
}