Skip to content

Commit

Permalink
Merge pull request #307 from getlift/fix-queues-construct-alarm-exten…
Browse files Browse the repository at this point in the history
…sion

Fix queues construct alarm extension
  • Loading branch information
fredericbarthelet authored Feb 24, 2023
2 parents c27f379 + 519148d commit 5ff580e
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 4 deletions.
2 changes: 2 additions & 0 deletions docs/queue.md
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,8 @@ constructs:
| dlq | AWS::SQS::Queue | [Link](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html) |
| alarm | AWS::CloudWatch::Alarm | [Link](https://docs.aws.amazon.com/fr_fr/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html) |

> ⚠️ The `alarm` extension key is only available if an alarm email destination has been configured on the construct.

### More options

Feel like a common extension pattern should be implemented as part of the construct configuration? [Open a GitHub issue](https://github.com/getlift/lift/issues/new).
15 changes: 11 additions & 4 deletions src/constructs/aws/Queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Key } from "aws-cdk-lib/aws-kms";
import type { CfnQueue } from "aws-cdk-lib/aws-sqs";
import { Queue as CdkQueue, QueueEncryption } from "aws-cdk-lib/aws-sqs";
import type { FromSchema } from "json-schema-to-ts";
import type { CfnAlarm } from "aws-cdk-lib/aws-cloudwatch";
import { Alarm, ComparisonOperator, Metric } from "aws-cdk-lib/aws-cloudwatch";
import { Subscription, SubscriptionProtocol, Topic } from "aws-cdk-lib/aws-sns";
import type { AlarmActionConfig } from "aws-cdk-lib/aws-cloudwatch/lib/alarm-action";
Expand Down Expand Up @@ -117,6 +118,7 @@ export class Queue extends AwsConstruct {

private readonly queue: CdkQueue;
private readonly dlq: CdkQueue;
private readonly alarm?: Alarm;
private readonly queueArnOutput: CfnOutput;
private readonly queueUrlOutput: CfnOutput;
private readonly dlqUrlOutput: CfnOutput;
Expand Down Expand Up @@ -218,7 +220,7 @@ export class Queue extends AwsConstruct {
endpoint: alarmEmail,
});

const alarm = new Alarm(this, "Alarm", {
this.alarm = new Alarm(this, "Alarm", {
alarmName: `${this.provider.stackName}-${id}-dlq-alarm`,
alarmDescription: "Alert triggered when there are failed jobs in the dead letter queue.",
metric: new Metric({
Expand All @@ -235,7 +237,7 @@ export class Queue extends AwsConstruct {
threshold: 0,
comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,
});
alarm.addAlarmAction({
this.alarm.addAlarmAction({
bind(): AlarmActionConfig {
return { alarmActionArn: alarmTopic.topicArn };
},
Expand Down Expand Up @@ -279,11 +281,16 @@ export class Queue extends AwsConstruct {
}

extend(): Record<string, CfnResource> {
return {
const extensions = {
queue: this.queue.node.defaultChild as CfnQueue,
dlq: this.dlq.node.defaultChild as CfnQueue,
alarm: this.dlq.node.defaultChild as CfnQueue,
};

if (this.alarm !== undefined) {
Object.assign(extensions, { alarm: this.alarm.node.defaultChild as CfnAlarm });
}

return extensions;
}

private getMaximumBatchingWindow(): number {
Expand Down
54 changes: 54 additions & 0 deletions test/unit/queues.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -620,4 +620,58 @@ describe("queues", () => {
MaximumMessageSize: 1024,
});
});

it("allows overriding alarm properties", async () => {
const { cfTemplate, computeLogicalId } = await runServerless({
fixture: "queues",
configExt: merge({}, pluginConfigExt, {
constructs: {
emails: {
alarm: "myemail@mycompany.com",
extensions: {
alarm: {
Properties: {
AlarmActions: ["arn:aws:sns:region:account-id:sns-topic-name"],
},
},
},
},
},
}),
command: "package",
});
expect(cfTemplate.Resources[computeLogicalId("emails", "Alarm")].Properties).toMatchObject({
AlarmActions: ["arn:aws:sns:region:account-id:sns-topic-name"],
});
});

it("should throw if overriding alarm properties while no alarm is configured", async () => {
expect.assertions(2);

try {
await runServerless({
fixture: "queues",
configExt: merge({}, pluginConfigExt, {
constructs: {
emails: {
extensions: {
alarm: {
Properties: {
AlarmActions: ["arn:aws:sns:region:account-id:sns-topic-name"],
},
},
},
},
},
}),
command: "package",
});
} catch (error) {
expect(error).toBeInstanceOf(ServerlessError);
expect(error).toHaveProperty(
"message",
"There is no extension 'alarm' available on this construct. Available extensions are: queue, dlq."
);
}
});
});

0 comments on commit 5ff580e

Please sign in to comment.