export async function handler()

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;
}