Skip to content

Commit b113d3f

Browse files
committed
feat: add EventBridge importer
1 parent 1776319 commit b113d3f

File tree

16 files changed

+1838
-5
lines changed

16 files changed

+1838
-5
lines changed

packages/@aws-cdk/aws-service-spec/build/full-database.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import * as path from 'node:path';
2-
import { SpecDatabase } from '@aws-cdk/service-spec-types';
32
import { DatabaseBuilder, DatabaseBuilderOptions, ReportAudience } from '@aws-cdk/service-spec-importers';
3+
import { patchOobRelationships } from '@aws-cdk/service-spec-importers/src/patches/oob-relationship-patches';
4+
import { SpecDatabase } from '@aws-cdk/service-spec-types';
45
import { Augmentations } from './augmentations';
5-
import { Scrutinies } from './scrutinies';
6-
import { patchSamTemplateSpec } from './patches/sam-patches';
76
import { patchCloudFormationRegistry } from './patches/registry-patches';
8-
import { patchOobRelationships } from '@aws-cdk/service-spec-importers/src/patches/oob-relationship-patches';
7+
import { patchSamTemplateSpec } from './patches/sam-patches';
8+
import { Scrutinies } from './scrutinies';
99

1010
const SOURCES = path.join(__dirname, '../../../../sources');
1111

@@ -29,7 +29,8 @@ export class FullDatabase extends DatabaseBuilder {
2929
)
3030
.importLogSources(path.join(SOURCES, 'LogSources/log-source-resource.json'))
3131
.importScrutinies()
32-
.importAugmentations();
32+
.importAugmentations()
33+
.importEventBridgeSchema(path.join(SOURCES, 'EventBridgeSchema'));
3334
}
3435

3536
/**
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
{
2+
"$ref": "#/definitions/EventBridgeSchema",
3+
"$schema": "http://json-schema.org/draft-07/schema#",
4+
"definitions": {
5+
"EventBridgeSchema": {
6+
"additionalProperties": false,
7+
"description": "Root class of an EventBridge Schema",
8+
"properties": {
9+
"SchemaName": {
10+
"type": "string"
11+
},
12+
"Content": {
13+
"$ref": "#/definitions/EventBridgeContent"
14+
},
15+
"Description": {
16+
"type": "string"
17+
}
18+
},
19+
"required": [
20+
"SchemaName",
21+
"Content",
22+
"Description"
23+
],
24+
"type": "object"
25+
},
26+
"EventBridgeContent": {
27+
"additionalProperties": false,
28+
"properties": {
29+
"components": {
30+
"$ref": "#/definitions/EventBridgeComponents"
31+
}
32+
},
33+
"required": [
34+
"components"
35+
],
36+
"type": "object"
37+
},
38+
"EventBridgeComponents": {
39+
"additionalProperties": false,
40+
"properties": {
41+
"schemas": {
42+
"$ref": "#/definitions/EventBridgeSchemas"
43+
}
44+
},
45+
"required": [
46+
"schemas"
47+
],
48+
"type": "object"
49+
},
50+
"EventBridgeSchemas": {
51+
"additionalProperties": false,
52+
"properties": {
53+
"AWSEvent": {
54+
"$ref": "#/definitions/AWSEvent"
55+
}
56+
},
57+
"required": [
58+
"AWSEvent"
59+
],
60+
"type": "object"
61+
},
62+
"AWSEvent": {
63+
"additionalProperties": false,
64+
"properties": {
65+
"x-amazon-events-detail-type": {
66+
"type": "string"
67+
},
68+
"x-amazon-events-source": {
69+
"type": "string"
70+
},
71+
"properties": {
72+
"$ref": "#/definitions/AWSEventProperties"
73+
}
74+
},
75+
"required": [
76+
"x-amazon-events-detail-type",
77+
"x-amazon-events-source",
78+
"properties"
79+
],
80+
"type": "object"
81+
},
82+
"AWSEventProperties": {
83+
"additionalProperties": false,
84+
"properties": {
85+
"detail": {
86+
"type": "object"
87+
}
88+
},
89+
"required": [
90+
"detail"
91+
],
92+
"type": "object"
93+
}
94+
}
95+
}

packages/@aws-cdk/service-spec-importers/src/cli/import-db.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const AVAILABLE_SOURCES: Record<string, keyof DatabaseBuilder> = {
1717
arnTemplates: 'importArnTemplates',
1818
oobRelationships: 'importOobRelationships',
1919
logSources: 'importLogSources',
20+
eventbridgeschema: 'importEventBridgeSchema',
2021
};
2122

2223
async function main() {

packages/@aws-cdk/service-spec-importers/src/db-builder.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { importArnTemplates } from './importers/import-arn-templates';
55
import { importCannedMetrics } from './importers/import-canned-metrics';
66
import { importCloudFormationDocumentation } from './importers/import-cloudformation-docs';
77
import { importCloudFormationRegistryResource } from './importers/import-cloudformation-registry';
8+
import { importEventBridgeSchema } from './importers/import-eventbridge-schema';
89
import { importGetAttAllowList } from './importers/import-getatt-allowlist';
910
import { importLogSources } from './importers/import-log-source';
1011
import { importOobRelationships } from './importers/import-oob-relationships';
@@ -23,6 +24,7 @@ import {
2324
loadSamSpec,
2425
loadOobRelationships,
2526
} from './loaders';
27+
import { loadDefaultEventBridgeSchema } from './loaders/load-eventbridge-schema';
2628
import { JsonLensPatcher } from './patching';
2729
import { ProblemReport, ReportAudience } from './report';
2830

@@ -217,6 +219,26 @@ export class DatabaseBuilder {
217219
});
218220
}
219221

222+
public importEventBridgeSchema(schemaDirectory: string) {
223+
return this.addSourceImporter(async (db, report) => {
224+
const regions = await loadDefaultEventBridgeSchema(schemaDirectory, {
225+
...this.options,
226+
report,
227+
failureAudience: this.defaultProblemGrouping,
228+
});
229+
for (const region of regions) {
230+
for (const event of region.events) {
231+
importEventBridgeSchema({
232+
db,
233+
event,
234+
report,
235+
region: region.regionName,
236+
});
237+
}
238+
}
239+
});
240+
}
241+
220242
/**
221243
* Look at a load result and report problems
222244
*/

packages/@aws-cdk/service-spec-importers/src/db-diff.ts

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ import {
1616
UpdatedService,
1717
UpdatedTypeDefinition,
1818
MapDiff,
19+
Event,
20+
EventTypeDefinition,
21+
EventProperty,
22+
UpdatedEvent,
23+
UpdatedEventTypeDefinition,
24+
UpdatedEventProperty,
1925
} from '@aws-cdk/service-spec-types';
2026
import {
2127
diffByKey,
@@ -115,6 +121,7 @@ export class DbDiff {
115121
properties: collapseEmptyDiff(diffMap(a.properties, b.properties, (x, y) => this.diffProperty(x, y))),
116122
typeDefinitionDiff: this.diffResourceTypeDefinitions(a, b),
117123
metrics: this.diffResourceMetrics(a, b),
124+
events: this.diffResourceEvents(a, b),
118125
} satisfies AllFieldsGiven<UpdatedResource>);
119126
}
120127

@@ -177,6 +184,105 @@ export class DbDiff {
177184
} satisfies AllFieldsGiven<UpdatedTypeDefinition>);
178185
}
179186

187+
public diffResourceEvents(a: Resource, b: Resource): UpdatedResource['events'] {
188+
const aEvents = this.db1.follow('resourceHasEvent', a).map((r) => r.entity);
189+
const bEvents = this.db2.follow('resourceHasEvent', b).map((r) => r.entity);
190+
191+
return collapseEmptyDiff(
192+
diffByKey(
193+
aEvents,
194+
bEvents,
195+
(event) => event.name,
196+
(x, y) => this.diffEvent(x, y),
197+
),
198+
);
199+
}
200+
201+
public diffEvent(a: Event, b: Event): UpdatedEvent | undefined {
202+
return collapseUndefined({
203+
name: diffScalar(a, b, 'name'),
204+
description: diffScalar(a, b, 'description'),
205+
source: diffScalar(a, b, 'source'),
206+
detailType: diffScalar(a, b, 'detailType'),
207+
resourcesField: diffField(a, b, 'resourcesField', jsonEq),
208+
rootProperty: diffField(a, b, 'rootProperty', jsonEq),
209+
typeDefinitionDiff: this.diffEventTypeDefinitions(a, b),
210+
} satisfies AllFieldsGiven<UpdatedEvent>);
211+
}
212+
213+
public diffEventTypeDefinitions(a: Event, b: Event): UpdatedEvent['typeDefinitionDiff'] {
214+
const aTypes = this.db1.follow('eventUsesType', a).map((r) => r.entity);
215+
const bTypes = this.db2.follow('eventUsesType', b).map((r) => r.entity);
216+
217+
return collapseEmptyDiff(
218+
diffByKey(
219+
aTypes,
220+
bTypes,
221+
(type) => type.name,
222+
(x, y) => this.diffEventTypeDefinition(x, y),
223+
),
224+
);
225+
}
226+
227+
public diffEventTypeDefinition(
228+
a: EventTypeDefinition,
229+
b: EventTypeDefinition,
230+
): UpdatedEventTypeDefinition | undefined {
231+
return collapseUndefined({
232+
name: diffScalar(a, b, 'name'),
233+
properties: collapseEmptyDiff(diffMap(a.properties, b.properties, (x, y) => this.diffEventProperty(x, y))),
234+
} satisfies AllFieldsGiven<UpdatedEventTypeDefinition>);
235+
}
236+
237+
public diffEventProperty(a: EventProperty, b: EventProperty): UpdatedEventProperty | undefined {
238+
const anyDiffs = collapseUndefined({
239+
required: diffScalar(a, b, 'required', false),
240+
type: diffField(a, b, 'type', (x, y) => this.eqEventPropertyType(x, y)),
241+
} satisfies DontCareAboutTypes<AllFieldsGiven<EventProperty>>);
242+
243+
if (anyDiffs) {
244+
return { old: a, new: b };
245+
}
246+
return undefined;
247+
}
248+
249+
/**
250+
* Compare event property types by stringifying them.
251+
* Event property types reference EventTypeDefinition, not TypeDefinition.
252+
*/
253+
private eqEventPropertyType(a: EventProperty['type'], b: EventProperty['type']): boolean {
254+
return this.stringifyGenericType(a, this.db1) === this.stringifyGenericType(b, this.db2);
255+
}
256+
257+
/**
258+
* Stringify a generic property type for comparison.
259+
*/
260+
private stringifyGenericType(type: EventProperty['type'], db: SpecDatabase): string {
261+
if (type.type === 'string') return 'string';
262+
if (type.type === 'number') return 'number';
263+
if (type.type === 'integer') return 'integer';
264+
if (type.type === 'boolean') return 'boolean';
265+
if (type.type === 'json') return 'json';
266+
if (type.type === 'date-time') return 'date-time';
267+
if (type.type === 'null') return 'null';
268+
if (type.type === 'tag') return 'tag';
269+
if (type.type === 'ref') {
270+
const entity = db.get('eventTypeDefinition', type.reference.$ref);
271+
return `ref:${entity.name}`;
272+
}
273+
if (type.type === 'array') {
274+
return `array<${this.stringifyGenericType(type.element, db)}>`;
275+
}
276+
if (type.type === 'map') {
277+
return `map<${this.stringifyGenericType(type.element, db)}>`;
278+
}
279+
if (type.type === 'union') {
280+
const types = type.types.map((t) => this.stringifyGenericType(t, db)).sort();
281+
return `union<${types.join('|')}>`;
282+
}
283+
return 'unknown';
284+
}
285+
180286
/**
181287
* Tricky -- we have to deep-compare all the type references which will have different ids in
182288
* different databases.

0 commit comments

Comments
 (0)