diff --git a/packages/@aws-cdk/aws-cloudwatch-actions/README.md b/packages/@aws-cdk/aws-cloudwatch-actions/README.md index 99eb74e06eb54..7788dc363a5ec 100644 --- a/packages/@aws-cdk/aws-cloudwatch-actions/README.md +++ b/packages/@aws-cdk/aws-cloudwatch-actions/README.md @@ -11,7 +11,7 @@ This library contains a set of classes which can be used as CloudWatch Alarm actions. -The currently implemented actions are: EC2 Actions, SNS Actions, Autoscaling Actions and Aplication Autoscaling Actions +The currently implemented actions are: EC2 Actions, SNS Actions, SSM OpsCenter Actions, Autoscaling Actions and Application Autoscaling Actions ## EC2 Action Example @@ -25,4 +25,17 @@ alarm.addAlarmAction( ); ``` +## SSM OpsCenter Action Example + +```ts +declare const alarm: cloudwatch.Alarm; +// Create an OpsItem with specific severity and category when alarm triggers +alarm.addAlarmAction( + new actions.SsmAction( + actions.OpsItemSeverity.CRITICAL, + actions.OpsItemCategory.PERFORMANCE // category is optional + ) +); +``` + See `@aws-cdk/aws-cloudwatch` for more information. diff --git a/packages/@aws-cdk/aws-cloudwatch-actions/lib/index.ts b/packages/@aws-cdk/aws-cloudwatch-actions/lib/index.ts index 5a384eba01247..191da008b23a9 100644 --- a/packages/@aws-cdk/aws-cloudwatch-actions/lib/index.ts +++ b/packages/@aws-cdk/aws-cloudwatch-actions/lib/index.ts @@ -2,3 +2,4 @@ export * from './appscaling'; export * from './autoscaling'; export * from './sns'; export * from './ec2'; +export * from './ssm'; diff --git a/packages/@aws-cdk/aws-cloudwatch-actions/lib/ssm.ts b/packages/@aws-cdk/aws-cloudwatch-actions/lib/ssm.ts new file mode 100644 index 0000000000000..0d26c4258c0d5 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudwatch-actions/lib/ssm.ts @@ -0,0 +1,79 @@ +import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; +import { Stack } from '@aws-cdk/core'; + +// keep this import separate from other imports to reduce chance for merge conflicts with v2-main +// eslint-disable-next-line no-duplicate-imports, import/order +import { Construct } from '@aws-cdk/core'; + +/** + * Types of OpsItem severity available + */ +export enum OpsItemSeverity { + /** + * Set the severity to critical + */ + CRITICAL = '1', + /** + * Set the severity to high + */ + HIGH = '2', + /** + * Set the severity to medium + */ + MEDIUM = '3', + /** + * Set the severity to low + */ + LOW = '4' +} + +/** + * Types of OpsItem category available + */ +export enum OpsItemCategory { + /** + * Set the category to availability + */ + AVAILABILITY = 'Availability', + /** + * Set the category to cost + */ + COST = 'Cost', + /** + * Set the category to performance + */ + PERFORMANCE = 'Performance', + /** + * Set the category to recovery + */ + RECOVERY = 'Recovery', + /** + * Set the category to security + */ + SECURITY = 'Security' +} + +/** + * Use an SSM OpsItem action as an Alarm action + */ +export class SsmAction implements cloudwatch.IAlarmAction { + private severity: OpsItemSeverity; + private category?: OpsItemCategory; + + constructor(severity: OpsItemSeverity, category?: OpsItemCategory) { + this.severity = severity; + this.category = category; + } + + /** + * Returns an alarm action configuration to use an SSM OpsItem action as an alarm action + */ + bind(_scope: Construct, _alarm: cloudwatch.IAlarm): cloudwatch.AlarmActionConfig { + if (this.category === undefined) { + return { alarmActionArn: `arn:aws:ssm:${Stack.of(_scope).region}:${Stack.of(_scope).account}:opsitem:${this.severity}` }; + } else { + return { alarmActionArn: `arn:aws:ssm:${Stack.of(_scope).region}:${Stack.of(_scope).account}:opsitem:${this.severity}#CATEGORY=${this.category}` }; + } + } +} + diff --git a/packages/@aws-cdk/aws-cloudwatch-actions/test/ssm.test.ts b/packages/@aws-cdk/aws-cloudwatch-actions/test/ssm.test.ts new file mode 100644 index 0000000000000..a4bb582005b22 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudwatch-actions/test/ssm.test.ts @@ -0,0 +1,82 @@ +import { Template } from '@aws-cdk/assertions'; +import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; +import { Stack } from '@aws-cdk/core'; +import * as actions from '../lib'; + +test('can use ssm with critical severity and performance category as alarm action', () => { + // GIVEN + const stack = new Stack(); + const alarm = new cloudwatch.Alarm(stack, 'Alarm', { + metric: new cloudwatch.Metric({ + namespace: 'AWS', + metricName: 'Test', + }), + evaluationPeriods: 3, + threshold: 100, + }); + + // WHEN + alarm.addAlarmAction(new actions.SsmAction(actions.OpsItemSeverity.CRITICAL, actions.OpsItemCategory.PERFORMANCE)); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { + AlarmActions: [ + { + 'Fn::Join': [ + '', + [ + 'arn:aws:ssm:', + { + Ref: 'AWS::Region', + }, + ':', + { + Ref: 'AWS::AccountId', + }, + ':opsitem:1#CATEGORY=Performance', + ], + ], + }, + ], + }); +}); + + +test('can use ssm with meduim severity and no category as alarm action', () => { + // GIVEN + const stack = new Stack(); + const alarm = new cloudwatch.Alarm(stack, 'Alarm', { + metric: new cloudwatch.Metric({ + namespace: 'AWS', + metricName: 'Test', + }), + evaluationPeriods: 3, + threshold: 100, + }); + + // WHEN + alarm.addAlarmAction(new actions.SsmAction(actions.OpsItemSeverity.MEDIUM)); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { + AlarmActions: [ + { + 'Fn::Join': [ + '', + [ + 'arn:aws:ssm:', + { + Ref: 'AWS::Region', + }, + ':', + { + Ref: 'AWS::AccountId', + }, + ':opsitem:3', + ], + ], + }, + ], + }); +}); +