in source/solution-helper/index.ts [25:184]
export async function handler(event: ICustomResourceRequest, context: ILambdaContext) {
logger.log(LogLevel.INFO, `Received event: ${JSON.stringify(event)}`);
let response: ICompletionStatus = {
Status: StatusTypes.Success,
Data: {}
};
try {
switch (event.ResourceProperties.Action) {
case CustomResourceActions.GENERATE_SOLUTION_CONSTANTS:
const handlerOutput = await handleGenerateSolutionConstants(event);
if (!handlerOutput.anonymousUUID) {
response.Data.Message = `No action needed for ${event.RequestType}`;
} else {
response.Data.AnonymousDataUUID = handlerOutput.anonymousUUID;
response.Data.IotEndpointAddress = handlerOutput.iotEndpointAddress;
}
break;
case CustomResourceActions.SOLUTION_LIFECYCLE:
if (SEND_ANONYMOUS_DATA === 'Yes') {
await sendAnonymousMetric({
SolutionLifecycle: event.RequestType,
SolutionParameters: (event.ResourceProperties as ISolutionLifecycleRequestProps).SolutionParameters
});
}
if (event.RequestType === 'Delete') {
// Detach AWS IoT policy so that the resources can be deleted.
const { IotPolicyName } = (event.ResourceProperties as ISolutionLifecycleRequestProps);
try {
await detachIotPolicy(IotPolicyName);
} catch (error) {
logger.log(LogLevel.ERROR, `Detaching IoT policy failed.`);
throw error;
}
}
response.Data = { Message: `${event.RequestType} completed OK` };
break;
case CustomResourceActions.COPY_WEBSITE:
if ([CustomResourceRequestTypes.CREATE, CustomResourceRequestTypes.UPDATE].includes(event.RequestType)) {
const { SourceBucket, SourceKey, SourceManifest, DestinationBucket, WebsiteDistributionDomain } = (event.ResourceProperties as ICopyWebsiteRequestProps);
try {
response.Data = await copyWebsite(SourceBucket, SourceKey, SourceManifest, DestinationBucket, WebsiteDistributionDomain);
} catch (error) {
logger.log(LogLevel.ERROR, 'Copying website asset failed.');
throw error;
}
}
break;
case CustomResourceActions.PUT_WEBSITE_CONFIG:
if ([CustomResourceRequestTypes.CREATE, CustomResourceRequestTypes.UPDATE].includes(event.RequestType)) {
const { S3Bucket, AndonWebsiteConfigFileBaseName, AndonWebsiteConfig } = (event.ResourceProperties as IPutWebsiteConfigRequestProps);
const configFile = `const ${AndonWebsiteConfigFileBaseName} = ${JSON.stringify(AndonWebsiteConfig, null, 2)};`;
try {
logger.log(LogLevel.VERBOSE, 'Putting website config file', configFile);
response.Data = await putObject(S3Bucket, configFile, `assets/${AndonWebsiteConfigFileBaseName}.js`);
} catch (error) {
logger.log(LogLevel.ERROR, 'Put website config failed.');
throw error;
}
}
break;
case CustomResourceActions.CONFIGURE_BUCKET_NOTIFICATION:
try {
if (![CustomResourceRequestTypes.CREATE, CustomResourceRequestTypes.UPDATE, CustomResourceRequestTypes.DELETE].includes(event.RequestType)) {
break;
}
let shouldPutBucketNotificationConfig = false;
const { BucketName, FunctionArn } = (event.ResourceProperties as IConfigureBucketNotificationRequestProps);
const getBucketNotificationConfigParams: S3.GetBucketNotificationConfigurationRequest = {
Bucket: BucketName
};
logger.log(LogLevel.INFO, 'Getting bucket notification configuration');
logger.log(LogLevel.VERBOSE, 'Get bucket notification configuration parameters', JSON.stringify(getBucketNotificationConfigParams, null, 2));
const bucketNotificationConfig = await s3.getBucketNotificationConfiguration(getBucketNotificationConfigParams).promise();
logger.log(LogLevel.VERBOSE, 'Get bucket notification configuration response', JSON.stringify(bucketNotificationConfig, null, 2));
// Check to see if there is already a configuration for this function
let idx = -1;
if (bucketNotificationConfig.LambdaFunctionConfigurations) {
idx = bucketNotificationConfig.LambdaFunctionConfigurations.findIndex((c: any) => c.LambdaFunctionArn === FunctionArn);
}
if ([CustomResourceRequestTypes.CREATE, CustomResourceRequestTypes.UPDATE].includes(event.RequestType)) {
// Add the s3:ObjectCreated:* notification configuration to the bucket so it will call
// the external integrations handler Lambda function
const requiredS3Event = 's3:ObjectCreated:*';
const lambdaFnConfig: S3.LambdaFunctionConfiguration = {
Events: [requiredS3Event],
LambdaFunctionArn: FunctionArn
};
if (!bucketNotificationConfig.LambdaFunctionConfigurations) {
bucketNotificationConfig.LambdaFunctionConfigurations = [lambdaFnConfig];
} else {
if (idx > -1) {
// Make sure the required event is included. Use a Set to ensure a unique list
bucketNotificationConfig.LambdaFunctionConfigurations[idx].Events = Array.from(new Set<string>([...bucketNotificationConfig.LambdaFunctionConfigurations[idx].Events, requiredS3Event]));
} else {
bucketNotificationConfig.LambdaFunctionConfigurations.push(lambdaFnConfig);
}
}
shouldPutBucketNotificationConfig = true;
} else {
// Remove the bucket configuration for the external integration handler
if (idx > -1) {
bucketNotificationConfig.LambdaFunctionConfigurations.splice(idx, 1);
shouldPutBucketNotificationConfig = true;
}
}
const bucketNotificationConfigParams: S3.PutBucketNotificationConfigurationRequest = {
Bucket: BucketName,
NotificationConfiguration: bucketNotificationConfig
};
if (shouldPutBucketNotificationConfig) {
logger.log(LogLevel.INFO, 'Putting Bucket Notification Configuration', JSON.stringify(bucketNotificationConfigParams, null, 2));
await s3.putBucketNotificationConfiguration(bucketNotificationConfigParams).promise();
response.Data = { Message: 'Bucket Notification Configuration Put Successfully' };
} else {
response.Data = { Message: 'No update to Bucket Notification Configuration needed' };
}
} catch (err) {
logger.log(LogLevel.ERROR, 'Error while putting bucket notification configuration');
throw err;
}
break;
default:
break;
}
} catch (error) {
logger.log(LogLevel.ERROR, `Error occurred at ${event.RequestType} ${event.ResourceType}:`, error);
response = {
Status: StatusTypes.Failed,
Data: {
Error: error.message
}
}
} finally {
await sendResponse(event, context.logStreamName, response);
}
return response;
}