diff --git a/packages/@aws-cdk/aws-appconfig-alpha/README.md b/packages/@aws-cdk/aws-appconfig-alpha/README.md index bbe1f9c2286d3..4e48ed0a568ff 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/README.md +++ b/packages/@aws-cdk/aws-appconfig-alpha/README.md @@ -370,11 +370,13 @@ Basic environment with monitors: ```ts declare const application: appconfig.Application; declare const alarm: cloudwatch.Alarm; +declare const compositeAlarm: cloudwatch.CompositeAlarm; new appconfig.Environment(this, 'MyEnvironment', { application, monitors: [ appconfig.Monitor.fromCloudWatchAlarm(alarm), + appconfig.Monitor.fromCloudWatchAlarm(compositeAlarm), ], }); ``` diff --git a/packages/@aws-cdk/aws-appconfig-alpha/lib/environment.ts b/packages/@aws-cdk/aws-appconfig-alpha/lib/environment.ts index c77bbe8975106..70109132b7443 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/lib/environment.ts +++ b/packages/@aws-cdk/aws-appconfig-alpha/lib/environment.ts @@ -256,7 +256,7 @@ export class Environment extends EnvironmentBase { return { alarmArn: monitor.alarmArn, ...(monitor.monitorType === MonitorType.CLOUDWATCH - ? { alarmRoleArn: monitor.alarmRoleArn || this.createAlarmRole(monitor.alarmArn, index).roleArn } + ? { alarmRoleArn: monitor.alarmRoleArn || this.createAlarmRole(monitor, index).roleArn } : { alarmRoleArn: monitor.alarmRoleArn }), }; }), @@ -274,7 +274,20 @@ export class Environment extends EnvironmentBase { this.application.addExistingEnvironment(this); } - private createAlarmRole(alarmArn: string, index: number): iam.IRole { + private createAlarmRole(monitor: Monitor, index: number): iam.IRole { + const logicalId = monitor.isCompositeAlarm ? 'RoleCompositeAlarm' : `Role${index}`; + const existingRole = this.node.tryFindChild(logicalId) as iam.IRole; + if (existingRole) { + return existingRole; + } + const alarmArn = monitor.isCompositeAlarm + ? this.stack.formatArn({ + service: 'cloudwatch', + resource: 'alarm', + resourceName: '*', + arnFormat: ArnFormat.COLON_RESOURCE_NAME, + }) + : monitor.alarmArn; const policy = new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['cloudwatch:DescribeAlarms'], @@ -283,7 +296,7 @@ export class Environment extends EnvironmentBase { const document = new iam.PolicyDocument({ statements: [policy], }); - const role = new iam.Role(this, `Role${index}`, { + const role = new iam.Role(this, logicalId, { roleName: PhysicalName.GENERATE_IF_NEEDED, assumedBy: new iam.ServicePrincipal('appconfig.amazonaws.com'), inlinePolicies: { @@ -325,6 +338,7 @@ export abstract class Monitor { alarmArn: alarm.alarmArn, alarmRoleArn: alarmRole?.roleArn, monitorType: MonitorType.CLOUDWATCH, + isCompositeAlarm: alarm instanceof cloudwatch.CompositeAlarm, }; } @@ -355,6 +369,11 @@ export abstract class Monitor { * The IAM role ARN for AWS AppConfig to view the alarm state. */ public abstract readonly alarmRoleArn?: string; + + /** + * Indicates whether a CloudWatch alarm is a composite alarm. + */ + public abstract readonly isCompositeAlarm?: boolean; } export interface IEnvironment extends IResource { diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/environment.test.ts b/packages/@aws-cdk/aws-appconfig-alpha/test/environment.test.ts index a7426b2e2e3e7..9c6dd7c7f3e4b 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/environment.test.ts +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/environment.test.ts @@ -1,7 +1,7 @@ import * as cdk from 'aws-cdk-lib'; import { App } from 'aws-cdk-lib'; import { Template } from 'aws-cdk-lib/assertions'; -import { Alarm, Metric } from 'aws-cdk-lib/aws-cloudwatch'; +import { Alarm, CompositeAlarm, Metric } from 'aws-cdk-lib/aws-cloudwatch'; import * as iam from 'aws-cdk-lib/aws-iam'; import { Application, Environment, Monitor } from '../lib'; @@ -230,6 +230,185 @@ describe('environment', () => { }); }); + test('environment with composite alarm', () => { + const stack = new cdk.Stack(); + const app = new Application(stack, 'MyAppConfig'); + const alarm = new Alarm(stack, 'Alarm', { + threshold: 5, + evaluationPeriods: 5, + metric: new Metric( + { + namespace: 'aws', + metricName: 'myMetric', + }, + ), + }); + const compositeAlarm = new CompositeAlarm(stack, 'MyCompositeAlarm', { + alarmRule: alarm, + }); + const env = new Environment(stack, 'MyEnvironment', { + name: 'TestEnv', + application: app, + monitors: [ + Monitor.fromCloudWatchAlarm(compositeAlarm), + ], + }); + + expect(env).toBeDefined(); + Template.fromStack(stack).resourceCountIs('AWS::CloudWatch::Alarm', 1); + Template.fromStack(stack).resourceCountIs('AWS::CloudWatch::CompositeAlarm', 1); + Template.fromStack(stack).hasResourceProperties('AWS::AppConfig::Environment', { + Name: 'TestEnv', + ApplicationId: { + Ref: 'MyAppConfigB4B63E75', + }, + Monitors: [ + { + AlarmArn: { + 'Fn::GetAtt': [ + 'MyCompositeAlarm0F045229', + 'Arn', + ], + }, + AlarmRoleArn: { + 'Fn::GetAtt': [ + 'MyEnvironmentRoleCompositeAlarm8C2A0542', + 'Arn', + ], + }, + }, + ], + }); + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { + Policies: [ + { + PolicyDocument: { + Statement: [ + { + Effect: iam.Effect.ALLOW, + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':cloudwatch:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':alarm:*', + ], + ], + }, + Action: 'cloudwatch:DescribeAlarms', + }, + ], + }, + PolicyName: 'AllowAppConfigMonitorAlarmPolicy', + }, + ], + }); + }); + + test('environment with two composite alarms', () => { + const stack = new cdk.Stack(); + const app = new Application(stack, 'MyAppConfig'); + const alarm = new Alarm(stack, 'Alarm', { + threshold: 5, + evaluationPeriods: 5, + metric: new Metric( + { + namespace: 'aws', + metricName: 'myMetric', + }, + ), + }); + const compositeAlarm1 = new CompositeAlarm(stack, 'MyCompositeAlarm1', { + alarmRule: alarm, + }); + const compositeAlarm2 = new CompositeAlarm(stack, 'MyCompositeAlarm2', { + alarmRule: alarm, + }); + const env = new Environment(stack, 'MyEnvironment', { + name: 'TestEnv', + application: app, + monitors: [ + Monitor.fromCloudWatchAlarm(compositeAlarm1), + Monitor.fromCloudWatchAlarm(compositeAlarm2), + ], + }); + + expect(env).toBeDefined(); + Template.fromStack(stack).resourceCountIs('AWS::CloudWatch::Alarm', 1); + Template.fromStack(stack).resourceCountIs('AWS::CloudWatch::CompositeAlarm', 2); + Template.fromStack(stack).resourceCountIs('AWS::IAM::Role', 1); + Template.fromStack(stack).hasResourceProperties('AWS::AppConfig::Environment', { + Name: 'TestEnv', + ApplicationId: { + Ref: 'MyAppConfigB4B63E75', + }, + Monitors: [ + { + AlarmArn: { + 'Fn::GetAtt': [ + 'MyCompositeAlarm159A950D0', + 'Arn', + ], + }, + AlarmRoleArn: { + 'Fn::GetAtt': [ + 'MyEnvironmentRoleCompositeAlarm8C2A0542', + 'Arn', + ], + }, + }, + { + AlarmArn: { + 'Fn::GetAtt': [ + 'MyCompositeAlarm2195BFA48', + 'Arn', + ], + }, + AlarmRoleArn: { + 'Fn::GetAtt': [ + 'MyEnvironmentRoleCompositeAlarm8C2A0542', + 'Arn', + ], + }, + }, + ], + }); + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { + Policies: [ + { + PolicyDocument: { + Statement: [ + { + Effect: iam.Effect.ALLOW, + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':cloudwatch:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':alarm:*', + ], + ], + }, + Action: 'cloudwatch:DescribeAlarms', + }, + ], + }, + PolicyName: 'AllowAppConfigMonitorAlarmPolicy', + }, + ], + }); + }); + test('environment with monitors with two alarms', () => { const stack = new cdk.Stack(); const app = new Application(stack, 'MyAppConfig'); diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/appconfigenvironmentDefaultTestDeployAssert75BD28E7.assets.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/appconfigenvironmentDefaultTestDeployAssert75BD28E7.assets.json index 49f0e48e091a4..87b95745076b2 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/appconfigenvironmentDefaultTestDeployAssert75BD28E7.assets.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/appconfigenvironmentDefaultTestDeployAssert75BD28E7.assets.json @@ -1,5 +1,5 @@ { - "version": "34.0.0", + "version": "35.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.assets.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.assets.json index 89f92e7bd5dc4..fa54d57aa0d8a 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.assets.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.assets.json @@ -1,7 +1,7 @@ { - "version": "34.0.0", + "version": "35.0.0", "files": { - "ea755ac1ccc8e2c8816cf7e0a2b3789e472a166174037cb50eb45ec4ed621ba4": { + "6452c0ef7699cda5c609159e92012f180afda9cac21a0cba23acff97b8734de7": { "source": { "path": "aws-appconfig-environment.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "ea755ac1ccc8e2c8816cf7e0a2b3789e472a166174037cb50eb45ec4ed621ba4.json", + "objectKey": "6452c0ef7699cda5c609159e92012f180afda9cac21a0cba23acff97b8734de7.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.template.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.template.json index c3951447345b9..bb9c67d5ebfcb 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.template.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.template.json @@ -35,6 +35,27 @@ } } }, + "MyCompositeAlarm0F045229": { + "Type": "AWS::CloudWatch::CompositeAlarm", + "Properties": { + "AlarmName": "awsappconfigenvironmentMyCompositeAlarm730A7A48", + "AlarmRule": { + "Fn::Join": [ + "", + [ + "ALARM(\"", + { + "Fn::GetAtt": [ + "MyAlarm696658B6", + "Arn" + ] + }, + "\")" + ] + ] + } + } + }, "MyEnvironmentRole01C8C013F": { "Type": "AWS::IAM::Role", "Properties": { @@ -72,6 +93,57 @@ ] } }, + "MyEnvironmentRoleCompositeAlarm8C2A0542": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "appconfig.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": "cloudwatch:DescribeAlarms", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":cloudwatch:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":alarm:*" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "AllowAppConfigMonitorAlarmPolicy" + } + ] + } + }, "MyEnvironment465E4DEA": { "Type": "AWS::AppConfig::Environment", "Properties": { @@ -107,6 +179,20 @@ "Arn" ] } + }, + { + "AlarmArn": { + "Fn::GetAtt": [ + "MyCompositeAlarm0F045229", + "Arn" + ] + }, + "AlarmRoleArn": { + "Fn::GetAtt": [ + "MyEnvironmentRoleCompositeAlarm8C2A0542", + "Arn" + ] + } } ], "Name": "awsappconfigenvironment-MyEnvironment-C8813182" diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/cdk.out b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/cdk.out index 2313ab5436501..c5cb2e5de6344 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"34.0.0"} \ No newline at end of file +{"version":"35.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/integ.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/integ.json index a9ffb18c9ba71..8c6291ddb72a5 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "34.0.0", + "version": "35.0.0", "testCases": { "appconfig-environment/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/manifest.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/manifest.json index 4c038cd5bcd81..cb504329bc8a0 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "34.0.0", + "version": "35.0.0", "artifacts": { "aws-appconfig-environment.assets": { "type": "cdk:asset-manifest", @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/ea755ac1ccc8e2c8816cf7e0a2b3789e472a166174037cb50eb45ec4ed621ba4.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/6452c0ef7699cda5c609159e92012f180afda9cac21a0cba23acff97b8734de7.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -52,12 +52,24 @@ "data": "MyRoleF48FFE04" } ], + "/aws-appconfig-environment/MyCompositeAlarm/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyCompositeAlarm0F045229" + } + ], "/aws-appconfig-environment/MyEnvironment/Role0/Resource": [ { "type": "aws:cdk:logicalId", "data": "MyEnvironmentRole01C8C013F" } ], + "/aws-appconfig-environment/MyEnvironment/RoleCompositeAlarm/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyEnvironmentRoleCompositeAlarm8C2A0542" + } + ], "/aws-appconfig-environment/MyEnvironment/Resource": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/tree.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/tree.json index 9b1d723134bbf..744719477b065 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/tree.json @@ -105,6 +105,45 @@ "version": "0.0.0" } }, + "MyCompositeAlarm": { + "id": "MyCompositeAlarm", + "path": "aws-appconfig-environment/MyCompositeAlarm", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-appconfig-environment/MyCompositeAlarm/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudWatch::CompositeAlarm", + "aws:cdk:cloudformation:props": { + "alarmName": "awsappconfigenvironmentMyCompositeAlarm730A7A48", + "alarmRule": { + "Fn::Join": [ + "", + [ + "ALARM(\"", + { + "Fn::GetAtt": [ + "MyAlarm696658B6", + "Arn" + ] + }, + "\")" + ] + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.CfnCompositeAlarm", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudwatch.CompositeAlarm", + "version": "0.0.0" + } + }, "MyEnvironment": { "id": "MyEnvironment", "path": "aws-appconfig-environment/MyEnvironment", @@ -172,6 +211,83 @@ "version": "0.0.0" } }, + "RoleCompositeAlarm": { + "id": "RoleCompositeAlarm", + "path": "aws-appconfig-environment/MyEnvironment/RoleCompositeAlarm", + "children": { + "ImportRoleCompositeAlarm": { + "id": "ImportRoleCompositeAlarm", + "path": "aws-appconfig-environment/MyEnvironment/RoleCompositeAlarm/ImportRoleCompositeAlarm", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-appconfig-environment/MyEnvironment/RoleCompositeAlarm/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "appconfig.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "policies": [ + { + "policyName": "AllowAppConfigMonitorAlarmPolicy", + "policyDocument": { + "Statement": [ + { + "Action": "cloudwatch:DescribeAlarms", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":cloudwatch:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":alarm:*" + ] + ] + } + } + ], + "Version": "2012-10-17" + } + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "aws-appconfig-environment/MyEnvironment/Resource", @@ -210,6 +326,20 @@ "Arn" ] } + }, + { + "alarmArn": { + "Fn::GetAtt": [ + "MyCompositeAlarm0F045229", + "Arn" + ] + }, + "alarmRoleArn": { + "Fn::GetAtt": [ + "MyEnvironmentRoleCompositeAlarm8C2A0542", + "Arn" + ] + } } ], "name": "awsappconfigenvironment-MyEnvironment-C8813182" @@ -261,7 +391,7 @@ "path": "appconfig-environment/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.2.70" + "version": "10.3.0" } }, "DeployAssert": { @@ -307,7 +437,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.2.70" + "version": "10.3.0" } } }, diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.ts b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.ts index 3716997e2253e..bce1591e70ba8 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.ts +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.ts @@ -1,7 +1,7 @@ import { IntegTest } from '@aws-cdk/integ-tests-alpha'; import { App, Stack } from 'aws-cdk-lib'; import { Application, Environment, Monitor } from '../lib'; -import { Alarm, Metric } from 'aws-cdk-lib/aws-cloudwatch'; +import { Alarm, CompositeAlarm, Metric } from 'aws-cdk-lib/aws-cloudwatch'; import { Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam'; const app = new App(); @@ -23,6 +23,9 @@ const alarm = new Alarm(stack, 'MyAlarm', { const role = new Role(stack, 'MyRole', { assumedBy: new ServicePrincipal('appconfig.amazonaws.com'), }); +const compositeAlarm = new CompositeAlarm(stack, 'MyCompositeAlarm', { + alarmRule: alarm, +}); // create environment with all props defined new Environment(stack, 'MyEnvironment', { @@ -34,6 +37,7 @@ new Environment(stack, 'MyEnvironment', { alarmArn: alarm.alarmArn, alarmRoleArn: role.roleArn, }), + Monitor.fromCloudWatchAlarm(compositeAlarm), ], });