export async function handler()

in packages/aws-rfdk/lib/lambdas/nodejs/unhealthyFleetAction/index.ts [18:93]


export async function handler(event: AWSLambda.SNSEvent, context: AWSLambda.Context) {

  console.log(JSON.stringify(event));

  try {

    // each alarm notification should have only one record.
    if (event.Records.length !== 1) {
      throw new Error('Expecting a single record in SNS Event, found ' + event.Records.length);
    }

    const record = event.Records[0];

    if (!record.Sns || !record.Sns.Message) {
      throw new Error('No message found in the SNS Event.');
    }

    const message = JSON.parse(record.Sns.Message);
    const metrics = message.Trigger.Metrics;

    /**
     * The unhealthy fleet alarm is created using following 3 metrics:
     * 1. ASG desired capacity
     * 2. Unhealthy target count
     * 3. Expression to calculate percent
     * If these 3 metrics are not passed, throw an exception, something went wrong.
     */
    if (!metrics || metrics.length !== 3) {
      throw new Error('Exactly 3 metrics should be present in the alarm message');
    }

    // find the metric with the ASG dimension in it.
    const autoScalingGroupDimensions = metrics.filter((metric: any) => metric.Id === 'fleetCapacity')
      .map((metric: any) => {
        if (metric && metric.MetricStat && metric.MetricStat.Metric && metric.MetricStat.Metric.Dimensions) {
          return metric.MetricStat.Metric.Dimensions.filter((dimension: any) => dimension.name === 'AutoScalingGroupName');
        }
      });

    if (autoScalingGroupDimensions.length !== 1) {
      throw new Error(`There should be exactly one Metric with Id "fleetCapacity". Found ${autoScalingGroupDimensions.length}`);
    }

    if (autoScalingGroupDimensions[0].length !== 1) {
      throw new Error(`There should be exactly one dimension with name "AutoScalingGroupName". Found ${autoScalingGroupDimensions[0].length}`);
    }

    const dimensionName = autoScalingGroupDimensions[0][0].name;
    const dimensionValue = autoScalingGroupDimensions[0][0].value;

    console.info(`Found fleet: ${dimensionName} with fleetId: ${dimensionValue}`);

    // this is an ASG Target, we need to suspend its size
    const autoScaling = new AutoScalingClient();
    await autoScaling.send(new UpdateAutoScalingGroupCommand({
      AutoScalingGroupName: dimensionValue,
      MaxSize: 0,
      MinSize: 0,
      DesiredCapacity: 0,
    })).then((data: any) => {
      // successful response
      console.log(`Successfully suspended the fleet ${dimensionValue}: ${data}`);
    }).catch((err: any) => {
      // an error occurred
      throw new Error(`Exception while suspending fleet ${dimensionValue}: ${err}`);
    });
  } catch (e) {
    console.error(`ERROR: Exception while processing the event: ${e}`);
    return {
      status: 'ERROR',
      reason: isNativeError(e) ? e.message : String(e),
    };
  }

  return {status: 'OK'};
}