Skip to content

Commit

Permalink
feat(aws-cloudwatch-actions): add ssm incidents as alarm action (aws#…
Browse files Browse the repository at this point in the history
…21167)

Finishes work originally contributed by @dosatos by addressing changes requested by @comcalvi in [aws#20553](aws#20553)

closes [aws#20552](aws#20552)
  • Loading branch information
callumthomson authored and josephedward committed Aug 30, 2022
1 parent 7acd9e9 commit def0b15
Show file tree
Hide file tree
Showing 11 changed files with 369 additions and 1 deletion.
10 changes: 10 additions & 0 deletions packages/@aws-cdk/aws-cloudwatch-actions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,14 @@ alarm.addAlarmAction(
);
```

## SSM Incident Manager Action Example

```ts
declare const alarm: cloudwatch.Alarm;
// Create an Incident Manager incident based on a specific response plan
alarm.addAlarmAction(
new actions.SsmIncidentAction('ResponsePlanName')
);
```

See `@aws-cdk/aws-cloudwatch` for more information.
17 changes: 17 additions & 0 deletions packages/@aws-cdk/aws-cloudwatch-actions/lib/ssm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,20 @@ export class SsmAction implements cloudwatch.IAlarmAction {
}
}

/**
* Use an SSM Incident Response Plan as an Alarm action
*/
export class SsmIncidentAction implements cloudwatch.IAlarmAction {
constructor(private readonly responsePlanName: string) {}

/**
* Returns an alarm action configuration to use an SSM Incident as an alarm action
* based on an Incident Manager Response Plan
*/
bind(_scope: Construct, _alarm: cloudwatch.IAlarm): cloudwatch.AlarmActionConfig {
return {
alarmActionArn: `arn:${Stack.of(_scope).partition}:ssm-incidents::${Stack.of(_scope).account}:response-plan/${this.responsePlanName}`,
};
}
}

3 changes: 3 additions & 0 deletions packages/@aws-cdk/aws-cloudwatch-actions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,11 @@
"devDependencies": {
"@aws-cdk/assertions": "0.0.0",
"@aws-cdk/aws-ec2": "0.0.0",
"@aws-cdk/aws-cloudwatch": "0.0.0",
"@aws-cdk/aws-ssmincidents": "0.0.0",
"@aws-cdk/cdk-build-tools": "0.0.0",
"@aws-cdk/integ-runner": "0.0.0",
"@aws-cdk/integ-tests": "0.0.0",
"@aws-cdk/cfn2ts": "0.0.0",
"@aws-cdk/pkglint": "0.0.0",
"@types/jest": "^27.5.2",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as cloudwatch from '@aws-cdk/aws-cloudwatch';
import * as ssmIncidents from '@aws-cdk/aws-ssmincidents';
import { App, Stack, StackProps } from '@aws-cdk/core';
import * as integ from '@aws-cdk/integ-tests';

import * as cloudwatchActions from '../lib';

class SsmIncidentAlarmActionIntegrationTestStack extends Stack {

constructor(scope: App, id: string, props?: StackProps) {
super(scope, id, props);

const responsePlanName = 'test-response-plan';

new ssmIncidents.CfnResponsePlan(this, 'ResponsePlan', {
name: responsePlanName,
incidentTemplate: {
title: 'Incident Title',
impact: 1,
},
});

const metric = new cloudwatch.Metric({
namespace: 'CDK/Test',
metricName: 'Metric',
label: 'Metric [AVG: ${AVG}]',
});

const alarm = new cloudwatch.Alarm(this, 'Alarm1', {
metric,
threshold: 100,
evaluationPeriods: 3,
});

alarm.addAlarmAction(new cloudwatchActions.SsmIncidentAction(responsePlanName));
}
}

const app = new App();

const stack = new SsmIncidentAlarmActionIntegrationTestStack(app, 'SsmIncidentAlarmActionIntegrationTestStack');

new integ.IntegTest(app, 'SsmIncidentManagerAlarmActionTest', {
testCases: [stack],
});

app.synth();
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"Resources": {
"ResponsePlan": {
"Type": "AWS::SSMIncidents::ResponsePlan",
"Properties": {
"IncidentTemplate": {
"Impact": 1,
"Title": "Incident Title"
},
"Name": "test-response-plan"
}
},
"Alarm1F9009D71": {
"Type": "AWS::CloudWatch::Alarm",
"Properties": {
"ComparisonOperator": "GreaterThanOrEqualToThreshold",
"EvaluationPeriods": 3,
"AlarmActions": [
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":ssm-incidents::",
{
"Ref": "AWS::AccountId"
},
":response-plan/test-response-plan"
]
]
}
],
"Metrics": [
{
"Id": "m1",
"Label": "Metric [AVG: ${AVG}]",
"MetricStat": {
"Metric": {
"MetricName": "Metric",
"Namespace": "CDK/Test"
},
"Period": 300,
"Stat": "Average"
},
"ReturnData": true
}
],
"Threshold": 100
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"version":"20.0.0"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"version": "20.0.0",
"testCases": {
"SsmIncidentManagerAlarmActionTest/DefaultTest": {
"stacks": [
"SsmIncidentAlarmActionIntegrationTestStack"
],
"assertionStack": "SsmIncidentManagerAlarmActionTestDefaultTestDeployAssert9DC05EC0"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"version": "20.0.0",
"artifacts": {
"Tree": {
"type": "cdk:tree",
"properties": {
"file": "tree.json"
}
},
"SsmIncidentAlarmActionIntegrationTestStack": {
"type": "aws:cloudformation:stack",
"environment": "aws://unknown-account/unknown-region",
"properties": {
"templateFile": "SsmIncidentAlarmActionIntegrationTestStack.template.json",
"validateOnSynth": false
},
"metadata": {
"/SsmIncidentAlarmActionIntegrationTestStack/ResponsePlan": [
{
"type": "aws:cdk:logicalId",
"data": "ResponsePlan"
}
],
"/SsmIncidentAlarmActionIntegrationTestStack/Alarm1/Resource": [
{
"type": "aws:cdk:logicalId",
"data": "Alarm1F9009D71"
}
]
},
"displayName": "SsmIncidentAlarmActionIntegrationTestStack"
},
"SsmIncidentManagerAlarmActionTestDefaultTestDeployAssert9DC05EC0": {
"type": "aws:cloudformation:stack",
"environment": "aws://unknown-account/unknown-region",
"properties": {
"templateFile": "SsmIncidentManagerAlarmActionTestDefaultTestDeployAssert9DC05EC0.template.json",
"validateOnSynth": false
},
"displayName": "SsmIncidentManagerAlarmActionTest/DefaultTest/DeployAssert"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
{
"version": "tree-0.1",
"tree": {
"id": "App",
"path": "",
"children": {
"Tree": {
"id": "Tree",
"path": "Tree",
"constructInfo": {
"fqn": "@aws-cdk/core.Construct",
"version": "0.0.0"
}
},
"SsmIncidentAlarmActionIntegrationTestStack": {
"id": "SsmIncidentAlarmActionIntegrationTestStack",
"path": "SsmIncidentAlarmActionIntegrationTestStack",
"children": {
"ResponsePlan": {
"id": "ResponsePlan",
"path": "SsmIncidentAlarmActionIntegrationTestStack/ResponsePlan",
"attributes": {
"aws:cdk:cloudformation:type": "AWS::SSMIncidents::ResponsePlan",
"aws:cdk:cloudformation:props": {
"incidentTemplate": {
"title": "Incident Title",
"impact": 1
},
"name": "test-response-plan"
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-ssmincidents.CfnResponsePlan",
"version": "0.0.0"
}
},
"Alarm1": {
"id": "Alarm1",
"path": "SsmIncidentAlarmActionIntegrationTestStack/Alarm1",
"children": {
"Resource": {
"id": "Resource",
"path": "SsmIncidentAlarmActionIntegrationTestStack/Alarm1/Resource",
"attributes": {
"aws:cdk:cloudformation:type": "AWS::CloudWatch::Alarm",
"aws:cdk:cloudformation:props": {
"comparisonOperator": "GreaterThanOrEqualToThreshold",
"evaluationPeriods": 3,
"alarmActions": [
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":ssm-incidents::",
{
"Ref": "AWS::AccountId"
},
":response-plan/test-response-plan"
]
]
}
],
"metrics": [
{
"metricStat": {
"metric": {
"metricName": "Metric",
"namespace": "CDK/Test"
},
"period": 300,
"stat": "Average"
},
"id": "m1",
"label": "Metric [AVG: ${AVG}]",
"returnData": true
}
],
"threshold": 100
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-cloudwatch.CfnAlarm",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-cloudwatch.Alarm",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/core.Stack",
"version": "0.0.0"
}
},
"SsmIncidentManagerAlarmActionTest": {
"id": "SsmIncidentManagerAlarmActionTest",
"path": "SsmIncidentManagerAlarmActionTest",
"children": {
"DefaultTest": {
"id": "DefaultTest",
"path": "SsmIncidentManagerAlarmActionTest/DefaultTest",
"children": {
"Default": {
"id": "Default",
"path": "SsmIncidentManagerAlarmActionTest/DefaultTest/Default",
"constructInfo": {
"fqn": "@aws-cdk/core.Construct",
"version": "0.0.0"
}
},
"DeployAssert": {
"id": "DeployAssert",
"path": "SsmIncidentManagerAlarmActionTest/DefaultTest/DeployAssert",
"constructInfo": {
"fqn": "@aws-cdk/core.Stack",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/integ-tests.IntegTestCase",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/integ-tests.IntegTest",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/core.App",
"version": "0.0.0"
}
}
}
Loading

0 comments on commit def0b15

Please sign in to comment.