diff --git a/packages/@aws-cdk/service-spec-importers/src/db-diff.ts b/packages/@aws-cdk/service-spec-importers/src/db-diff.ts index 14deca5a8..00be77997 100644 --- a/packages/@aws-cdk/service-spec-importers/src/db-diff.ts +++ b/packages/@aws-cdk/service-spec-importers/src/db-diff.ts @@ -74,6 +74,9 @@ export class DbDiff { name: diffScalar(a, b, 'name'), scrutinizable: diffScalar(a, b, 'scrutinizable'), tagInformation: diffField(a, b, 'tagInformation', jsonEq), + primaryIdentifier: collapseEmptyDiff( + diffList(a.primaryIdentifier ?? [], b.primaryIdentifier ?? [], (x, y) => x === y), + ), attributes: collapseEmptyDiff(diffMap(a.attributes, b.attributes, (x, y) => this.diffAttribute(x, y))), properties: collapseEmptyDiff(diffMap(a.properties, b.properties, (x, y) => this.diffProperty(x, y))), typeDefinitionDiff: this.diffResourceTypeDefinitions(a, b), diff --git a/packages/@aws-cdk/service-spec-importers/src/import-cloudformation-registry.ts b/packages/@aws-cdk/service-spec-importers/src/import-cloudformation-registry.ts index d78c1a8bc..3046ca1f0 100644 --- a/packages/@aws-cdk/service-spec-importers/src/import-cloudformation-registry.ts +++ b/packages/@aws-cdk/service-spec-importers/src/import-cloudformation-registry.ts @@ -16,6 +16,7 @@ export interface LoadCloudFormationRegistryResourceOptions { readonly report: ProblemReport; readonly region?: string; } + export function importCloudFormationRegistryResource(options: LoadCloudFormationRegistryResourceOptions) { const { db, resource } = options; const report = options.report.forAudience(ReportAudience.fromCloudFormationResource(resource.typeName)); @@ -25,6 +26,7 @@ export function importCloudFormationRegistryResource(options: LoadCloudFormation const specBuilder = new SpecBuilder(db); const resourceBuilder = specBuilder.resourceBuilder(resource.typeName, { description: resource.description, + primaryIdentifier: resource.primaryIdentifier?.map((id) => id.slice(12)), // remove "/properties/" that reliably is included in each identifier region: options.region, }); const resourceFailure = failure.in(resource.typeName); diff --git a/packages/@aws-cdk/service-spec-importers/src/resource-builder.ts b/packages/@aws-cdk/service-spec-importers/src/resource-builder.ts index 3f9a6fe5c..a9c3dad23 100644 --- a/packages/@aws-cdk/service-spec-importers/src/resource-builder.ts +++ b/packages/@aws-cdk/service-spec-importers/src/resource-builder.ts @@ -12,13 +12,22 @@ import { } from '@aws-cdk/service-spec-types'; import { AllFieldsGiven } from './diff-helpers'; +/** + * Options for the resourceBuilder API + */ +export interface ResourceBuilderOptions { + description?: string; + region?: string; + primaryIdentifier?: string[]; +} + /** * Adds resources and types to a spec database */ export class SpecBuilder { constructor(public readonly db: SpecDatabase) {} - public resourceBuilder(typeName: string, options: { description?: string; region?: string } = {}) { + public resourceBuilder(typeName: string, options: ResourceBuilderOptions = {}) { const existing = this.db.lookup('resource', 'cloudFormationType', 'equals', typeName); if (existing.length > 0) { @@ -26,6 +35,10 @@ export class SpecBuilder { if (!resource.documentation && options.description) { resource.documentation = options.description; } + if (!resource.primaryIdentifier) { + resource.primaryIdentifier = options.primaryIdentifier; + } + return new ResourceBuilder(this.db, resource); } @@ -33,6 +46,7 @@ export class SpecBuilder { cloudFormationType: typeName, documentation: options.description, name: last(typeName.split('::')), + primaryIdentifier: options.primaryIdentifier, attributes: {}, properties: {}, }); diff --git a/packages/@aws-cdk/service-spec-importers/test/cloudformation-registry.test.ts b/packages/@aws-cdk/service-spec-importers/test/cloudformation-registry.test.ts new file mode 100644 index 000000000..0488cc615 --- /dev/null +++ b/packages/@aws-cdk/service-spec-importers/test/cloudformation-registry.test.ts @@ -0,0 +1,37 @@ +import { emptyDatabase } from '@aws-cdk/service-spec-types'; +import { importCloudFormationRegistryResource } from '../src/import-cloudformation-registry'; +import { ProblemReport } from '../src/report'; + +let db: ReturnType; +let report: ProblemReport; +beforeEach(() => { + db = emptyDatabase(); + report = new ProblemReport(); +}); + +test('include primaryIdentifier in database', () => { + importCloudFormationRegistryResource({ + db, + report, + resource: { + typeName: 'AWS::Some::Type', + description: 'resource with PrimaryIdentifier', + properties: { + id: { + type: 'string', + }, + secondId: { + type: 'string', + }, + notId: { + type: 'string', + }, + }, + primaryIdentifier: ['/properties/id', '/properties/secondId'], + }, + }); + + // eslint-disable-next-line prettier/prettier + const primaryIdentifier = db.lookup('resource', 'cloudFormationType', 'equals', 'AWS::Some::Type')[0]?.primaryIdentifier; + expect(primaryIdentifier).toEqual(['id', 'secondId']); +}); diff --git a/packages/@aws-cdk/service-spec-types/src/types/diff.ts b/packages/@aws-cdk/service-spec-types/src/types/diff.ts index bd5b6bdc9..f72b0447b 100644 --- a/packages/@aws-cdk/service-spec-types/src/types/diff.ts +++ b/packages/@aws-cdk/service-spec-types/src/types/diff.ts @@ -36,6 +36,7 @@ export interface UpdatedResource { readonly tagInformation?: ScalarDiff; readonly scrutinizable?: ScalarDiff; readonly typeDefinitionDiff?: MapDiff; + readonly primaryIdentifier?: ListDiff; } export interface UpdatedProperty { diff --git a/packages/@aws-cdk/service-spec-types/src/types/resource.ts b/packages/@aws-cdk/service-spec-types/src/types/resource.ts index b6f29efcb..41e2d905d 100644 --- a/packages/@aws-cdk/service-spec-types/src/types/resource.ts +++ b/packages/@aws-cdk/service-spec-types/src/types/resource.ts @@ -60,6 +60,7 @@ export interface Resource extends Entity { */ cloudFormationTransform?: string; documentation?: string; + primaryIdentifier?: string[]; readonly properties: ResourceProperties; readonly attributes: Record; readonly validations?: unknown;