Skip to content

Commit 680a755

Browse files
authored
feat(events): new filtering capabilities (#23075)
Add suffix and equals ignore case matching. See https://aws.amazon.com/about-aws/whats-new/2022/11/amazon-eventbridge-enhanced-filtering-capabilities/ See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns-content-based-filtering.html ---- ### All Submissions: * [x] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) ### Adding new Unconventional Dependencies: * [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies) ### New Features * [x] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)? * [x] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)? *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 52edf29 commit 680a755

File tree

11 files changed

+129
-39
lines changed

11 files changed

+129
-39
lines changed

packages/@aws-cdk/aws-events/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,11 @@ const rule = new events.Rule(this, 'rule', {
114114

115115
// 'OR' condition
116116
'source-storage-class': events.Match.anyOf(
117-
events.Match.prefix("GLACIER"),
117+
events.Match.prefix("GLACIER"),
118118
events.Match.exactString('DEEP_ARCHIVE'),
119119
),
120120
},
121+
'detail-type': events.Match.equalsIgnoreCase('object created'),
121122

122123
// If you prefer, you can use a low level array of strings, as directly consumed by EventBridge
123124
source: ['aws.s3'],

packages/@aws-cdk/aws-events/lib/event-pattern.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,35 @@ export class Match implements IResolvable {
4040
/**
4141
* Matches a string, exactly, in the JSON of the event
4242
*/
43-
public static exactString(value: string): string [] {
43+
public static exactString(value: string): string[] {
4444
return this.fromObjects([value]);
4545
}
4646

47+
/**
48+
* Matches a string, regardless of case, in the JSON of the event
49+
*/
50+
public static equalsIgnoreCase(value: string): string[] {
51+
return this.fromObjects([{ 'equals-ignore-case': value }]);
52+
}
53+
4754
/**
4855
* Matches strings with the given prefix in the JSON of the event
4956
*/
50-
static prefix(value: string): string[] {
57+
public static prefix(value: string): string[] {
5158
return this.fromObjects([{ prefix: value }]);
5259
}
5360

61+
/**
62+
* Matches strings with the given suffix in the JSON of the event
63+
*/
64+
public static suffix(value: string): string[] {
65+
return this.fromObjects([{ suffix: value }]);
66+
}
67+
5468
/**
5569
* Matches IPv4 and IPv6 network addresses using the Classless Inter-Domain Routing (CIDR) format
5670
*/
57-
static cidr(range: string): string[] {
71+
public static cidr(range: string): string[] {
5872
const ipv4Regex = /^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$/igm;
5973
const ipv6Regex = /^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$/igm;
6074

@@ -69,15 +83,15 @@ export class Match implements IResolvable {
6983
* Matches IPv4 and IPv6 network addresses using the Classless Inter-Domain Routing (CIDR) format.
7084
* Alias of `cidr()`.
7185
*/
72-
static ipAddressRange(range: string): string[] {
86+
public static ipAddressRange(range: string): string[] {
7387
return Match.cidr(range);
7488
}
7589

7690
/**
7791
* Matches anything except what's provided in the rule. The list of provided values must contain
7892
* only strings or only numbers.
7993
*/
80-
static anythingBut(...values: any[]): string[] {
94+
public static anythingBut(...values: any[]): string[] {
8195
if (values.length === 0) {
8296
throw new Error('anythingBut matchers must be non-empty lists');
8397
}
@@ -95,7 +109,7 @@ export class Match implements IResolvable {
95109
/**
96110
* Matches any string that doesn't start with the given prefix.
97111
*/
98-
static anythingButPrefix(prefix: string): string[] {
112+
public static anythingButPrefix(prefix: string): string[] {
99113
return this.fromObjects([{ 'anything-but': { prefix: prefix } }]);
100114
}
101115

@@ -142,7 +156,7 @@ export class Match implements IResolvable {
142156
* @param lower Lower bound (inclusive)
143157
* @param upper Upper bound (inclusive)
144158
*/
145-
static interval(lower: number, upper: number): string[] {
159+
public static interval(lower: number, upper: number): string[] {
146160
if (lower > upper) {
147161
throw new Error(`Invalid interval: [${lower}, ${upper}]`);
148162
}

packages/@aws-cdk/aws-events/test/integ.rule.js.snapshot/IntegTestBatchDefaultEnvVarsStackDefaultTestDeployAssertC15EFFF2.assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "20.0.0",
2+
"version": "21.0.0",
33
"files": {
44
"21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": {
55
"source": {

packages/@aws-cdk/aws-events/test/integ.rule.js.snapshot/RuleStack.assets.json

Lines changed: 3 additions & 3 deletions
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-
"f8f3154528da0601b814868afeeb0474f8644916293f783617ff6d56a6d92035": {
4+
"f9728b2d2c64ff638563c8cc4a3e8eb9ddf3074e2ae01d68fde11aeda0968fb1": {
55
"source": {
66
"path": "RuleStack.template.json",
77
"packaging": "file"
88
},
99
"destinations": {
1010
"current_account-current_region": {
1111
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12-
"objectKey": "f8f3154528da0601b814868afeeb0474f8644916293f783617ff6d56a6d92035.json",
12+
"objectKey": "f9728b2d2c64ff638563c8cc4a3e8eb9ddf3074e2ae01d68fde11aeda0968fb1.json",
1313
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
1414
}
1515
}

packages/@aws-cdk/aws-events/test/integ.rule.js.snapshot/RuleStack.template.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,16 @@
108108
"prefix": "sensitive-"
109109
}
110110
}
111+
],
112+
"suffix": [
113+
{
114+
"suffix": ".com"
115+
}
116+
],
117+
"equalsIgnoreCase": [
118+
{
119+
"equals-ignore-case": "ignore case"
120+
}
111121
]
112122
},
113123
"detail-type": [
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"version":"20.0.0"}
1+
{"version":"21.0.0"}
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
{
2-
"version": "20.0.0",
2+
"version": "21.0.0",
33
"testCases": {
44
"IntegTest-BatchDefaultEnvVarsStack/DefaultTest": {
55
"stacks": [
66
"RuleStack"
77
],
8-
"assertionStack": "IntegTest-BatchDefaultEnvVarsStack/DefaultTest/DeployAssert"
8+
"assertionStack": "IntegTest-BatchDefaultEnvVarsStack/DefaultTest/DeployAssert",
9+
"assertionStackName": "IntegTestBatchDefaultEnvVarsStackDefaultTestDeployAssertC15EFFF2"
910
}
1011
}
1112
}

packages/@aws-cdk/aws-events/test/integ.rule.js.snapshot/manifest.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
{
2-
"version": "20.0.0",
2+
"version": "21.0.0",
33
"artifacts": {
4-
"Tree": {
5-
"type": "cdk:tree",
6-
"properties": {
7-
"file": "tree.json"
8-
}
9-
},
104
"RuleStack.assets": {
115
"type": "cdk:asset-manifest",
126
"properties": {
@@ -23,7 +17,7 @@
2317
"validateOnSynth": false,
2418
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}",
2519
"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}/f8f3154528da0601b814868afeeb0474f8644916293f783617ff6d56a6d92035.json",
20+
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/f9728b2d2c64ff638563c8cc4a3e8eb9ddf3074e2ae01d68fde11aeda0968fb1.json",
2721
"requiresBootstrapStackVersion": 6,
2822
"bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version",
2923
"additionalDependencies": [
@@ -106,6 +100,12 @@
106100
]
107101
},
108102
"displayName": "IntegTest-BatchDefaultEnvVarsStack/DefaultTest/DeployAssert"
103+
},
104+
"Tree": {
105+
"type": "cdk:tree",
106+
"properties": {
107+
"file": "tree.json"
108+
}
109109
}
110110
}
111111
}

packages/@aws-cdk/aws-events/test/integ.rule.js.snapshot/tree.json

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,6 @@
44
"id": "App",
55
"path": "",
66
"children": {
7-
"Tree": {
8-
"id": "Tree",
9-
"path": "Tree",
10-
"constructInfo": {
11-
"fqn": "constructs.Construct",
12-
"version": "10.1.85"
13-
}
14-
},
157
"RuleStack": {
168
"id": "RuleStack",
179
"path": "RuleStack",
@@ -131,6 +123,16 @@
131123
"prefix": "sensitive-"
132124
}
133125
}
126+
],
127+
"suffix": [
128+
{
129+
"suffix": ".com"
130+
}
131+
],
132+
"equalsIgnoreCase": [
133+
{
134+
"equals-ignore-case": "ignore case"
135+
}
134136
]
135137
},
136138
"detail-type": [
@@ -172,11 +174,27 @@
172174
"fqn": "@aws-cdk/aws-events.Rule",
173175
"version": "0.0.0"
174176
}
177+
},
178+
"BootstrapVersion": {
179+
"id": "BootstrapVersion",
180+
"path": "RuleStack/BootstrapVersion",
181+
"constructInfo": {
182+
"fqn": "@aws-cdk/core.CfnParameter",
183+
"version": "0.0.0"
184+
}
185+
},
186+
"CheckBootstrapVersion": {
187+
"id": "CheckBootstrapVersion",
188+
"path": "RuleStack/CheckBootstrapVersion",
189+
"constructInfo": {
190+
"fqn": "@aws-cdk/core.CfnRule",
191+
"version": "0.0.0"
192+
}
175193
}
176194
},
177195
"constructInfo": {
178-
"fqn": "constructs.Construct",
179-
"version": "10.1.85"
196+
"fqn": "@aws-cdk/core.Stack",
197+
"version": "0.0.0"
180198
}
181199
},
182200
"IntegTest-BatchDefaultEnvVarsStack": {
@@ -192,15 +210,33 @@
192210
"path": "IntegTest-BatchDefaultEnvVarsStack/DefaultTest/Default",
193211
"constructInfo": {
194212
"fqn": "constructs.Construct",
195-
"version": "10.1.85"
213+
"version": "10.1.154"
196214
}
197215
},
198216
"DeployAssert": {
199217
"id": "DeployAssert",
200218
"path": "IntegTest-BatchDefaultEnvVarsStack/DefaultTest/DeployAssert",
219+
"children": {
220+
"BootstrapVersion": {
221+
"id": "BootstrapVersion",
222+
"path": "IntegTest-BatchDefaultEnvVarsStack/DefaultTest/DeployAssert/BootstrapVersion",
223+
"constructInfo": {
224+
"fqn": "@aws-cdk/core.CfnParameter",
225+
"version": "0.0.0"
226+
}
227+
},
228+
"CheckBootstrapVersion": {
229+
"id": "CheckBootstrapVersion",
230+
"path": "IntegTest-BatchDefaultEnvVarsStack/DefaultTest/DeployAssert/CheckBootstrapVersion",
231+
"constructInfo": {
232+
"fqn": "@aws-cdk/core.CfnRule",
233+
"version": "0.0.0"
234+
}
235+
}
236+
},
201237
"constructInfo": {
202-
"fqn": "constructs.Construct",
203-
"version": "10.1.85"
238+
"fqn": "@aws-cdk/core.Stack",
239+
"version": "0.0.0"
204240
}
205241
}
206242
},
@@ -214,11 +250,19 @@
214250
"fqn": "@aws-cdk/integ-tests.IntegTest",
215251
"version": "0.0.0"
216252
}
253+
},
254+
"Tree": {
255+
"id": "Tree",
256+
"path": "Tree",
257+
"constructInfo": {
258+
"fqn": "constructs.Construct",
259+
"version": "10.1.154"
260+
}
217261
}
218262
},
219263
"constructInfo": {
220-
"fqn": "constructs.Construct",
221-
"version": "10.1.85"
264+
"fqn": "@aws-cdk/core.App",
265+
"version": "0.0.0"
222266
}
223267
}
224268
}

packages/@aws-cdk/aws-events/test/integ.rule.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ new Rule(stack, 'MyRule', {
2929
state: Match.anythingBut('initializing'),
3030
limit: Match.anythingBut(100, 200, 300),
3131
notPrefixedBy: Match.anythingButPrefix('sensitive-'),
32+
suffix: Match.suffix('.com'),
33+
equalsIgnoreCase: Match.equalsIgnoreCase('ignore case'),
3234
},
3335
detailType: ['detailType1'],
3436
id: ['id1', 'id2'],

packages/@aws-cdk/aws-events/test/matchers.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,22 @@ describe(Match, () => {
6464

6565
expect(() => stack.resolve(Match.anyOf())).toThrow(/A list of matchers must contain at least one element/);
6666
});
67-
});
67+
68+
test('prefix', () => {
69+
expect(stack.resolve(Match.prefix('foo'))).toEqual([
70+
{ prefix: 'foo' },
71+
]);
72+
});
73+
74+
test('suffix', () => {
75+
expect(stack.resolve(Match.suffix('foo'))).toEqual([
76+
{ suffix: 'foo' },
77+
]);
78+
});
79+
80+
test('equalsIgnoreCase', () => {
81+
expect(stack.resolve(Match.equalsIgnoreCase('foo'))).toEqual([
82+
{ 'equals-ignore-case': 'foo' },
83+
]);
84+
});
85+
});

0 commit comments

Comments
 (0)