Skip to content

Commit 729ea95

Browse files
authored
Merge branch 'main' into issue-18900
2 parents 15f3437 + 5eecb7b commit 729ea95

File tree

91 files changed

+6272
-200
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+6272
-200
lines changed

Diff for: .github/workflows/issue-label-assign.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -282,5 +282,7 @@ env:
282282
{"area":"@aws-cdk/yaml-cfn","keywords":["aws-yaml-cfn","yaml-cfn"],"labels":["@aws-cdk/aws-yaml-cfn"],"assignees":["kaizencc"]},
283283
{"area":"@aws-cdk/aws-lightsail","keywords":["lightsail","aws-lightsail"],"labels":["@aws-cdk/aws-lightsail"],"assignees":["corymhall"]},
284284
{"area":"@aws-cdk/aws-aps","keywords":["aps","aws-aps","prometheus"],"labels":["@aws-cdk/aws-aps"],"assignees":["corymhall"]},
285-
{"area":"@aws-cdk/triggers","keywords":["trigger","triggers"],"labels":["@aws-cdk/triggers"],"assignees":["otaviomacedo"]}
285+
{"area":"@aws-cdk/triggers","keywords":["trigger","triggers"],"labels":["@aws-cdk/triggers"],"assignees":["otaviomacedo"]},
286+
{"area":"@aws-cdk/integ-tests","keywords":["integ-tests", "integ"],"labels":["@aws-cdk/integ-tests"],"assignees":["corymhall"]},
287+
{"area":"@aws-cdk/integ-runner","keywords":["integ-runner"],"labels":["@aws-cdk/integ-runner"],"assignees":["corymhall"]}
286288
]

Diff for: .mergify.yml

+1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ pull_request_rules:
9595
- base=main
9696
- -merged
9797
- -closed
98+
- changes-requested-reviews-by!=aws-cdk-automation
9899
- name: if fails conventional commits
99100
actions:
100101
comment:

Diff for: packages/@aws-cdk/assertions/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ const templateJson = '{ "Resources": ... }'; /* The CloudFormation template as J
3434
const template = Template.fromString(templateJson);
3535
```
3636

37+
**Cyclical Resources Note**
38+
39+
If allowing cyclical references is desired, for example in the case of unprocessed Transform templates, supply TemplateParsingOptions and
40+
set skipCyclicalDependenciesCheck to true. In all other cases, will fail on detecting cyclical dependencies.
41+
3742
## Full Template Match
3843

3944
The simplest assertion would be to assert that the template matches a given

Diff for: packages/@aws-cdk/assertions/lib/template.ts

+31-9
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,42 @@ export class Template {
2121
/**
2222
* Base your assertions on the CloudFormation template synthesized by a CDK `Stack`.
2323
* @param stack the CDK Stack to run assertions on
24+
* @param templateParsingOptions Optional param to configure template parsing behavior, such as disregarding circular
25+
* dependencies.
2426
*/
25-
public static fromStack(stack: Stack): Template {
26-
return new Template(toTemplate(stack));
27+
public static fromStack(stack: Stack, templateParsingOptions?: TemplateParsingOptions): Template {
28+
return new Template(toTemplate(stack), templateParsingOptions);
2729
}
2830

2931
/**
3032
* Base your assertions from an existing CloudFormation template formatted as an in-memory
3133
* JSON object.
3234
* @param template the CloudFormation template formatted as a nested set of records
35+
* @param templateParsingOptions Optional param to configure template parsing behavior, such as disregarding circular
36+
* dependencies.
3337
*/
34-
public static fromJSON(template: { [key: string] : any }): Template {
35-
return new Template(template);
38+
public static fromJSON(template: { [key: string] : any }, templateParsingOptions?: TemplateParsingOptions): Template {
39+
return new Template(template, templateParsingOptions);
3640
}
3741

3842
/**
3943
* Base your assertions from an existing CloudFormation template formatted as a
4044
* JSON string.
4145
* @param template the CloudFormation template in
46+
* @param templateParsingOptions Optional param to configure template parsing behavior, such as disregarding circular
47+
* dependencies.
4248
*/
43-
public static fromString(template: string): Template {
44-
return new Template(JSON.parse(template));
49+
public static fromString(template: string, templateParsingOptions?: TemplateParsingOptions): Template {
50+
return new Template(JSON.parse(template), templateParsingOptions);
4551
}
4652

4753
private readonly template: TemplateType;
4854

49-
private constructor(template: { [key: string]: any }) {
55+
private constructor(template: { [key: string]: any }, templateParsingOptions: TemplateParsingOptions = {}) {
5056
this.template = template as TemplateType;
51-
checkTemplateForCyclicDependencies(this.template);
57+
if (!templateParsingOptions?.skipCyclicalDependenciesCheck ?? true) {
58+
checkTemplateForCyclicDependencies(this.template);
59+
}
5260
}
5361

5462
/**
@@ -243,6 +251,20 @@ export class Template {
243251
}
244252
}
245253

254+
/**
255+
* Options to configure template parsing behavior, such as disregarding circular
256+
* dependencies.
257+
*/
258+
export interface TemplateParsingOptions {
259+
/**
260+
* If set to true, will skip checking for cyclical / circular dependencies. Should be set to false other than for
261+
* templates that are valid despite containing cycles, such as unprocessed transform stacks.
262+
*
263+
* @default false
264+
*/
265+
readonly skipCyclicalDependenciesCheck?: boolean;
266+
}
267+
246268
function toTemplate(stack: Stack): any {
247269
const root = stack.node.root;
248270
if (!Stage.isStage(root)) {
@@ -255,4 +277,4 @@ function toTemplate(stack: Stack): any {
255277
return JSON.parse(fs.readFileSync(path.join(assembly.directory, stack.templateFile)).toString('utf-8'));
256278
}
257279
return assembly.getStackArtifact(stack.artifactId).template;
258-
}
280+
}

Diff for: packages/@aws-cdk/assertions/test/template.test.ts

+21
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,27 @@ describe('Template', () => {
11941194
});
11951195
}).toThrow(/dependency cycle/);
11961196
});
1197+
1198+
test('does not throw when given a template with cyclic dependencies if check is skipped', () => {
1199+
expect(() => {
1200+
Template.fromJSON({
1201+
Resources: {
1202+
Res1: {
1203+
Type: 'Foo',
1204+
Properties: {
1205+
Thing: { Ref: 'Res2' },
1206+
},
1207+
},
1208+
Res2: {
1209+
Type: 'Foo',
1210+
DependsOn: ['Res1'],
1211+
},
1212+
},
1213+
}, {
1214+
skipCyclicalDependenciesCheck: true,
1215+
});
1216+
}).not.toThrow(/dependency cycle/);
1217+
});
11971218
});
11981219

11991220
function expectToThrow(fn: () => void, msgs: (RegExp | string)[], done: jest.DoneCallback): void {

Diff for: packages/@aws-cdk/aws-cloudwatch/README.md

+24
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,30 @@ new cloudwatch.CompositeAlarm(this, 'MyAwesomeCompositeAlarm', {
288288
});
289289
```
290290

291+
#### Actions Suppressor
292+
293+
If you want to disable actions of a Composite Alarm based on a certain condition, you can use [Actions Suppression](https://www.amazonaws.cn/en/new/2022/amazon-cloudwatch-supports-composite-alarm-actions-suppression/).
294+
295+
```ts
296+
declare const childAlarm1: cloudwatch.Alarm;
297+
declare const childAlarm2: cloudwatch.Alarm;
298+
declare const onAlarmAction: cloudwatch.IAlarmAction;
299+
declare const onOkAction: cloudwatch.IAlarmAction;
300+
declare const actionsSuppressor: cloudwatch.Alarm;
301+
302+
const alarmRule = cloudwatch.AlarmRule.anyOf(alarm1, alarm2);
303+
304+
const myCompositeAlarm = new cloudwatch.CompositeAlarm(this, 'MyAwesomeCompositeAlarm', {
305+
alarmRule,
306+
actionsSuppressor,
307+
});
308+
myCompositeAlarm.addAlarmActions(onAlarmAction);
309+
myComposireAlarm.addOkAction(onOkAction);
310+
```
311+
312+
In the provided example, if `actionsSuppressor` is in `ALARM` state, `onAlarmAction` won't be triggered even if `myCompositeAlarm` goes into `ALARM` state.
313+
Similar, if `actionsSuppressor` is in `ALARM` state and `myCompositeAlarm` goes from `ALARM` into `OK` state, `onOkAction` won't be triggered.
314+
291315
### A note on units
292316

293317
In CloudWatch, Metrics datums are emitted with units, such as `seconds` or

Diff for: packages/@aws-cdk/aws-cloudwatch/lib/composite-alarm.ts

+39-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ArnFormat, Lazy, Names, Stack } from '@aws-cdk/core';
1+
import { ArnFormat, Lazy, Names, Stack, Duration } from '@aws-cdk/core';
22
import { Construct } from 'constructs';
33
import { AlarmBase, IAlarm, IAlarmRule } from './alarm-base';
44
import { CfnCompositeAlarm } from './cloudwatch.generated';
@@ -18,14 +18,14 @@ export interface CompositeAlarmProps {
1818
/**
1919
* Description for the alarm
2020
*
21-
* @default No description
21+
* @default - No description.
2222
*/
2323
readonly alarmDescription?: string;
2424

2525
/**
2626
* Name of the alarm
2727
*
28-
* @default Automatically generated name
28+
* @default - Automatically generated name.
2929
*/
3030
readonly compositeAlarmName?: string;
3131

@@ -34,6 +34,28 @@ export interface CompositeAlarmProps {
3434
*/
3535
readonly alarmRule: IAlarmRule;
3636

37+
/**
38+
* Actions will be suppressed if the suppressor alarm is in the ALARM state.
39+
*
40+
* @default - alarm will not be suppressed.
41+
*/
42+
readonly actionsSuppressor?: IAlarm;
43+
44+
/**
45+
* The maximum duration that the composite alarm waits after suppressor alarm goes out of the ALARM state.
46+
* After this time, the composite alarm performs its actions.
47+
*
48+
* @default - 1 minute extension period will be set.
49+
*/
50+
readonly actionsSuppressorExtensionPeriod?: Duration;
51+
52+
/**
53+
* The maximum duration that the composite alarm waits for the suppressor alarm to go into the ALARM state.
54+
* After this time, the composite alarm performs its actions.
55+
*
56+
* @default - 1 minute wait period will be set.
57+
*/
58+
readonly actionsSuppressorWaitPeriod?: Duration;
3759
}
3860

3961
/**
@@ -98,6 +120,17 @@ export class CompositeAlarm extends AlarmBase {
98120
throw new Error('Alarm Rule expression cannot be greater than 10240 characters, please reduce the conditions in the Alarm Rule');
99121
}
100122

123+
let extensionPeriod = props.actionsSuppressorExtensionPeriod;
124+
let waitPeriod = props.actionsSuppressorWaitPeriod;
125+
if (props.actionsSuppressor === undefined) {
126+
if (extensionPeriod !== undefined || waitPeriod !== undefined) {
127+
throw new Error('ActionsSuppressor Extension/Wait Periods require an ActionsSuppressor to be set.');
128+
}
129+
} else {
130+
extensionPeriod = extensionPeriod ?? Duration.minutes(1);
131+
waitPeriod = waitPeriod ?? Duration.minutes(1);
132+
}
133+
101134
this.alarmRule = props.alarmRule.renderAlarmRule();
102135

103136
const alarm = new CfnCompositeAlarm(this, 'Resource', {
@@ -108,6 +141,9 @@ export class CompositeAlarm extends AlarmBase {
108141
alarmActions: Lazy.list({ produce: () => this.alarmActionArns }),
109142
insufficientDataActions: Lazy.list({ produce: (() => this.insufficientDataActionArns) }),
110143
okActions: Lazy.list({ produce: () => this.okActionArns }),
144+
actionsSuppressor: props.actionsSuppressor?.alarmArn,
145+
actionsSuppressorExtensionPeriod: extensionPeriod?.toSeconds(),
146+
actionsSuppressorWaitPeriod: waitPeriod?.toSeconds(),
111147
});
112148

113149
this.alarmName = this.getResourceNameAttribute(alarm.ref);

Diff for: packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/CompositeAlarmIntegrationTest.assets.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
2-
"version": "20.0.0",
2+
"version": "21.0.0",
33
"files": {
4-
"1f1d7f1c425488b9245a0ff851dae7650c25e5558781cc88a972edb6a36be237": {
4+
"ad8a5012407e26a8fc0b1b169b0ab2373b8466d955070ee91a90193c5c70d1a4": {
55
"source": {
66
"path": "CompositeAlarmIntegrationTest.template.json",
77
"packaging": "file"
88
},
99
"destinations": {
1010
"current_account-current_region": {
1111
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12-
"objectKey": "1f1d7f1c425488b9245a0ff851dae7650c25e5558781cc88a972edb6a36be237.json",
12+
"objectKey": "ad8a5012407e26a8fc0b1b169b0ab2373b8466d955070ee91a90193c5c70d1a4.json",
1313
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
1414
}
1515
}

Diff for: packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/CompositeAlarmIntegrationTest.template.json

+9-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,15 @@
107107
"\")))) OR FALSE)"
108108
]
109109
]
110-
}
110+
},
111+
"ActionsSuppressor": {
112+
"Fn::GetAtt": [
113+
"Alarm548383B2F",
114+
"Arn"
115+
]
116+
},
117+
"ActionsSuppressorExtensionPeriod": 60,
118+
"ActionsSuppressorWaitPeriod": 60
111119
}
112120
}
113121
},
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"version":"20.0.0"}
1+
{"version":"21.0.0"}

Diff for: packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/integ.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "20.0.0",
2+
"version": "21.0.0",
33
"testCases": {
44
"integ.composite-alarm": {
55
"stacks": [

Diff for: packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/manifest.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "20.0.0",
2+
"version": "21.0.0",
33
"artifacts": {
44
"Tree": {
55
"type": "cdk:tree",
@@ -23,7 +23,7 @@
2323
"validateOnSynth": false,
2424
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}",
2525
"cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}",
26-
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/1f1d7f1c425488b9245a0ff851dae7650c25e5558781cc88a972edb6a36be237.json",
26+
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/ad8a5012407e26a8fc0b1b169b0ab2373b8466d955070ee91a90193c5c70d1a4.json",
2727
"requiresBootstrapStackVersion": 6,
2828
"bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version",
2929
"additionalDependencies": [

Diff for: packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.integ.snapshot/tree.json

+14-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"path": "Tree",
1010
"constructInfo": {
1111
"fqn": "constructs.Construct",
12-
"version": "10.1.85"
12+
"version": "10.1.108"
1313
}
1414
},
1515
"CompositeAlarmIntegrationTest": {
@@ -220,7 +220,15 @@
220220
"\")))) OR FALSE)"
221221
]
222222
]
223-
}
223+
},
224+
"actionsSuppressor": {
225+
"Fn::GetAtt": [
226+
"Alarm548383B2F",
227+
"Arn"
228+
]
229+
},
230+
"actionsSuppressorExtensionPeriod": 60,
231+
"actionsSuppressorWaitPeriod": 60
224232
}
225233
},
226234
"constructInfo": {
@@ -236,14 +244,14 @@
236244
}
237245
},
238246
"constructInfo": {
239-
"fqn": "constructs.Construct",
240-
"version": "10.1.85"
247+
"fqn": "@aws-cdk/core.Stack",
248+
"version": "0.0.0"
241249
}
242250
}
243251
},
244252
"constructInfo": {
245-
"fqn": "constructs.Construct",
246-
"version": "10.1.85"
253+
"fqn": "@aws-cdk/core.App",
254+
"version": "0.0.0"
247255
}
248256
}
249257
}

0 commit comments

Comments
 (0)