From ee1323641cb16355223ed4466e9f59d6019aa211 Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Tue, 22 Jul 2025 16:47:31 +0100 Subject: [PATCH 01/26] feat: new resource reference interfaces --- packages/awslint/lib/rules/core-types.ts | 9 +- .../spec2cdk/lib/cdk/resource-class.ts | 24 +- .../spec2cdk/lib/cdk/resource-decider.ts | 73 ++ tools/@aws-cdk/spec2cdk/lib/cli/cli.ts | 8 + .../spec2cdk/lib/naming/conventions.ts | 4 + .../test/__snapshots__/resources.test.ts.snap | 837 ++++++++++++++++++ .../@aws-cdk/spec2cdk/test/resources.test.ts | 156 ++++ 7 files changed, 1104 insertions(+), 7 deletions(-) create mode 100644 tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap create mode 100644 tools/@aws-cdk/spec2cdk/test/resources.test.ts diff --git a/packages/awslint/lib/rules/core-types.ts b/packages/awslint/lib/rules/core-types.ts index eb5de41f61e2c..1a1ce304634f6 100644 --- a/packages/awslint/lib/rules/core-types.ts +++ b/packages/awslint/lib/rules/core-types.ts @@ -44,11 +44,7 @@ export class CoreTypes { return false; } - if (!c.name.startsWith('Cfn')) { - return false; - } - - return true; + return c.name.startsWith('Cfn'); } /** @@ -86,10 +82,11 @@ export class CoreTypes { } /** - * Return true if the given interface type is a CFN class or prop type + * Return true if the given interface type is a CFN class, prop type or interface */ public static isCfnType(interfaceType: reflect.Type) { return interfaceType.name.startsWith('Cfn') + || interfaceType.name.startsWith('ICfn') || (interfaceType.namespace && interfaceType.namespace.startsWith('Cfn')) // aws_service.CfnTheResource.SubType || (interfaceType.namespace && interfaceType.namespace.split('.', 2).at(1)?.startsWith('Cfn')); diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts index 7890e6efa5b0a..0f61ca274c812 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts @@ -20,6 +20,7 @@ import { Stability, ObjectLiteral, Module, + InterfaceType, } from '@cdklabs/typewriter'; import { CDK_CORE, CONSTRUCTS } from './cdk'; import { CloudFormationMapping } from './cloudformation-mapping'; @@ -33,6 +34,7 @@ import { cfnProducerNameFromType, propStructNameFromResource, staticRequiredTransform, + interfaceNameFromResource, } from '../naming'; import { splitDocumentation } from '../util'; @@ -45,6 +47,7 @@ const $this = $E(expr.this_()); export class ResourceClass extends ClassType { private readonly propsType: StructType; + private readonly resourceInterface: InterfaceType; private readonly decider: ResourceDecider; private readonly converter: TypeConverter; private readonly module: Module; @@ -55,6 +58,16 @@ export class ResourceClass extends ClassType { private readonly resource: Resource, private readonly suffix?: string, ) { + const resourceInterface = new InterfaceType(scope, { + export: true, + name: interfaceNameFromResource(resource, suffix), + docs: { + summary: `Attributes to reference a \`${classNameFromResource(resource)}\`.`, + stability: Stability.External, + }, + extends: [CONSTRUCTS.IConstruct], + }); + super(scope, { export: true, name: classNameFromResource(resource, suffix), @@ -67,9 +80,10 @@ export class ResourceClass extends ClassType { }), }, extends: CDK_CORE.CfnResource, - implements: [CDK_CORE.IInspectable, ...ResourceDecider.taggabilityInterfaces(resource)], + implements: [CDK_CORE.IInspectable, resourceInterface.type, ...ResourceDecider.taggabilityInterfaces(resource)], }); + this.resourceInterface = resourceInterface; this.module = Module.of(this); this.propsType = new StructType(this.scope, { @@ -105,6 +119,14 @@ export class ResourceClass extends ClassType { cfnMapping.add(prop.cfnMapping); } + // Build the shared interface + for (const identifier of this.decider.primaryIdentifier ?? []) { + this.resourceInterface.addProperty({ + ...identifier, + immutable: true, + }); + } + // Build the members of this class this.addProperty({ name: staticResourceTypeName(), diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts index 23906deef7805..e304709a186fd 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts @@ -10,6 +10,9 @@ import { splitDocumentation } from '../util'; // This convenience typewriter builder is used all over the place const $this = $E(expr.this_()); +// This convenience typewriter builder is used for cloudformation intrinsics +const $Fn = $E(expr.directCode('cdk.Fn')); + /** * Decide how properties get mapped between model types, Typescript types, and CloudFormation */ @@ -25,6 +28,7 @@ export class ResourceDecider { private readonly taggability?: TaggabilityStyle; + public readonly primaryIdentifier = new Array(); public readonly propsProperties = new Array(); public readonly classProperties = new Array(); public readonly classAttributeProperties = new Array(); @@ -35,6 +39,8 @@ export class ResourceDecider { this.convertProperties(); this.convertAttributes(); + this.convertPrimaryIdentifier(); + this.propsProperties.sort((p1, p2) => p1.propertySpec.name.localeCompare(p2.propertySpec.name)); this.classProperties.sort((p1, p2) => p1.propertySpec.name.localeCompare(p2.propertySpec.name)); this.classAttributeProperties.sort((p1, p2) => p1.propertySpec.name.localeCompare(p2.propertySpec.name)); @@ -59,6 +65,73 @@ export class ResourceDecider { } } + private convertPrimaryIdentifier() { + if (this.resource.primaryIdentifier === undefined) { return; } + for (let i = 0; i < (this.resource.primaryIdentifier).length; i++) { + const cfnName = this.resource.primaryIdentifier[i]; + const att = this.findAttributeByName(attributePropertyName(cfnName)); + const prop = this.findPropertyByName(propertyNameFromCloudFormation(cfnName)); + if (att) { + this.primaryIdentifier.push(att); + } else if (prop) { + const propSpec = prop.propertySpec; + + // Build an attribute out of the property we're getting + // Create initializer for new attribute, if possible + let initializer: Expression | undefined = undefined; + if (propSpec.type === Type.STRING) { // handling only this case for now + if (this.resource.primaryIdentifier!.length === 1) { + initializer = CDK_CORE.tokenAsString($this.ref); + } else { + initializer = CDK_CORE.tokenAsString($Fn.select(expr.lit(i), $Fn.split(expr.lit('|'), $this.ref))); + } + } + + // If we cannot come up with an initializer, we're dropping this property on the floor + if (!initializer) { continue; } + + // Build an attribute spec out of the property spec + const attrPropertySpec = this.convertPropertySpecToRefAttribute(propSpec); + + // Add the new attribute to the relevant places + this.classAttributeProperties.push({ + propertySpec: attrPropertySpec, + initializer, + }); + + this.primaryIdentifier.push(attrPropertySpec); + } + } + } + + private convertPropertySpecToRefAttribute(propSpec: PropertySpec): PropertySpec { + return { + ...propSpec, + name: attributePropertyName(propSpec.name[0].toUpperCase() + propSpec.name.slice(1)), + docs: { + ...propSpec.docs, + summary: (propSpec.docs?.summary ?? '').concat('\nThis property gets determined after the resource is created.'), + remarks: (propSpec.docs?.remarks ?? '').concat('@cloudformationAttribute Ref'), + }, + immutable: true, + optional: false, + }; + } + + private findPropertyByName(name: string): ClassProperty | undefined { + const props = this.classProperties.filter((prop) => prop.propertySpec.name === name); + // there's no way we have multiple properties with the same name + if (props.length > 0) { return props[0]; } + return; + } + + private findAttributeByName(name: string): PropertySpec | undefined { + const atts = this.classAttributeProperties.filter((att) => att.propertySpec.name === name); + // there's no way we have multiple attributes with the same name + if (atts.length > 0) { return atts[0].propertySpec; } + return; + } + /** * Default mapping for a property */ diff --git a/tools/@aws-cdk/spec2cdk/lib/cli/cli.ts b/tools/@aws-cdk/spec2cdk/lib/cli/cli.ts index 51a50d167f001..30e47c157689b 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cli/cli.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cli/cli.ts @@ -143,3 +143,11 @@ function stringOr(pat: unknown, def: string) { } return pat; } + +async function run() { + await generateAll({ + outputPath: '/Users/otaviom/construct-harmony', + }); +} +// eslint-disable-next-line no-console +run().catch(console.log); diff --git a/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts b/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts index be7a7f7336ba7..a22926e56cb66 100644 --- a/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts +++ b/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts @@ -55,6 +55,10 @@ export function propStructNameFromResource(res: Resource, suffix?: string) { return `${classNameFromResource(res, suffix)}Props`; } +export function interfaceNameFromResource(res: Resource, suffix?: string) { + return `I${classNameFromResource(res, suffix)}`; +} + export function cfnProducerNameFromType(struct: TypeDeclaration) { return `convert${qualifiedName(struct)}ToCloudFormation`; } diff --git a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap new file mode 100644 index 0000000000000..8759d134e1d67 --- /dev/null +++ b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap @@ -0,0 +1,837 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`resource interface when primaryIdentifier is a property 1`] = ` +"/* eslint-disable prettier/prettier, @stylistic/max-len */ +import * as cdk from "aws-cdk-lib"; +import * as constructs from "constructs"; +import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; +import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; + +/** + * Attributes for \`CfnResource\`. + * + * @stability external + */ +export interface ICfnResource extends constructs.IConstruct { + /** + * The identifier of the resource. + * This property gets determined after the resource is created. + * + * @cloudformationAttribute Ref + */ + readonly attrId: string; +} + +/** + * @cloudformationResource AWS::Some::Resource + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { + /** + * The CloudFormation resource type name for this resource class. + */ + public static readonly CFN_RESOURCE_TYPE_NAME: string = "AWS::Some::Resource"; + + /** + * Build a CfnResource from CloudFormation properties + * + * A factory method that creates a new instance of this class from an object + * containing the CloudFormation properties of this resource. + * Used in the @aws-cdk/cloudformation-include module. + * + * @internal + */ + public static _fromCloudFormation(scope: constructs.Construct, id: string, resourceAttributes: any, options: cfn_parse.FromCloudFormationOptions): CfnResource { + resourceAttributes = resourceAttributes || {}; + const resourceProperties = options.parser.parseValue(resourceAttributes.Properties); + const propsResult = CfnResourcePropsFromCloudFormation(resourceProperties); + if (cdk.isResolvableObject(propsResult.value)) { + throw new cdk_errors.ValidationError("Unexpected IResolvable", scope); + } + const ret = new CfnResource(scope, id, propsResult.value); + for (const [propKey, propVal] of Object.entries(propsResult.extraProperties)) { + ret.addPropertyOverride(propKey, propVal); + } + options.parser.handleAttributes(ret, resourceAttributes, id); + return ret; + } + + /** + * The identifier of the resource. + * This property gets determined after the resource is created. + * + * @cloudformationAttribute Ref + */ + public readonly attrId: string; + + /** + * The identifier of the resource. + */ + public id?: string; + + /** + * @param scope Scope in which this resource is defined + * @param id Construct identifier for this resource (unique in its scope) + * @param props Resource properties + */ + public constructor(scope: constructs.Construct, id: string, props: CfnResourceProps = {}) { + super(scope, id, { + "type": CfnResource.CFN_RESOURCE_TYPE_NAME, + "properties": props + }); + + this.attrId = cdk.Token.asString(this.ref); + this.id = props.id; + } + + protected get cfnProperties(): Record { + return { + "id": this.id + }; + } + + /** + * Examines the CloudFormation resource and discloses attributes + * + * @param inspector tree inspector to collect and process attributes + */ + public inspect(inspector: cdk.TreeInspector): void { + inspector.addAttribute("aws:cdk:cloudformation:type", CfnResource.CFN_RESOURCE_TYPE_NAME); + inspector.addAttribute("aws:cdk:cloudformation:props", this.cfnProperties); + } + + protected renderProperties(props: Record): Record { + return convertCfnResourcePropsToCloudFormation(props); + } +} + +/** + * Properties for defining a \`CfnResource\` + * + * @struct + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export interface CfnResourceProps { + /** + * The identifier of the resource. + * + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html#cfn-some-resource-id + */ + readonly id?: string; +} + +/** + * Determine whether the given properties match those of a \`CfnResourceProps\` + * + * @param properties - the TypeScript properties of a \`CfnResourceProps\` + * + * @returns the result of the validation. + */ +// @ts-ignore TS6133 +function CfnResourcePropsValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) return cdk.VALIDATION_SUCCESS; + const errors = new cdk.ValidationResults(); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + errors.collect(new cdk.ValidationResult("Expected an object, but received: " + JSON.stringify(properties))); + } + errors.collect(cdk.propertyValidator("id", cdk.validateString)(properties.id)); + return errors.wrap("supplied properties not correct for \\"CfnResourceProps\\""); +} + +// @ts-ignore TS6133 +function convertCfnResourcePropsToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) return properties; + CfnResourcePropsValidator(properties).assertSuccess(); + return { + "Id": cdk.stringToCloudFormation(properties.id) + }; +} + +// @ts-ignore TS6133 +function CfnResourcePropsFromCloudFormation(properties: any): cfn_parse.FromCloudFormationResult { + if (cdk.isResolvableObject(properties)) { + return new cfn_parse.FromCloudFormationResult(properties); + } + properties = ((properties == null) ? {} : properties); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + return new cfn_parse.FromCloudFormationResult(properties); + } + const ret = new cfn_parse.FromCloudFormationPropertyObject(); + ret.addPropertyResult("id", "Id", (properties.Id != null ? cfn_parse.FromCloudFormation.getString(properties.Id) : undefined)); + ret.addUnrecognizedPropertiesAsExtra(properties); + return ret; +}" +`; + +exports[`resource interface when primaryIdentifier is an attribute 1`] = ` +"/* eslint-disable prettier/prettier, @stylistic/max-len */ +import * as cdk from "aws-cdk-lib"; +import * as constructs from "constructs"; +import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; +import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; + +/** + * Attributes for \`CfnResource\`. + * + * @stability external + */ +export interface ICfnResource extends constructs.IConstruct { + /** + * The identifier of the resource + * + * @cloudformationAttribute Id + */ + readonly attrId: string; +} + +/** + * @cloudformationResource AWS::Some::Resource + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { + /** + * The CloudFormation resource type name for this resource class. + */ + public static readonly CFN_RESOURCE_TYPE_NAME: string = "AWS::Some::Resource"; + + /** + * Build a CfnResource from CloudFormation properties + * + * A factory method that creates a new instance of this class from an object + * containing the CloudFormation properties of this resource. + * Used in the @aws-cdk/cloudformation-include module. + * + * @internal + */ + public static _fromCloudFormation(scope: constructs.Construct, id: string, resourceAttributes: any, options: cfn_parse.FromCloudFormationOptions): CfnResource { + resourceAttributes = resourceAttributes || {}; + const resourceProperties = options.parser.parseValue(resourceAttributes.Properties); + const propsResult = CfnResourcePropsFromCloudFormation(resourceProperties); + if (cdk.isResolvableObject(propsResult.value)) { + throw new cdk_errors.ValidationError("Unexpected IResolvable", scope); + } + const ret = new CfnResource(scope, id, propsResult.value); + for (const [propKey, propVal] of Object.entries(propsResult.extraProperties)) { + ret.addPropertyOverride(propKey, propVal); + } + options.parser.handleAttributes(ret, resourceAttributes, id); + return ret; + } + + /** + * The identifier of the resource + * + * @cloudformationAttribute Id + */ + public readonly attrId: string; + + /** + * @param scope Scope in which this resource is defined + * @param id Construct identifier for this resource (unique in its scope) + * @param props Resource properties + */ + public constructor(scope: constructs.Construct, id: string, props: CfnResourceProps = {}) { + super(scope, id, { + "type": CfnResource.CFN_RESOURCE_TYPE_NAME, + "properties": props + }); + + this.attrId = cdk.Token.asString(this.getAtt("Id", cdk.ResolutionTypeHint.STRING)); + } + + protected get cfnProperties(): Record { + return {}; + } + + /** + * Examines the CloudFormation resource and discloses attributes + * + * @param inspector tree inspector to collect and process attributes + */ + public inspect(inspector: cdk.TreeInspector): void { + inspector.addAttribute("aws:cdk:cloudformation:type", CfnResource.CFN_RESOURCE_TYPE_NAME); + inspector.addAttribute("aws:cdk:cloudformation:props", this.cfnProperties); + } + + protected renderProperties(props: Record): Record { + return convertCfnResourcePropsToCloudFormation(props); + } +} + +/** + * Properties for defining a \`CfnResource\` + * + * @struct + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export interface CfnResourceProps { + +} + +/** + * Determine whether the given properties match those of a \`CfnResourceProps\` + * + * @param properties - the TypeScript properties of a \`CfnResourceProps\` + * + * @returns the result of the validation. + */ +// @ts-ignore TS6133 +function CfnResourcePropsValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) return cdk.VALIDATION_SUCCESS; + const errors = new cdk.ValidationResults(); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + errors.collect(new cdk.ValidationResult("Expected an object, but received: " + JSON.stringify(properties))); + } + return errors.wrap("supplied properties not correct for \\"CfnResourceProps\\""); +} + +// @ts-ignore TS6133 +function convertCfnResourcePropsToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) return properties; + CfnResourcePropsValidator(properties).assertSuccess(); + return {}; +} + +// @ts-ignore TS6133 +function CfnResourcePropsFromCloudFormation(properties: any): cfn_parse.FromCloudFormationResult { + if (cdk.isResolvableObject(properties)) { + return new cfn_parse.FromCloudFormationResult(properties); + } + properties = ((properties == null) ? {} : properties); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + return new cfn_parse.FromCloudFormationResult(properties); + } + const ret = new cfn_parse.FromCloudFormationPropertyObject(); + ret.addUnrecognizedPropertiesAsExtra(properties); + return ret; +}" +`; + +exports[`resource interface with multiple primaryIdentifiers 1`] = ` +"/* eslint-disable prettier/prettier, @stylistic/max-len */ +import * as cdk from "aws-cdk-lib"; +import * as constructs from "constructs"; +import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; +import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; + +/** + * Attributes for \`CfnResource\`. + * + * @stability external + */ +export interface ICfnResource extends constructs.IConstruct { + /** + * The identifier of the resource + * + * @cloudformationAttribute Id + */ + readonly attrId: string; + + /** + * Another identifier of the resource + * + * @cloudformationAttribute Another + */ + readonly attrAnother: string; +} + +/** + * @cloudformationResource AWS::Some::Resource + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { + /** + * The CloudFormation resource type name for this resource class. + */ + public static readonly CFN_RESOURCE_TYPE_NAME: string = "AWS::Some::Resource"; + + /** + * Build a CfnResource from CloudFormation properties + * + * A factory method that creates a new instance of this class from an object + * containing the CloudFormation properties of this resource. + * Used in the @aws-cdk/cloudformation-include module. + * + * @internal + */ + public static _fromCloudFormation(scope: constructs.Construct, id: string, resourceAttributes: any, options: cfn_parse.FromCloudFormationOptions): CfnResource { + resourceAttributes = resourceAttributes || {}; + const resourceProperties = options.parser.parseValue(resourceAttributes.Properties); + const propsResult = CfnResourcePropsFromCloudFormation(resourceProperties); + if (cdk.isResolvableObject(propsResult.value)) { + throw new cdk_errors.ValidationError("Unexpected IResolvable", scope); + } + const ret = new CfnResource(scope, id, propsResult.value); + for (const [propKey, propVal] of Object.entries(propsResult.extraProperties)) { + ret.addPropertyOverride(propKey, propVal); + } + options.parser.handleAttributes(ret, resourceAttributes, id); + return ret; + } + + /** + * Another identifier of the resource + * + * @cloudformationAttribute Another + */ + public readonly attrAnother: string; + + /** + * The identifier of the resource + * + * @cloudformationAttribute Id + */ + public readonly attrId: string; + + /** + * @param scope Scope in which this resource is defined + * @param id Construct identifier for this resource (unique in its scope) + * @param props Resource properties + */ + public constructor(scope: constructs.Construct, id: string, props: CfnResourceProps = {}) { + super(scope, id, { + "type": CfnResource.CFN_RESOURCE_TYPE_NAME, + "properties": props + }); + + this.attrAnother = cdk.Token.asString(this.getAtt("Another", cdk.ResolutionTypeHint.STRING)); + this.attrId = cdk.Token.asString(this.getAtt("Id", cdk.ResolutionTypeHint.STRING)); + } + + protected get cfnProperties(): Record { + return {}; + } + + /** + * Examines the CloudFormation resource and discloses attributes + * + * @param inspector tree inspector to collect and process attributes + */ + public inspect(inspector: cdk.TreeInspector): void { + inspector.addAttribute("aws:cdk:cloudformation:type", CfnResource.CFN_RESOURCE_TYPE_NAME); + inspector.addAttribute("aws:cdk:cloudformation:props", this.cfnProperties); + } + + protected renderProperties(props: Record): Record { + return convertCfnResourcePropsToCloudFormation(props); + } +} + +/** + * Properties for defining a \`CfnResource\` + * + * @struct + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export interface CfnResourceProps { + +} + +/** + * Determine whether the given properties match those of a \`CfnResourceProps\` + * + * @param properties - the TypeScript properties of a \`CfnResourceProps\` + * + * @returns the result of the validation. + */ +// @ts-ignore TS6133 +function CfnResourcePropsValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) return cdk.VALIDATION_SUCCESS; + const errors = new cdk.ValidationResults(); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + errors.collect(new cdk.ValidationResult("Expected an object, but received: " + JSON.stringify(properties))); + } + return errors.wrap("supplied properties not correct for \\"CfnResourceProps\\""); +} + +// @ts-ignore TS6133 +function convertCfnResourcePropsToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) return properties; + CfnResourcePropsValidator(properties).assertSuccess(); + return {}; +} + +// @ts-ignore TS6133 +function CfnResourcePropsFromCloudFormation(properties: any): cfn_parse.FromCloudFormationResult { + if (cdk.isResolvableObject(properties)) { + return new cfn_parse.FromCloudFormationResult(properties); + } + properties = ((properties == null) ? {} : properties); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + return new cfn_parse.FromCloudFormationResult(properties); + } + const ret = new cfn_parse.FromCloudFormationPropertyObject(); + ret.addUnrecognizedPropertiesAsExtra(properties); + return ret; +}" +`; + +exports[`resource with multiple primaryIdentifiers as properties 1`] = ` +"/* eslint-disable prettier/prettier, @stylistic/max-len */ +import * as cdk from "aws-cdk-lib"; +import * as constructs from "constructs"; +import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; +import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; + +/** + * Attributes for \`CfnResource\`. + * + * @stability external + */ +export interface ICfnResource extends constructs.IConstruct { + /** + * The identifier of the resource. + * This property gets determined after the resource is created. + * + * @cloudformationAttribute Ref + */ + readonly attrId: string; + + /** + * Another identifier of the resource. + * This property gets determined after the resource is created. + * + * @cloudformationAttribute Ref + */ + readonly attrAnotherId: string; +} + +/** + * @cloudformationResource AWS::Some::Resource + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { + /** + * The CloudFormation resource type name for this resource class. + */ + public static readonly CFN_RESOURCE_TYPE_NAME: string = "AWS::Some::Resource"; + + /** + * Build a CfnResource from CloudFormation properties + * + * A factory method that creates a new instance of this class from an object + * containing the CloudFormation properties of this resource. + * Used in the @aws-cdk/cloudformation-include module. + * + * @internal + */ + public static _fromCloudFormation(scope: constructs.Construct, id: string, resourceAttributes: any, options: cfn_parse.FromCloudFormationOptions): CfnResource { + resourceAttributes = resourceAttributes || {}; + const resourceProperties = options.parser.parseValue(resourceAttributes.Properties); + const propsResult = CfnResourcePropsFromCloudFormation(resourceProperties); + if (cdk.isResolvableObject(propsResult.value)) { + throw new cdk_errors.ValidationError("Unexpected IResolvable", scope); + } + const ret = new CfnResource(scope, id, propsResult.value); + for (const [propKey, propVal] of Object.entries(propsResult.extraProperties)) { + ret.addPropertyOverride(propKey, propVal); + } + options.parser.handleAttributes(ret, resourceAttributes, id); + return ret; + } + + /** + * Another identifier of the resource. + * This property gets determined after the resource is created. + * + * @cloudformationAttribute Ref + */ + public readonly attrAnotherId: string; + + /** + * The identifier of the resource. + * This property gets determined after the resource is created. + * + * @cloudformationAttribute Ref + */ + public readonly attrId: string; + + /** + * Another identifier of the resource. + */ + public anotherId?: string; + + /** + * The identifier of the resource. + */ + public id?: string; + + /** + * @param scope Scope in which this resource is defined + * @param id Construct identifier for this resource (unique in its scope) + * @param props Resource properties + */ + public constructor(scope: constructs.Construct, id: string, props: CfnResourceProps = {}) { + super(scope, id, { + "type": CfnResource.CFN_RESOURCE_TYPE_NAME, + "properties": props + }); + + this.attrAnotherId = cdk.Token.asString(cdk.Fn.select(1, cdk.Fn.split("|", this.ref))); + this.attrId = cdk.Token.asString(cdk.Fn.select(0, cdk.Fn.split("|", this.ref))); + this.anotherId = props.anotherId; + this.id = props.id; + } + + protected get cfnProperties(): Record { + return { + "anotherId": this.anotherId, + "id": this.id + }; + } + + /** + * Examines the CloudFormation resource and discloses attributes + * + * @param inspector tree inspector to collect and process attributes + */ + public inspect(inspector: cdk.TreeInspector): void { + inspector.addAttribute("aws:cdk:cloudformation:type", CfnResource.CFN_RESOURCE_TYPE_NAME); + inspector.addAttribute("aws:cdk:cloudformation:props", this.cfnProperties); + } + + protected renderProperties(props: Record): Record { + return convertCfnResourcePropsToCloudFormation(props); + } +} + +/** + * Properties for defining a \`CfnResource\` + * + * @struct + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export interface CfnResourceProps { + /** + * Another identifier of the resource. + * + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html#cfn-some-resource-anotherid + */ + readonly anotherId?: string; + + /** + * The identifier of the resource. + * + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html#cfn-some-resource-id + */ + readonly id?: string; +} + +/** + * Determine whether the given properties match those of a \`CfnResourceProps\` + * + * @param properties - the TypeScript properties of a \`CfnResourceProps\` + * + * @returns the result of the validation. + */ +// @ts-ignore TS6133 +function CfnResourcePropsValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) return cdk.VALIDATION_SUCCESS; + const errors = new cdk.ValidationResults(); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + errors.collect(new cdk.ValidationResult("Expected an object, but received: " + JSON.stringify(properties))); + } + errors.collect(cdk.propertyValidator("anotherId", cdk.validateString)(properties.anotherId)); + errors.collect(cdk.propertyValidator("id", cdk.validateString)(properties.id)); + return errors.wrap("supplied properties not correct for \\"CfnResourceProps\\""); +} + +// @ts-ignore TS6133 +function convertCfnResourcePropsToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) return properties; + CfnResourcePropsValidator(properties).assertSuccess(); + return { + "AnotherId": cdk.stringToCloudFormation(properties.anotherId), + "Id": cdk.stringToCloudFormation(properties.id) + }; +} + +// @ts-ignore TS6133 +function CfnResourcePropsFromCloudFormation(properties: any): cfn_parse.FromCloudFormationResult { + if (cdk.isResolvableObject(properties)) { + return new cfn_parse.FromCloudFormationResult(properties); + } + properties = ((properties == null) ? {} : properties); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + return new cfn_parse.FromCloudFormationResult(properties); + } + const ret = new cfn_parse.FromCloudFormationPropertyObject(); + ret.addPropertyResult("anotherId", "AnotherId", (properties.AnotherId != null ? cfn_parse.FromCloudFormation.getString(properties.AnotherId) : undefined)); + ret.addPropertyResult("id", "Id", (properties.Id != null ? cfn_parse.FromCloudFormation.getString(properties.Id) : undefined)); + ret.addUnrecognizedPropertiesAsExtra(properties); + return ret; +}" +`; + +exports[`resource with optional primary identifier gets property from ref 1`] = ` +"/* eslint-disable prettier/prettier, @stylistic/max-len */ +import * as cdk from "aws-cdk-lib"; +import * as constructs from "constructs"; +import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; +import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; + +/** + * Attributes for \`CfnResource\`. + * + * @stability external + */ +export interface ICfnResource extends constructs.IConstruct { + /** + * The identifier of the resource. + * This property gets determined after the resource is created. + * + * @cloudformationAttribute Ref + */ + readonly attrId: string; +} + +/** + * @cloudformationResource AWS::Some::Resource + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { + /** + * The CloudFormation resource type name for this resource class. + */ + public static readonly CFN_RESOURCE_TYPE_NAME: string = "AWS::Some::Resource"; + + /** + * Build a CfnResource from CloudFormation properties + * + * A factory method that creates a new instance of this class from an object + * containing the CloudFormation properties of this resource. + * Used in the @aws-cdk/cloudformation-include module. + * + * @internal + */ + public static _fromCloudFormation(scope: constructs.Construct, id: string, resourceAttributes: any, options: cfn_parse.FromCloudFormationOptions): CfnResource { + resourceAttributes = resourceAttributes || {}; + const resourceProperties = options.parser.parseValue(resourceAttributes.Properties); + const propsResult = CfnResourcePropsFromCloudFormation(resourceProperties); + if (cdk.isResolvableObject(propsResult.value)) { + throw new cdk_errors.ValidationError("Unexpected IResolvable", scope); + } + const ret = new CfnResource(scope, id, propsResult.value); + for (const [propKey, propVal] of Object.entries(propsResult.extraProperties)) { + ret.addPropertyOverride(propKey, propVal); + } + options.parser.handleAttributes(ret, resourceAttributes, id); + return ret; + } + + /** + * The identifier of the resource. + * This property gets determined after the resource is created. + * + * @cloudformationAttribute Ref + */ + public readonly attrId: string; + + /** + * The identifier of the resource. + */ + public id?: string; + + /** + * @param scope Scope in which this resource is defined + * @param id Construct identifier for this resource (unique in its scope) + * @param props Resource properties + */ + public constructor(scope: constructs.Construct, id: string, props: CfnResourceProps = {}) { + super(scope, id, { + "type": CfnResource.CFN_RESOURCE_TYPE_NAME, + "properties": props + }); + + this.attrId = cdk.Token.asString(this.ref); + this.id = props.id; + } + + protected get cfnProperties(): Record { + return { + "id": this.id + }; + } + + /** + * Examines the CloudFormation resource and discloses attributes + * + * @param inspector tree inspector to collect and process attributes + */ + public inspect(inspector: cdk.TreeInspector): void { + inspector.addAttribute("aws:cdk:cloudformation:type", CfnResource.CFN_RESOURCE_TYPE_NAME); + inspector.addAttribute("aws:cdk:cloudformation:props", this.cfnProperties); + } + + protected renderProperties(props: Record): Record { + return convertCfnResourcePropsToCloudFormation(props); + } +} + +/** + * Properties for defining a \`CfnResource\` + * + * @struct + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export interface CfnResourceProps { + /** + * The identifier of the resource. + * + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html#cfn-some-resource-id + */ + readonly id?: string; +} + +/** + * Determine whether the given properties match those of a \`CfnResourceProps\` + * + * @param properties - the TypeScript properties of a \`CfnResourceProps\` + * + * @returns the result of the validation. + */ +// @ts-ignore TS6133 +function CfnResourcePropsValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) return cdk.VALIDATION_SUCCESS; + const errors = new cdk.ValidationResults(); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + errors.collect(new cdk.ValidationResult("Expected an object, but received: " + JSON.stringify(properties))); + } + errors.collect(cdk.propertyValidator("id", cdk.validateString)(properties.id)); + return errors.wrap("supplied properties not correct for \\"CfnResourceProps\\""); +} + +// @ts-ignore TS6133 +function convertCfnResourcePropsToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) return properties; + CfnResourcePropsValidator(properties).assertSuccess(); + return { + "Id": cdk.stringToCloudFormation(properties.id) + }; +} + +// @ts-ignore TS6133 +function CfnResourcePropsFromCloudFormation(properties: any): cfn_parse.FromCloudFormationResult { + if (cdk.isResolvableObject(properties)) { + return new cfn_parse.FromCloudFormationResult(properties); + } + properties = ((properties == null) ? {} : properties); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + return new cfn_parse.FromCloudFormationResult(properties); + } + const ret = new cfn_parse.FromCloudFormationPropertyObject(); + ret.addPropertyResult("id", "Id", (properties.Id != null ? cfn_parse.FromCloudFormation.getString(properties.Id) : undefined)); + ret.addUnrecognizedPropertiesAsExtra(properties); + return ret; +}" +`; diff --git a/tools/@aws-cdk/spec2cdk/test/resources.test.ts b/tools/@aws-cdk/spec2cdk/test/resources.test.ts new file mode 100644 index 0000000000000..db8c1cadb060c --- /dev/null +++ b/tools/@aws-cdk/spec2cdk/test/resources.test.ts @@ -0,0 +1,156 @@ +import { Service, SpecDatabase, emptyDatabase } from '@aws-cdk/service-spec-types'; +import { TypeScriptRenderer } from '@cdklabs/typewriter'; +import { AstBuilder } from '../lib/cdk/ast'; + +const renderer = new TypeScriptRenderer(); +let db: SpecDatabase; +let service: Service; + +beforeEach(async () => { + db = emptyDatabase(); + + service = db.allocate('service', { + name: 'aws-some', + shortName: 'some', + capitalized: 'Some', + cloudFormationNamespace: 'AWS::Some', + }); +}); + +test('resource interface when primaryIdentifier is a property', () => { + // GIVEN + const resource = db.allocate('resource', { + name: 'Resource', + primaryIdentifier: ['Id'], + attributes: {}, + properties: { + Id: { + type: { type: 'string' }, + documentation: 'The identifier of the resource', + }, + }, + cloudFormationType: 'AWS::Some::Resource', + }); + db.link('hasResource', service, resource); + + // THEN + const foundResource = db.lookup('resource', 'cloudFormationType', 'equals', 'AWS::Some::Resource').only(); + + const ast = AstBuilder.forResource(foundResource, { db }); + + const rendered = renderer.render(ast.module); + + expect(rendered).toMatchSnapshot(); +}); + +test('resource with optional primary identifier gets property from ref', () => { + // GIVEN + const resource = db.allocate('resource', { + name: 'Resource', + primaryIdentifier: ['Id'], + attributes: {}, + properties: { + Id: { + type: { type: 'string' }, + documentation: 'The identifier of the resource', + }, + }, + cloudFormationType: 'AWS::Some::Resource', + }); + db.link('hasResource', service, resource); + + // THEN + const foundResource = db.lookup('resource', 'cloudFormationType', 'equals', 'AWS::Some::Resource').only(); + + const ast = AstBuilder.forResource(foundResource, { db }); + + const rendered = renderer.render(ast.module); + + expect(rendered).toMatchSnapshot(); +}); + +test('resource with multiple primaryIdentifiers as properties', () => { + // GIVEN + const resource = db.allocate('resource', { + name: 'Resource', + primaryIdentifier: ['Id', 'AnotherId'], + attributes: {}, + properties: { + Id: { + type: { type: 'string' }, + documentation: 'The identifier of the resource', + }, + AnotherId: { + type: { type: 'string' }, + documentation: 'Another identifier of the resource', + }, + }, + cloudFormationType: 'AWS::Some::Resource', + }); + db.link('hasResource', service, resource); + + // THEN + const foundResource = db.lookup('resource', 'cloudFormationType', 'equals', 'AWS::Some::Resource').only(); + + const ast = AstBuilder.forResource(foundResource, { db }); + + const rendered = renderer.render(ast.module); + + expect(rendered).toMatchSnapshot(); +}); + +test('resource interface when primaryIdentifier is an attribute', () => { + // GIVEN + const resource = db.allocate('resource', { + name: 'Resource', + primaryIdentifier: ['Id'], + properties: {}, + attributes: { + Id: { + type: { type: 'string' }, + documentation: 'The identifier of the resource', + }, + }, + cloudFormationType: 'AWS::Some::Resource', + }); + db.link('hasResource', service, resource); + + // THEN + const foundResource = db.lookup('resource', 'cloudFormationType', 'equals', 'AWS::Some::Resource').only(); + + const ast = AstBuilder.forResource(foundResource, { db }); + + const rendered = renderer.render(ast.module); + + expect(rendered).toMatchSnapshot(); +}); + +test('resource interface with multiple primaryIdentifiers', () => { + // GIVEN + const resource = db.allocate('resource', { + name: 'Resource', + primaryIdentifier: ['Id', 'Another'], + properties: {}, + attributes: { + Id: { + type: { type: 'string' }, + documentation: 'The identifier of the resource', + }, + Another: { + type: { type: 'string' }, + documentation: 'Another identifier of the resource', + }, + }, + cloudFormationType: 'AWS::Some::Resource', + }); + db.link('hasResource', service, resource); + + // THEN + const foundResource = db.lookup('resource', 'cloudFormationType', 'equals', 'AWS::Some::Resource').only(); + + const ast = AstBuilder.forResource(foundResource, { db }); + + const rendered = renderer.render(ast.module); + + expect(rendered).toMatchSnapshot(); +}); From 9dd8eba7920c3daf9f002019621913f51103d50d Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Tue, 22 Jul 2025 17:04:25 +0100 Subject: [PATCH 02/26] Oops --- tools/@aws-cdk/spec2cdk/lib/cli/cli.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tools/@aws-cdk/spec2cdk/lib/cli/cli.ts b/tools/@aws-cdk/spec2cdk/lib/cli/cli.ts index 30e47c157689b..51a50d167f001 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cli/cli.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cli/cli.ts @@ -143,11 +143,3 @@ function stringOr(pat: unknown, def: string) { } return pat; } - -async function run() { - await generateAll({ - outputPath: '/Users/otaviom/construct-harmony', - }); -} -// eslint-disable-next-line no-console -run().catch(console.log); From bef585b0aed87ea2df1902e5038fc910fac09da8 Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Wed, 23 Jul 2025 09:02:37 +0100 Subject: [PATCH 03/26] Updated snapshot --- .../spec2cdk/test/__snapshots__/resources.test.ts.snap | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap index 8759d134e1d67..9a9594c4b5c75 100644 --- a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap +++ b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap @@ -8,7 +8,7 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Attributes for \`CfnResource\`. + * Attributes to reference a \`CfnResource\`. * * @stability external */ @@ -173,7 +173,7 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Attributes for \`CfnResource\`. + * Attributes to reference a \`CfnResource\`. * * @stability external */ @@ -319,7 +319,7 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Attributes for \`CfnResource\`. + * Attributes to reference a \`CfnResource\`. * * @stability external */ @@ -480,7 +480,7 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Attributes for \`CfnResource\`. + * Attributes to reference a \`CfnResource\`. * * @stability external */ @@ -679,7 +679,7 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Attributes for \`CfnResource\`. + * Attributes to reference a \`CfnResource\`. * * @stability external */ From 3713f102e37dbea20734345fe9d0ed0ca32f5e8e Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Wed, 23 Jul 2025 14:18:55 +0100 Subject: [PATCH 04/26] itemId --- scripts/prioritization/assign-r5-priority.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/prioritization/assign-r5-priority.js b/scripts/prioritization/assign-r5-priority.js index 3c3204ae36edf..9ac7eb47a6c49 100644 --- a/scripts/prioritization/assign-r5-priority.js +++ b/scripts/prioritization/assign-r5-priority.js @@ -140,7 +140,7 @@ module.exports = async ({ github }) => { updateProjectDateField({ github, projectId: PROJECT_CONFIG.projectId, - itemId: itemId, + itemId: addResult.addProjectV2ItemById.item.id, fieldId: PROJECT_CONFIG.addedOnFieldId, date: new Date().toISOString(), }) From 1dcfbd859aecd74813a832f097c193793c9809f3 Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Wed, 23 Jul 2025 14:51:30 +0100 Subject: [PATCH 05/26] feat: add ARN attribute to common resource interface --- .../spec2cdk/lib/cdk/resource-class.ts | 8 + .../spec2cdk/lib/cdk/resource-decider.ts | 24 +- .../test/__snapshots__/resources.test.ts.snap | 631 ++++++++++++++++++ .../@aws-cdk/spec2cdk/test/resources.test.ts | 117 ++++ 4 files changed, 779 insertions(+), 1 deletion(-) diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts index 0f61ca274c812..75bb47900f503 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts @@ -127,6 +127,14 @@ export class ResourceClass extends ClassType { }); } + // Add the arn too, unless it is duplicated in the resourceIdentifier already + if (this.decider.arn && this.resourceInterface.properties.every((p) => p.name !== this.decider.arn!.name)) { + this.resourceInterface.addProperty({ + ...this.decider.arn, + immutable: true, + }); + } + // Build the members of this class this.addProperty({ name: staticResourceTypeName(), diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts index e304709a186fd..1bc1aaf63f5aa 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts @@ -5,7 +5,7 @@ import { PropertyMapping } from './cloudformation-mapping'; import { NON_RESOLVABLE_PROPERTY_NAMES, TaggabilityStyle, resourceTaggabilityStyle } from './tagging'; import { TypeConverter } from './type-converter'; import { attributePropertyName, cloudFormationDocLink, propertyNameFromCloudFormation } from '../naming'; -import { splitDocumentation } from '../util'; +import { log, splitDocumentation } from '../util'; // This convenience typewriter builder is used all over the place const $this = $E(expr.this_()); @@ -28,6 +28,10 @@ export class ResourceDecider { private readonly taggability?: TaggabilityStyle; + /** + * The arn returned by the resource, if applicable. + */ + public readonly arn?: PropertySpec; public readonly primaryIdentifier = new Array(); public readonly propsProperties = new Array(); public readonly classProperties = new Array(); @@ -40,6 +44,12 @@ export class ResourceDecider { this.convertAttributes(); this.convertPrimaryIdentifier(); + this.arn = this.findArn(); + + const arn = this.findArn(); + if (arn && arn.name !== 'attrArn') { + log.info(`"${this.resource.cloudFormationType}.${this.resource.name}": "${arn.name}",`); + } this.propsProperties.sort((p1, p2) => p1.propertySpec.name.localeCompare(p2.propertySpec.name)); this.classProperties.sort((p1, p2) => p1.propertySpec.name.localeCompare(p2.propertySpec.name)); @@ -65,6 +75,18 @@ export class ResourceDecider { } } + private findArn() { + // A list of possible names for the arn, in order of importance. + // This is relevant because some resources, like AWS::VpcLattice::AccessLogSubscription + // has both `Arn` and `ResourceArn`, and we want to select the `Arn` property. + const possibleArnNames = ['Arn', `${this.resource.name}Arn`]; + for (const arn of possibleArnNames) { + const att = this.classAttributeProperties.find((a) => a.propertySpec.name === attributePropertyName(arn)); + if (att) { return att.propertySpec; } + } + return; + } + private convertPrimaryIdentifier() { if (this.resource.primaryIdentifier === undefined) { return; } for (let i = 0; i < (this.resource.primaryIdentifier).length; i++) { diff --git a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap index 9a9594c4b5c75..c6475ba4f68da 100644 --- a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap +++ b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap @@ -311,6 +311,637 @@ function CfnResourcePropsFromCloudFormation(properties: any): cfn_parse.FromClou }" `; +exports[`resource interface with "Arn" 1`] = ` +"/* eslint-disable prettier/prettier, @stylistic/max-len */ +import * as cdk from "aws-cdk-lib"; +import * as constructs from "constructs"; +import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; +import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; + +/** + * Attributes to reference a \`CfnSomething\`. + * + * @stability external + */ +export interface ICfnSomething extends constructs.IConstruct { + /** + * The identifier of the resource + * + * @cloudformationAttribute Id + */ + readonly attrId: string; + + /** + * The arn for something + * + * @cloudformationAttribute SomethingArn + */ + readonly attrSomethingArn: string; +} + +/** + * @cloudformationResource AWS::Some::Something + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-something.html + */ +export class CfnSomething extends cdk.CfnResource implements cdk.IInspectable, ICfnSomething { + /** + * The CloudFormation resource type name for this resource class. + */ + public static readonly CFN_RESOURCE_TYPE_NAME: string = "AWS::Some::Something"; + + /** + * Build a CfnSomething from CloudFormation properties + * + * A factory method that creates a new instance of this class from an object + * containing the CloudFormation properties of this resource. + * Used in the @aws-cdk/cloudformation-include module. + * + * @internal + */ + public static _fromCloudFormation(scope: constructs.Construct, id: string, resourceAttributes: any, options: cfn_parse.FromCloudFormationOptions): CfnSomething { + resourceAttributes = resourceAttributes || {}; + const resourceProperties = options.parser.parseValue(resourceAttributes.Properties); + const propsResult = CfnSomethingPropsFromCloudFormation(resourceProperties); + if (cdk.isResolvableObject(propsResult.value)) { + throw new cdk_errors.ValidationError("Unexpected IResolvable", scope); + } + const ret = new CfnSomething(scope, id, propsResult.value); + for (const [propKey, propVal] of Object.entries(propsResult.extraProperties)) { + ret.addPropertyOverride(propKey, propVal); + } + options.parser.handleAttributes(ret, resourceAttributes, id); + return ret; + } + + /** + * The identifier of the resource + * + * @cloudformationAttribute Id + */ + public readonly attrId: string; + + /** + * The arn for something + * + * @cloudformationAttribute SomethingArn + */ + public readonly attrSomethingArn: string; + + /** + * @param scope Scope in which this resource is defined + * @param id Construct identifier for this resource (unique in its scope) + * @param props Resource properties + */ + public constructor(scope: constructs.Construct, id: string, props: CfnSomethingProps = {}) { + super(scope, id, { + "type": CfnSomething.CFN_RESOURCE_TYPE_NAME, + "properties": props + }); + + this.attrId = cdk.Token.asString(this.getAtt("Id", cdk.ResolutionTypeHint.STRING)); + this.attrSomethingArn = cdk.Token.asString(this.getAtt("SomethingArn", cdk.ResolutionTypeHint.STRING)); + } + + protected get cfnProperties(): Record { + return {}; + } + + /** + * Examines the CloudFormation resource and discloses attributes + * + * @param inspector tree inspector to collect and process attributes + */ + public inspect(inspector: cdk.TreeInspector): void { + inspector.addAttribute("aws:cdk:cloudformation:type", CfnSomething.CFN_RESOURCE_TYPE_NAME); + inspector.addAttribute("aws:cdk:cloudformation:props", this.cfnProperties); + } + + protected renderProperties(props: Record): Record { + return convertCfnSomethingPropsToCloudFormation(props); + } +} + +/** + * Properties for defining a \`CfnSomething\` + * + * @struct + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-something.html + */ +export interface CfnSomethingProps { + +} + +/** + * Determine whether the given properties match those of a \`CfnSomethingProps\` + * + * @param properties - the TypeScript properties of a \`CfnSomethingProps\` + * + * @returns the result of the validation. + */ +// @ts-ignore TS6133 +function CfnSomethingPropsValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) return cdk.VALIDATION_SUCCESS; + const errors = new cdk.ValidationResults(); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + errors.collect(new cdk.ValidationResult("Expected an object, but received: " + JSON.stringify(properties))); + } + return errors.wrap("supplied properties not correct for \\"CfnSomethingProps\\""); +} + +// @ts-ignore TS6133 +function convertCfnSomethingPropsToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) return properties; + CfnSomethingPropsValidator(properties).assertSuccess(); + return {}; +} + +// @ts-ignore TS6133 +function CfnSomethingPropsFromCloudFormation(properties: any): cfn_parse.FromCloudFormationResult { + if (cdk.isResolvableObject(properties)) { + return new cfn_parse.FromCloudFormationResult(properties); + } + properties = ((properties == null) ? {} : properties); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + return new cfn_parse.FromCloudFormationResult(properties); + } + const ret = new cfn_parse.FromCloudFormationPropertyObject(); + ret.addUnrecognizedPropertiesAsExtra(properties); + return ret; +}" +`; + +exports[`resource interface with "Arn" 1`] = ` +"/* eslint-disable prettier/prettier, @stylistic/max-len */ +import * as cdk from "aws-cdk-lib"; +import * as constructs from "constructs"; +import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; +import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; + +/** + * Attributes to reference a \`CfnResource\`. + * + * @stability external + */ +export interface ICfnResource extends constructs.IConstruct { + /** + * The identifier of the resource + * + * @cloudformationAttribute Id + */ + readonly attrId: string; + + /** + * The arn for the resource + * + * @cloudformationAttribute Arn + */ + readonly attrArn: string; +} + +/** + * @cloudformationResource AWS::Some::Resource + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { + /** + * The CloudFormation resource type name for this resource class. + */ + public static readonly CFN_RESOURCE_TYPE_NAME: string = "AWS::Some::Resource"; + + /** + * Build a CfnResource from CloudFormation properties + * + * A factory method that creates a new instance of this class from an object + * containing the CloudFormation properties of this resource. + * Used in the @aws-cdk/cloudformation-include module. + * + * @internal + */ + public static _fromCloudFormation(scope: constructs.Construct, id: string, resourceAttributes: any, options: cfn_parse.FromCloudFormationOptions): CfnResource { + resourceAttributes = resourceAttributes || {}; + const resourceProperties = options.parser.parseValue(resourceAttributes.Properties); + const propsResult = CfnResourcePropsFromCloudFormation(resourceProperties); + if (cdk.isResolvableObject(propsResult.value)) { + throw new cdk_errors.ValidationError("Unexpected IResolvable", scope); + } + const ret = new CfnResource(scope, id, propsResult.value); + for (const [propKey, propVal] of Object.entries(propsResult.extraProperties)) { + ret.addPropertyOverride(propKey, propVal); + } + options.parser.handleAttributes(ret, resourceAttributes, id); + return ret; + } + + /** + * The arn for the resource + * + * @cloudformationAttribute Arn + */ + public readonly attrArn: string; + + /** + * The identifier of the resource + * + * @cloudformationAttribute Id + */ + public readonly attrId: string; + + /** + * @param scope Scope in which this resource is defined + * @param id Construct identifier for this resource (unique in its scope) + * @param props Resource properties + */ + public constructor(scope: constructs.Construct, id: string, props: CfnResourceProps = {}) { + super(scope, id, { + "type": CfnResource.CFN_RESOURCE_TYPE_NAME, + "properties": props + }); + + this.attrArn = cdk.Token.asString(this.getAtt("Arn", cdk.ResolutionTypeHint.STRING)); + this.attrId = cdk.Token.asString(this.getAtt("Id", cdk.ResolutionTypeHint.STRING)); + } + + protected get cfnProperties(): Record { + return {}; + } + + /** + * Examines the CloudFormation resource and discloses attributes + * + * @param inspector tree inspector to collect and process attributes + */ + public inspect(inspector: cdk.TreeInspector): void { + inspector.addAttribute("aws:cdk:cloudformation:type", CfnResource.CFN_RESOURCE_TYPE_NAME); + inspector.addAttribute("aws:cdk:cloudformation:props", this.cfnProperties); + } + + protected renderProperties(props: Record): Record { + return convertCfnResourcePropsToCloudFormation(props); + } +} + +/** + * Properties for defining a \`CfnResource\` + * + * @struct + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export interface CfnResourceProps { + +} + +/** + * Determine whether the given properties match those of a \`CfnResourceProps\` + * + * @param properties - the TypeScript properties of a \`CfnResourceProps\` + * + * @returns the result of the validation. + */ +// @ts-ignore TS6133 +function CfnResourcePropsValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) return cdk.VALIDATION_SUCCESS; + const errors = new cdk.ValidationResults(); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + errors.collect(new cdk.ValidationResult("Expected an object, but received: " + JSON.stringify(properties))); + } + return errors.wrap("supplied properties not correct for \\"CfnResourceProps\\""); +} + +// @ts-ignore TS6133 +function convertCfnResourcePropsToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) return properties; + CfnResourcePropsValidator(properties).assertSuccess(); + return {}; +} + +// @ts-ignore TS6133 +function CfnResourcePropsFromCloudFormation(properties: any): cfn_parse.FromCloudFormationResult { + if (cdk.isResolvableObject(properties)) { + return new cfn_parse.FromCloudFormationResult(properties); + } + properties = ((properties == null) ? {} : properties); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + return new cfn_parse.FromCloudFormationResult(properties); + } + const ret = new cfn_parse.FromCloudFormationPropertyObject(); + ret.addUnrecognizedPropertiesAsExtra(properties); + return ret; +}" +`; + +exports[`resource interface with Arn as a property and not a primaryIdentifier 1`] = ` +"/* eslint-disable prettier/prettier, @stylistic/max-len */ +import * as cdk from "aws-cdk-lib"; +import * as constructs from "constructs"; +import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; +import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; + +/** + * Attributes to reference a \`CfnResource\`. + * + * @stability external + */ +export interface ICfnResource extends constructs.IConstruct { + /** + * The identifier of the resource + * + * @cloudformationAttribute Id + */ + readonly attrId: string; +} + +/** + * @cloudformationResource AWS::Some::Resource + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { + /** + * The CloudFormation resource type name for this resource class. + */ + public static readonly CFN_RESOURCE_TYPE_NAME: string = "AWS::Some::Resource"; + + /** + * Build a CfnResource from CloudFormation properties + * + * A factory method that creates a new instance of this class from an object + * containing the CloudFormation properties of this resource. + * Used in the @aws-cdk/cloudformation-include module. + * + * @internal + */ + public static _fromCloudFormation(scope: constructs.Construct, id: string, resourceAttributes: any, options: cfn_parse.FromCloudFormationOptions): CfnResource { + resourceAttributes = resourceAttributes || {}; + const resourceProperties = options.parser.parseValue(resourceAttributes.Properties); + const propsResult = CfnResourcePropsFromCloudFormation(resourceProperties); + if (cdk.isResolvableObject(propsResult.value)) { + throw new cdk_errors.ValidationError("Unexpected IResolvable", scope); + } + const ret = new CfnResource(scope, id, propsResult.value); + for (const [propKey, propVal] of Object.entries(propsResult.extraProperties)) { + ret.addPropertyOverride(propKey, propVal); + } + options.parser.handleAttributes(ret, resourceAttributes, id); + return ret; + } + + /** + * The identifier of the resource + * + * @cloudformationAttribute Id + */ + public readonly attrId: string; + + /** + * The arn for the resource. + */ + public arn?: string; + + /** + * @param scope Scope in which this resource is defined + * @param id Construct identifier for this resource (unique in its scope) + * @param props Resource properties + */ + public constructor(scope: constructs.Construct, id: string, props: CfnResourceProps = {}) { + super(scope, id, { + "type": CfnResource.CFN_RESOURCE_TYPE_NAME, + "properties": props + }); + + this.attrId = cdk.Token.asString(this.getAtt("Id", cdk.ResolutionTypeHint.STRING)); + this.arn = props.arn; + } + + protected get cfnProperties(): Record { + return { + "arn": this.arn + }; + } + + /** + * Examines the CloudFormation resource and discloses attributes + * + * @param inspector tree inspector to collect and process attributes + */ + public inspect(inspector: cdk.TreeInspector): void { + inspector.addAttribute("aws:cdk:cloudformation:type", CfnResource.CFN_RESOURCE_TYPE_NAME); + inspector.addAttribute("aws:cdk:cloudformation:props", this.cfnProperties); + } + + protected renderProperties(props: Record): Record { + return convertCfnResourcePropsToCloudFormation(props); + } +} + +/** + * Properties for defining a \`CfnResource\` + * + * @struct + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export interface CfnResourceProps { + /** + * The arn for the resource. + * + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html#cfn-some-resource-arn + */ + readonly arn?: string; +} + +/** + * Determine whether the given properties match those of a \`CfnResourceProps\` + * + * @param properties - the TypeScript properties of a \`CfnResourceProps\` + * + * @returns the result of the validation. + */ +// @ts-ignore TS6133 +function CfnResourcePropsValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) return cdk.VALIDATION_SUCCESS; + const errors = new cdk.ValidationResults(); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + errors.collect(new cdk.ValidationResult("Expected an object, but received: " + JSON.stringify(properties))); + } + errors.collect(cdk.propertyValidator("arn", cdk.validateString)(properties.arn)); + return errors.wrap("supplied properties not correct for \\"CfnResourceProps\\""); +} + +// @ts-ignore TS6133 +function convertCfnResourcePropsToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) return properties; + CfnResourcePropsValidator(properties).assertSuccess(); + return { + "Arn": cdk.stringToCloudFormation(properties.arn) + }; +} + +// @ts-ignore TS6133 +function CfnResourcePropsFromCloudFormation(properties: any): cfn_parse.FromCloudFormationResult { + if (cdk.isResolvableObject(properties)) { + return new cfn_parse.FromCloudFormationResult(properties); + } + properties = ((properties == null) ? {} : properties); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + return new cfn_parse.FromCloudFormationResult(properties); + } + const ret = new cfn_parse.FromCloudFormationPropertyObject(); + ret.addPropertyResult("arn", "Arn", (properties.Arn != null ? cfn_parse.FromCloudFormation.getString(properties.Arn) : undefined)); + ret.addUnrecognizedPropertiesAsExtra(properties); + return ret; +}" +`; + +exports[`resource interface with Arn as primaryIdentifier 1`] = ` +"/* eslint-disable prettier/prettier, @stylistic/max-len */ +import * as cdk from "aws-cdk-lib"; +import * as constructs from "constructs"; +import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; +import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; + +/** + * Attributes to reference a \`CfnResource\`. + * + * @stability external + */ +export interface ICfnResource extends constructs.IConstruct { + /** + * The arn of the resource + * + * @cloudformationAttribute Arn + */ + readonly attrArn: string; +} + +/** + * @cloudformationResource AWS::Some::Resource + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { + /** + * The CloudFormation resource type name for this resource class. + */ + public static readonly CFN_RESOURCE_TYPE_NAME: string = "AWS::Some::Resource"; + + /** + * Build a CfnResource from CloudFormation properties + * + * A factory method that creates a new instance of this class from an object + * containing the CloudFormation properties of this resource. + * Used in the @aws-cdk/cloudformation-include module. + * + * @internal + */ + public static _fromCloudFormation(scope: constructs.Construct, id: string, resourceAttributes: any, options: cfn_parse.FromCloudFormationOptions): CfnResource { + resourceAttributes = resourceAttributes || {}; + const resourceProperties = options.parser.parseValue(resourceAttributes.Properties); + const propsResult = CfnResourcePropsFromCloudFormation(resourceProperties); + if (cdk.isResolvableObject(propsResult.value)) { + throw new cdk_errors.ValidationError("Unexpected IResolvable", scope); + } + const ret = new CfnResource(scope, id, propsResult.value); + for (const [propKey, propVal] of Object.entries(propsResult.extraProperties)) { + ret.addPropertyOverride(propKey, propVal); + } + options.parser.handleAttributes(ret, resourceAttributes, id); + return ret; + } + + /** + * The arn of the resource + * + * @cloudformationAttribute Arn + */ + public readonly attrArn: string; + + /** + * @param scope Scope in which this resource is defined + * @param id Construct identifier for this resource (unique in its scope) + * @param props Resource properties + */ + public constructor(scope: constructs.Construct, id: string, props: CfnResourceProps = {}) { + super(scope, id, { + "type": CfnResource.CFN_RESOURCE_TYPE_NAME, + "properties": props + }); + + this.attrArn = cdk.Token.asString(this.getAtt("Arn", cdk.ResolutionTypeHint.STRING)); + } + + protected get cfnProperties(): Record { + return {}; + } + + /** + * Examines the CloudFormation resource and discloses attributes + * + * @param inspector tree inspector to collect and process attributes + */ + public inspect(inspector: cdk.TreeInspector): void { + inspector.addAttribute("aws:cdk:cloudformation:type", CfnResource.CFN_RESOURCE_TYPE_NAME); + inspector.addAttribute("aws:cdk:cloudformation:props", this.cfnProperties); + } + + protected renderProperties(props: Record): Record { + return convertCfnResourcePropsToCloudFormation(props); + } +} + +/** + * Properties for defining a \`CfnResource\` + * + * @struct + * @stability external + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html + */ +export interface CfnResourceProps { + +} + +/** + * Determine whether the given properties match those of a \`CfnResourceProps\` + * + * @param properties - the TypeScript properties of a \`CfnResourceProps\` + * + * @returns the result of the validation. + */ +// @ts-ignore TS6133 +function CfnResourcePropsValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) return cdk.VALIDATION_SUCCESS; + const errors = new cdk.ValidationResults(); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + errors.collect(new cdk.ValidationResult("Expected an object, but received: " + JSON.stringify(properties))); + } + return errors.wrap("supplied properties not correct for \\"CfnResourceProps\\""); +} + +// @ts-ignore TS6133 +function convertCfnResourcePropsToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) return properties; + CfnResourcePropsValidator(properties).assertSuccess(); + return {}; +} + +// @ts-ignore TS6133 +function CfnResourcePropsFromCloudFormation(properties: any): cfn_parse.FromCloudFormationResult { + if (cdk.isResolvableObject(properties)) { + return new cfn_parse.FromCloudFormationResult(properties); + } + properties = ((properties == null) ? {} : properties); + if (!(properties && typeof properties == 'object' && !Array.isArray(properties))) { + return new cfn_parse.FromCloudFormationResult(properties); + } + const ret = new cfn_parse.FromCloudFormationPropertyObject(); + ret.addUnrecognizedPropertiesAsExtra(properties); + return ret; +}" +`; + exports[`resource interface with multiple primaryIdentifiers 1`] = ` "/* eslint-disable prettier/prettier, @stylistic/max-len */ import * as cdk from "aws-cdk-lib"; diff --git a/tools/@aws-cdk/spec2cdk/test/resources.test.ts b/tools/@aws-cdk/spec2cdk/test/resources.test.ts index db8c1cadb060c..ca0d00b771f75 100644 --- a/tools/@aws-cdk/spec2cdk/test/resources.test.ts +++ b/tools/@aws-cdk/spec2cdk/test/resources.test.ts @@ -154,3 +154,120 @@ test('resource interface with multiple primaryIdentifiers', () => { expect(rendered).toMatchSnapshot(); }); + +test('resource interface with "Arn"', () => { + // GIVEN + const resource = db.allocate('resource', { + name: 'Resource', + primaryIdentifier: ['Id'], + properties: {}, + attributes: { + Id: { + type: { type: 'string' }, + documentation: 'The identifier of the resource', + }, + Arn: { + type: { type: 'string' }, + documentation: 'The arn for the resource', + }, + }, + cloudFormationType: 'AWS::Some::Resource', + }); + db.link('hasResource', service, resource); + + // THEN + const foundResource = db.lookup('resource', 'cloudFormationType', 'equals', 'AWS::Some::Resource').only(); + + const ast = AstBuilder.forResource(foundResource, { db }); + + const rendered = renderer.render(ast.module); + + expect(rendered).toMatchSnapshot(); +}); + +test('resource interface with "Arn"', () => { + // GIVEN + const resource = db.allocate('resource', { + name: 'Something', + primaryIdentifier: ['Id'], + properties: {}, + attributes: { + Id: { + type: { type: 'string' }, + documentation: 'The identifier of the resource', + }, + SomethingArn: { + type: { type: 'string' }, + documentation: 'The arn for something', + }, + }, + cloudFormationType: 'AWS::Some::Something', + }); + db.link('hasResource', service, resource); + + // THEN + const foundResource = db.lookup('resource', 'cloudFormationType', 'equals', 'AWS::Some::Something').only(); + + const ast = AstBuilder.forResource(foundResource, { db }); + + const rendered = renderer.render(ast.module); + + expect(rendered).toMatchSnapshot(); +}); + +test('resource interface with Arn as a property and not a primaryIdentifier', () => { + // GIVEN + const resource = db.allocate('resource', { + name: 'Resource', + primaryIdentifier: ['Id'], + properties: { + Arn: { + type: { type: 'string' }, + documentation: 'The arn for the resource', + }, + }, + attributes: { + Id: { + type: { type: 'string' }, + documentation: 'The identifier of the resource', + }, + }, + cloudFormationType: 'AWS::Some::Resource', + }); + db.link('hasResource', service, resource); + + // THEN + const foundResource = db.lookup('resource', 'cloudFormationType', 'equals', 'AWS::Some::Resource').only(); + + const ast = AstBuilder.forResource(foundResource, { db }); + + const rendered = renderer.render(ast.module); + + expect(rendered).toMatchSnapshot(); +}); + +test('resource interface with Arn as primaryIdentifier', () => { + // GIVEN + const resource = db.allocate('resource', { + name: 'Resource', + primaryIdentifier: ['Arn'], + properties: {}, + attributes: { + Arn: { + type: { type: 'string' }, + documentation: 'The arn of the resource', + }, + }, + cloudFormationType: 'AWS::Some::Resource', + }); + db.link('hasResource', service, resource); + + // THEN + const foundResource = db.lookup('resource', 'cloudFormationType', 'equals', 'AWS::Some::Resource').only(); + + const ast = AstBuilder.forResource(foundResource, { db }); + + const rendered = renderer.render(ast.module); + + expect(rendered).toMatchSnapshot(); +}); From b00f7bc6e6c85f73115e0819c20bf1d7556aebe1 Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Wed, 23 Jul 2025 14:55:42 +0100 Subject: [PATCH 06/26] Removed debug code --- tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts index 1bc1aaf63f5aa..aac0be5d2b535 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts @@ -5,7 +5,7 @@ import { PropertyMapping } from './cloudformation-mapping'; import { NON_RESOLVABLE_PROPERTY_NAMES, TaggabilityStyle, resourceTaggabilityStyle } from './tagging'; import { TypeConverter } from './type-converter'; import { attributePropertyName, cloudFormationDocLink, propertyNameFromCloudFormation } from '../naming'; -import { log, splitDocumentation } from '../util'; +import { splitDocumentation } from '../util'; // This convenience typewriter builder is used all over the place const $this = $E(expr.this_()); @@ -46,11 +46,6 @@ export class ResourceDecider { this.convertPrimaryIdentifier(); this.arn = this.findArn(); - const arn = this.findArn(); - if (arn && arn.name !== 'attrArn') { - log.info(`"${this.resource.cloudFormationType}.${this.resource.name}": "${arn.name}",`); - } - this.propsProperties.sort((p1, p2) => p1.propertySpec.name.localeCompare(p2.propertySpec.name)); this.classProperties.sort((p1, p2) => p1.propertySpec.name.localeCompare(p2.propertySpec.name)); this.classAttributeProperties.sort((p1, p2) => p1.propertySpec.name.localeCompare(p2.propertySpec.name)); From accce4002bdf48db4d5ada3af22880777fcbc281 Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Thu, 7 Aug 2025 16:41:22 +0100 Subject: [PATCH 07/26] Skip composite primary identifiers --- .../spec2cdk/lib/cdk/resource-decider.ts | 9 +++--- .../test/__snapshots__/resources.test.ts.snap | 32 ------------------- 2 files changed, 4 insertions(+), 37 deletions(-) diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts index aac0be5d2b535..cf6f0ca995ba9 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts @@ -10,9 +10,6 @@ import { splitDocumentation } from '../util'; // This convenience typewriter builder is used all over the place const $this = $E(expr.this_()); -// This convenience typewriter builder is used for cloudformation intrinsics -const $Fn = $E(expr.directCode('cdk.Fn')); - /** * Decide how properties get mapped between model types, Typescript types, and CloudFormation */ @@ -97,10 +94,12 @@ export class ResourceDecider { // Create initializer for new attribute, if possible let initializer: Expression | undefined = undefined; if (propSpec.type === Type.STRING) { // handling only this case for now + // The fact that a property is part of a primary identifier does not necessarily imply that it can be read. + // Example: AWS::ApiGateway::RequestValidator has a primary identifier composed of + // [ "/properties/RestApiId", "/properties/RequestValidatorId" ]. But Ref only returns the validator ID. + // Handling only the case where the primary identifier is a single property, which is the most common case. if (this.resource.primaryIdentifier!.length === 1) { initializer = CDK_CORE.tokenAsString($this.ref); - } else { - initializer = CDK_CORE.tokenAsString($Fn.select(expr.lit(i), $Fn.split(expr.lit('|'), $this.ref))); } } diff --git a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap index c6475ba4f68da..881c6316a5a63 100644 --- a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap +++ b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap @@ -1116,21 +1116,7 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; * @stability external */ export interface ICfnResource extends constructs.IConstruct { - /** - * The identifier of the resource. - * This property gets determined after the resource is created. - * - * @cloudformationAttribute Ref - */ - readonly attrId: string; - /** - * Another identifier of the resource. - * This property gets determined after the resource is created. - * - * @cloudformationAttribute Ref - */ - readonly attrAnotherId: string; } /** @@ -1168,22 +1154,6 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IC return ret; } - /** - * Another identifier of the resource. - * This property gets determined after the resource is created. - * - * @cloudformationAttribute Ref - */ - public readonly attrAnotherId: string; - - /** - * The identifier of the resource. - * This property gets determined after the resource is created. - * - * @cloudformationAttribute Ref - */ - public readonly attrId: string; - /** * Another identifier of the resource. */ @@ -1205,8 +1175,6 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IC "properties": props }); - this.attrAnotherId = cdk.Token.asString(cdk.Fn.select(1, cdk.Fn.split("|", this.ref))); - this.attrId = cdk.Token.asString(cdk.Fn.select(0, cdk.Fn.split("|", this.ref))); this.anotherId = props.anotherId; this.id = props.id; } From 9f96725d63275e7873d30bd195ecc25d776893b5 Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Mon, 11 Aug 2025 09:49:16 +0100 Subject: [PATCH 08/26] Revert scripts/prioritization/assign-r5-priority.js --- scripts/prioritization/assign-r5-priority.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/prioritization/assign-r5-priority.js b/scripts/prioritization/assign-r5-priority.js index 9ac7eb47a6c49..3c3204ae36edf 100644 --- a/scripts/prioritization/assign-r5-priority.js +++ b/scripts/prioritization/assign-r5-priority.js @@ -140,7 +140,7 @@ module.exports = async ({ github }) => { updateProjectDateField({ github, projectId: PROJECT_CONFIG.projectId, - itemId: addResult.addProjectV2ItemById.item.id, + itemId: itemId, fieldId: PROJECT_CONFIG.addedOnFieldId, date: new Date().toISOString(), }) From 62bdc7621b7ab71ed20269f54321541d62eeac20 Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Mon, 11 Aug 2025 11:04:24 +0100 Subject: [PATCH 09/26] Remove `Construct` from the parents of the generated interfaces --- .../spec2cdk/lib/cdk/resource-class.ts | 1 - .../test/__snapshots__/resources.test.ts.snap | 18 +++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts index 75bb47900f503..d60da8d0a855c 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts @@ -65,7 +65,6 @@ export class ResourceClass extends ClassType { summary: `Attributes to reference a \`${classNameFromResource(resource)}\`.`, stability: Stability.External, }, - extends: [CONSTRUCTS.IConstruct], }); super(scope, { diff --git a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap index 881c6316a5a63..fdc325860b02d 100644 --- a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap +++ b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap @@ -12,7 +12,7 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; * * @stability external */ -export interface ICfnResource extends constructs.IConstruct { +export interface ICfnResource { /** * The identifier of the resource. * This property gets determined after the resource is created. @@ -177,7 +177,7 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; * * @stability external */ -export interface ICfnResource extends constructs.IConstruct { +export interface ICfnResource { /** * The identifier of the resource * @@ -323,7 +323,7 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; * * @stability external */ -export interface ICfnSomething extends constructs.IConstruct { +export interface ICfnSomething { /** * The identifier of the resource * @@ -484,7 +484,7 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; * * @stability external */ -export interface ICfnResource extends constructs.IConstruct { +export interface ICfnResource { /** * The identifier of the resource * @@ -645,7 +645,7 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; * * @stability external */ -export interface ICfnResource extends constructs.IConstruct { +export interface ICfnResource { /** * The identifier of the resource * @@ -808,7 +808,7 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; * * @stability external */ -export interface ICfnResource extends constructs.IConstruct { +export interface ICfnResource { /** * The arn of the resource * @@ -954,7 +954,7 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; * * @stability external */ -export interface ICfnResource extends constructs.IConstruct { +export interface ICfnResource { /** * The identifier of the resource * @@ -1115,7 +1115,7 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; * * @stability external */ -export interface ICfnResource extends constructs.IConstruct { +export interface ICfnResource { } @@ -1282,7 +1282,7 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; * * @stability external */ -export interface ICfnResource extends constructs.IConstruct { +export interface ICfnResource { /** * The identifier of the resource. * This property gets determined after the resource is created. From 40fb819cac0fffc74a6f1c0e97a733512532d37c Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Tue, 12 Aug 2025 09:56:47 +0100 Subject: [PATCH 10/26] Exclude the 'construct-interface-extends-iconstruct' rule for the ICfn* interfaces --- .../@aws-cdk/cdk-build-tools/bin/cdk-awslint | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tools/@aws-cdk/cdk-build-tools/bin/cdk-awslint b/tools/@aws-cdk/cdk-build-tools/bin/cdk-awslint index ea9cac3495e6b..7c1c8c178d125 100755 --- a/tools/@aws-cdk/cdk-build-tools/bin/cdk-awslint +++ b/tools/@aws-cdk/cdk-build-tools/bin/cdk-awslint @@ -1,2 +1,48 @@ #!/usr/bin/env node + +/* +For every L1 construct, we generate a corresponding resource reference interface which it inherits. For example, +CfnManagedPolicy extends ICfnManagedPolicy. The ICfn* interfaces are meant to also be extended by L2 interfaces. +Although most L2 interfaces extend IConstruct, not all of them do. A case in point is IManagedPolicy, that can't extend +IConstruct because it would be impossible to produce an instance of it using ManagedPolicy.fromAwsManagedPolicyName(), +since it doesn't take a construct scope as a parameter. Therefore, the ICfn* interfaces cannot extend IConstruct if we +want to cover these cases. + +Before calling awslint, we are excluding the 'construct-interface-extends-iconstruct' rule for the ICfn* interfaces. + */ + +const fs = require('fs'); +const path = require('path'); + +// Get all AWS modules from aws-cdk-lib +function getAwsModules() { + const cdkLibPath = path.resolve(__dirname, '../../../../packages/aws-cdk-lib'); + const entries = fs.readdirSync(cdkLibPath, { withFileTypes: true }); + + return entries + .filter(entry => entry.isDirectory() && entry.name.startsWith('aws-')) + .map(entry => entry.name.replace('-', '_')) +} + +// Generate exclusions for ICfn* interfaces +function generateIcfnExclusions() { + const modules = getAwsModules(); + const exclusions = []; + + for (const module of modules) { + exclusions.push(`construct-interface-extends-iconstruct:aws-cdk-lib.${module}.ICfn*`); + } + exclusions.push('construct-interface-extends-iconstruct:aws-cdk-lib.ICfn*'); + exclusions.push('construct-interface-extends-iconstruct:aws-cdk-lib.alexa_ask.ICfn*'); + + return exclusions; +} + +// Add the generated exclusions to process.argv +const icfnExclusions = generateIcfnExclusions(); +for (const exclusion of icfnExclusions) { + process.argv.push('--exclude', exclusion); +} + +// Run the original awslint require('awslint/bin/awslint.js'); \ No newline at end of file From 9a79ff72f94904e2bd969603e7e2b257eddbcc79 Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Tue, 12 Aug 2025 12:06:20 +0100 Subject: [PATCH 11/26] Add "@aws-cdk/aws-pipes-sources-alpha" to example dependencies --- packages/@aws-cdk/aws-pipes-targets-alpha/package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-pipes-targets-alpha/package.json b/packages/@aws-cdk/aws-pipes-targets-alpha/package.json index 4882f6630ab2f..1101be17265e6 100644 --- a/packages/@aws-cdk/aws-pipes-targets-alpha/package.json +++ b/packages/@aws-cdk/aws-pipes-targets-alpha/package.json @@ -115,6 +115,8 @@ ] }, "jsiiRosetta": { - "exampleDependencies": {} + "exampleDependencies": { + "@aws-cdk/aws-pipes-sources-alpha": "^0.0.0" + } } } From d8da50c8e232d3665302b316751911341b6c2ab9 Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Tue, 12 Aug 2025 16:03:07 +0100 Subject: [PATCH 12/26] Addressed comments --- packages/awslint/lib/rules/core-types.ts | 2 +- .../@aws-cdk/cdk-build-tools/bin/cdk-awslint | 44 ------------------- .../@aws-cdk/cdk-build-tools/bin/cdk-build.ts | 39 +++++++++++++++- tools/@aws-cdk/cdk-build-tools/lib/lint.ts | 3 +- .../cdk-build-tools/lib/package-info.ts | 5 +++ .../spec2cdk/lib/cdk/resource-class.ts | 12 ++--- .../spec2cdk/lib/cdk/resource-decider.ts | 12 ++--- 7 files changed, 58 insertions(+), 59 deletions(-) diff --git a/packages/awslint/lib/rules/core-types.ts b/packages/awslint/lib/rules/core-types.ts index 1a1ce304634f6..1c0e00f7a5dbf 100644 --- a/packages/awslint/lib/rules/core-types.ts +++ b/packages/awslint/lib/rules/core-types.ts @@ -86,7 +86,7 @@ export class CoreTypes { */ public static isCfnType(interfaceType: reflect.Type) { return interfaceType.name.startsWith('Cfn') - || interfaceType.name.startsWith('ICfn') + || /^I\w+Ref/.test(interfaceType.name) || (interfaceType.namespace && interfaceType.namespace.startsWith('Cfn')) // aws_service.CfnTheResource.SubType || (interfaceType.namespace && interfaceType.namespace.split('.', 2).at(1)?.startsWith('Cfn')); diff --git a/tools/@aws-cdk/cdk-build-tools/bin/cdk-awslint b/tools/@aws-cdk/cdk-build-tools/bin/cdk-awslint index 7c1c8c178d125..c48646498be66 100755 --- a/tools/@aws-cdk/cdk-build-tools/bin/cdk-awslint +++ b/tools/@aws-cdk/cdk-build-tools/bin/cdk-awslint @@ -1,48 +1,4 @@ #!/usr/bin/env node -/* -For every L1 construct, we generate a corresponding resource reference interface which it inherits. For example, -CfnManagedPolicy extends ICfnManagedPolicy. The ICfn* interfaces are meant to also be extended by L2 interfaces. -Although most L2 interfaces extend IConstruct, not all of them do. A case in point is IManagedPolicy, that can't extend -IConstruct because it would be impossible to produce an instance of it using ManagedPolicy.fromAwsManagedPolicyName(), -since it doesn't take a construct scope as a parameter. Therefore, the ICfn* interfaces cannot extend IConstruct if we -want to cover these cases. - -Before calling awslint, we are excluding the 'construct-interface-extends-iconstruct' rule for the ICfn* interfaces. - */ - -const fs = require('fs'); -const path = require('path'); - -// Get all AWS modules from aws-cdk-lib -function getAwsModules() { - const cdkLibPath = path.resolve(__dirname, '../../../../packages/aws-cdk-lib'); - const entries = fs.readdirSync(cdkLibPath, { withFileTypes: true }); - - return entries - .filter(entry => entry.isDirectory() && entry.name.startsWith('aws-')) - .map(entry => entry.name.replace('-', '_')) -} - -// Generate exclusions for ICfn* interfaces -function generateIcfnExclusions() { - const modules = getAwsModules(); - const exclusions = []; - - for (const module of modules) { - exclusions.push(`construct-interface-extends-iconstruct:aws-cdk-lib.${module}.ICfn*`); - } - exclusions.push('construct-interface-extends-iconstruct:aws-cdk-lib.ICfn*'); - exclusions.push('construct-interface-extends-iconstruct:aws-cdk-lib.alexa_ask.ICfn*'); - - return exclusions; -} - -// Add the generated exclusions to process.argv -const icfnExclusions = generateIcfnExclusions(); -for (const exclusion of icfnExclusions) { - process.argv.push('--exclude', exclusion); -} - // Run the original awslint require('awslint/bin/awslint.js'); \ No newline at end of file diff --git a/tools/@aws-cdk/cdk-build-tools/bin/cdk-build.ts b/tools/@aws-cdk/cdk-build-tools/bin/cdk-build.ts index 0507b33126ff2..327bc1ef23ebc 100644 --- a/tools/@aws-cdk/cdk-build-tools/bin/cdk-build.ts +++ b/tools/@aws-cdk/cdk-build-tools/bin/cdk-build.ts @@ -1,3 +1,5 @@ +import * as fs from 'node:fs'; +import * as path from 'node:path'; import * as yargs from 'yargs'; import { compileCurrentPackage } from '../lib/compile'; import { lintCurrentPackage } from '../lib/lint'; @@ -57,7 +59,18 @@ async function main() { const overrides: CompilerOverrides = { eslint: args.eslint, jsii: args.jsii, tsc: args.tsc }; await compileCurrentPackage(options, timers, overrides); if (!args['skip-lint']) { - await lintCurrentPackage(options, timers, { ...overrides, fix: args.fix }); + /* + For every L1 construct, we generate a corresponding resource reference interface which it inherits. For example, + CfnManagedPolicy extends ICfnManagedPolicy. The ICfn* interfaces are meant to also be extended by L2 interfaces. + Although most L2 interfaces extend IConstruct, not all of them do. A case in point is IManagedPolicy, that can't extend + IConstruct because it would be impossible to produce an instance of it using ManagedPolicy.fromAwsManagedPolicyName(), + since it doesn't take a construct scope as a parameter. Therefore, the ICfn* interfaces cannot extend IConstruct if we + want to cover these cases. + + Before calling awslint, we are excluding the 'construct-interface-extends-iconstruct' rule for the ICfn* interfaces. + */ + const lintExclusions = generateIcfnExclusions().map(exclusion => `--exclude=${exclusion}`); + await lintCurrentPackage({ ...options, lintExclusions }, timers, { ...overrides, fix: args.fix }); } if (options.post) { @@ -78,3 +91,27 @@ main().catch(e => { buildTimer.end(); process.stdout.write(`Build times for ${currentPackageJson().name}: ${timers.display()}\n`); }); + +// Generate exclusions for ICfn* interfaces +function generateIcfnExclusions() { + const modules = getAwsModules(); + const exclusions = []; + + for (const module of modules) { + exclusions.push(`construct-interface-extends-iconstruct:aws-cdk-lib.${module}.ICfn*`); + } + exclusions.push('construct-interface-extends-iconstruct:aws-cdk-lib.ICfn*'); + exclusions.push('construct-interface-extends-iconstruct:aws-cdk-lib.alexa_ask.ICfn*'); + + return exclusions; +} + +// Get all AWS modules from aws-cdk-lib +function getAwsModules() { + const cdkLibPath = path.resolve(__dirname, '../../../../packages/aws-cdk-lib'); + const entries = fs.readdirSync(cdkLibPath, { withFileTypes: true }); + + return entries + .filter(entry => entry.isDirectory() && entry.name.startsWith('aws-')) + .map(entry => entry.name.replace('-', '_')); +} diff --git a/tools/@aws-cdk/cdk-build-tools/lib/lint.ts b/tools/@aws-cdk/cdk-build-tools/lib/lint.ts index ef5d522419264..426478b5fae95 100644 --- a/tools/@aws-cdk/cdk-build-tools/lib/lint.ts +++ b/tools/@aws-cdk/cdk-build-tools/lib/lint.ts @@ -48,5 +48,6 @@ export async function lintCurrentPackage( ], { timers }); } - await shell([path.join(__dirname, '..', 'bin', 'cdk-awslint')], { timers, env }); + const lintExclusions = options.lintExclusions ? options.lintExclusions.join(' ') : ''; + await shell([path.join(__dirname, '..', 'bin', 'cdk-awslint'), lintExclusions], { timers, env }); } diff --git a/tools/@aws-cdk/cdk-build-tools/lib/package-info.ts b/tools/@aws-cdk/cdk-build-tools/lib/package-info.ts index afcb0781a93cd..f865ad23fcebb 100644 --- a/tools/@aws-cdk/cdk-build-tools/lib/package-info.ts +++ b/tools/@aws-cdk/cdk-build-tools/lib/package-info.ts @@ -182,6 +182,11 @@ export interface CDKBuildOptions { * Whether the jsii assembly should be compressed into a .jsii.gz file or left uncompressed as a .jsii file. */ compressAssembly?: boolean; + + /** + * Patterns to be excluded from linting + */ + lintExclusions?: string[]; } export interface CDKPackageOptions { diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts index d60da8d0a855c..ad0aaa54da18e 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts @@ -34,7 +34,6 @@ import { cfnProducerNameFromType, propStructNameFromResource, staticRequiredTransform, - interfaceNameFromResource, } from '../naming'; import { splitDocumentation } from '../util'; @@ -60,9 +59,10 @@ export class ResourceClass extends ClassType { ) { const resourceInterface = new InterfaceType(scope, { export: true, - name: interfaceNameFromResource(resource, suffix), + // name: interfaceNameFromResource(resource, suffix), + name: `I${resource.name}${suffix ?? ''}Ref`, docs: { - summary: `Attributes to reference a \`${classNameFromResource(resource)}\`.`, + summary: `Reference to an instance of ${resource.name}.`, stability: Stability.External, }, }); @@ -119,7 +119,7 @@ export class ResourceClass extends ClassType { } // Build the shared interface - for (const identifier of this.decider.primaryIdentifier ?? []) { + for (const identifier of this.decider.primaryIdentifierProps ?? []) { this.resourceInterface.addProperty({ ...identifier, immutable: true, @@ -127,9 +127,9 @@ export class ResourceClass extends ClassType { } // Add the arn too, unless it is duplicated in the resourceIdentifier already - if (this.decider.arn && this.resourceInterface.properties.every((p) => p.name !== this.decider.arn!.name)) { + if (this.decider.arnProperty && this.resourceInterface.properties.every((p) => p.name !== this.decider.arnProperty!.name)) { this.resourceInterface.addProperty({ - ...this.decider.arn, + ...this.decider.arnProperty, immutable: true, }); } diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts index cf6f0ca995ba9..a4f47a954645a 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts @@ -28,8 +28,8 @@ export class ResourceDecider { /** * The arn returned by the resource, if applicable. */ - public readonly arn?: PropertySpec; - public readonly primaryIdentifier = new Array(); + public readonly arnProperty?: PropertySpec; + public readonly primaryIdentifierProps = new Array(); public readonly propsProperties = new Array(); public readonly classProperties = new Array(); public readonly classAttributeProperties = new Array(); @@ -41,7 +41,7 @@ export class ResourceDecider { this.convertAttributes(); this.convertPrimaryIdentifier(); - this.arn = this.findArn(); + this.arnProperty = this.findArn(); this.propsProperties.sort((p1, p2) => p1.propertySpec.name.localeCompare(p2.propertySpec.name)); this.classProperties.sort((p1, p2) => p1.propertySpec.name.localeCompare(p2.propertySpec.name)); @@ -86,14 +86,14 @@ export class ResourceDecider { const att = this.findAttributeByName(attributePropertyName(cfnName)); const prop = this.findPropertyByName(propertyNameFromCloudFormation(cfnName)); if (att) { - this.primaryIdentifier.push(att); + this.primaryIdentifierProps.push(att); } else if (prop) { const propSpec = prop.propertySpec; // Build an attribute out of the property we're getting // Create initializer for new attribute, if possible let initializer: Expression | undefined = undefined; - if (propSpec.type === Type.STRING) { // handling only this case for now + if (propSpec.type === Type.STRING) { // handling only this case for now. // The fact that a property is part of a primary identifier does not necessarily imply that it can be read. // Example: AWS::ApiGateway::RequestValidator has a primary identifier composed of // [ "/properties/RestApiId", "/properties/RequestValidatorId" ]. But Ref only returns the validator ID. @@ -115,7 +115,7 @@ export class ResourceDecider { initializer, }); - this.primaryIdentifier.push(attrPropertySpec); + this.primaryIdentifierProps.push(attrPropertySpec); } } } From a60fbf9a6f57d287c825d35cd39d0e8614acb74e Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Tue, 12 Aug 2025 16:32:37 +0100 Subject: [PATCH 13/26] Updated interface names --- .../test/__snapshots__/resources.test.ts.snap | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap index fdc325860b02d..8924263781031 100644 --- a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap +++ b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap @@ -8,11 +8,11 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Attributes to reference a \`CfnResource\`. + * Reference to an instance of Resource. * * @stability external */ -export interface ICfnResource { +export interface IResourceRef { /** * The identifier of the resource. * This property gets determined after the resource is created. @@ -27,7 +27,7 @@ export interface ICfnResource { * @stability external * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html */ -export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IResourceRef { /** * The CloudFormation resource type name for this resource class. */ @@ -173,11 +173,11 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Attributes to reference a \`CfnResource\`. + * Reference to an instance of Resource. * * @stability external */ -export interface ICfnResource { +export interface IResourceRef { /** * The identifier of the resource * @@ -191,7 +191,7 @@ export interface ICfnResource { * @stability external * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html */ -export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IResourceRef { /** * The CloudFormation resource type name for this resource class. */ @@ -319,11 +319,11 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Attributes to reference a \`CfnSomething\`. + * Reference to an instance of Something. * * @stability external */ -export interface ICfnSomething { +export interface ISomethingRef { /** * The identifier of the resource * @@ -344,7 +344,7 @@ export interface ICfnSomething { * @stability external * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-something.html */ -export class CfnSomething extends cdk.CfnResource implements cdk.IInspectable, ICfnSomething { +export class CfnSomething extends cdk.CfnResource implements cdk.IInspectable, ISomethingRef { /** * The CloudFormation resource type name for this resource class. */ @@ -480,11 +480,11 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Attributes to reference a \`CfnResource\`. + * Reference to an instance of Resource. * * @stability external */ -export interface ICfnResource { +export interface IResourceRef { /** * The identifier of the resource * @@ -505,7 +505,7 @@ export interface ICfnResource { * @stability external * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html */ -export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IResourceRef { /** * The CloudFormation resource type name for this resource class. */ @@ -641,11 +641,11 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Attributes to reference a \`CfnResource\`. + * Reference to an instance of Resource. * * @stability external */ -export interface ICfnResource { +export interface IResourceRef { /** * The identifier of the resource * @@ -659,7 +659,7 @@ export interface ICfnResource { * @stability external * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html */ -export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IResourceRef { /** * The CloudFormation resource type name for this resource class. */ @@ -804,11 +804,11 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Attributes to reference a \`CfnResource\`. + * Reference to an instance of Resource. * * @stability external */ -export interface ICfnResource { +export interface IResourceRef { /** * The arn of the resource * @@ -822,7 +822,7 @@ export interface ICfnResource { * @stability external * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html */ -export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IResourceRef { /** * The CloudFormation resource type name for this resource class. */ @@ -950,11 +950,11 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Attributes to reference a \`CfnResource\`. + * Reference to an instance of Resource. * * @stability external */ -export interface ICfnResource { +export interface IResourceRef { /** * The identifier of the resource * @@ -975,7 +975,7 @@ export interface ICfnResource { * @stability external * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html */ -export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IResourceRef { /** * The CloudFormation resource type name for this resource class. */ @@ -1111,11 +1111,11 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Attributes to reference a \`CfnResource\`. + * Reference to an instance of Resource. * * @stability external */ -export interface ICfnResource { +export interface IResourceRef { } @@ -1124,7 +1124,7 @@ export interface ICfnResource { * @stability external * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html */ -export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IResourceRef { /** * The CloudFormation resource type name for this resource class. */ @@ -1278,11 +1278,11 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Attributes to reference a \`CfnResource\`. + * Reference to an instance of Resource. * * @stability external */ -export interface ICfnResource { +export interface IResourceRef { /** * The identifier of the resource. * This property gets determined after the resource is created. @@ -1297,7 +1297,7 @@ export interface ICfnResource { * @stability external * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-some-resource.html */ -export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, ICfnResource { +export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IResourceRef { /** * The CloudFormation resource type name for this resource class. */ From 8099618db538374ef0eaab6332f51cf46548ca1d Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Tue, 12 Aug 2025 17:18:04 +0100 Subject: [PATCH 14/26] Removed awslint exclusions --- .../@aws-cdk/cdk-build-tools/bin/cdk-build.ts | 39 +------------------ 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/tools/@aws-cdk/cdk-build-tools/bin/cdk-build.ts b/tools/@aws-cdk/cdk-build-tools/bin/cdk-build.ts index 327bc1ef23ebc..0507b33126ff2 100644 --- a/tools/@aws-cdk/cdk-build-tools/bin/cdk-build.ts +++ b/tools/@aws-cdk/cdk-build-tools/bin/cdk-build.ts @@ -1,5 +1,3 @@ -import * as fs from 'node:fs'; -import * as path from 'node:path'; import * as yargs from 'yargs'; import { compileCurrentPackage } from '../lib/compile'; import { lintCurrentPackage } from '../lib/lint'; @@ -59,18 +57,7 @@ async function main() { const overrides: CompilerOverrides = { eslint: args.eslint, jsii: args.jsii, tsc: args.tsc }; await compileCurrentPackage(options, timers, overrides); if (!args['skip-lint']) { - /* - For every L1 construct, we generate a corresponding resource reference interface which it inherits. For example, - CfnManagedPolicy extends ICfnManagedPolicy. The ICfn* interfaces are meant to also be extended by L2 interfaces. - Although most L2 interfaces extend IConstruct, not all of them do. A case in point is IManagedPolicy, that can't extend - IConstruct because it would be impossible to produce an instance of it using ManagedPolicy.fromAwsManagedPolicyName(), - since it doesn't take a construct scope as a parameter. Therefore, the ICfn* interfaces cannot extend IConstruct if we - want to cover these cases. - - Before calling awslint, we are excluding the 'construct-interface-extends-iconstruct' rule for the ICfn* interfaces. - */ - const lintExclusions = generateIcfnExclusions().map(exclusion => `--exclude=${exclusion}`); - await lintCurrentPackage({ ...options, lintExclusions }, timers, { ...overrides, fix: args.fix }); + await lintCurrentPackage(options, timers, { ...overrides, fix: args.fix }); } if (options.post) { @@ -91,27 +78,3 @@ main().catch(e => { buildTimer.end(); process.stdout.write(`Build times for ${currentPackageJson().name}: ${timers.display()}\n`); }); - -// Generate exclusions for ICfn* interfaces -function generateIcfnExclusions() { - const modules = getAwsModules(); - const exclusions = []; - - for (const module of modules) { - exclusions.push(`construct-interface-extends-iconstruct:aws-cdk-lib.${module}.ICfn*`); - } - exclusions.push('construct-interface-extends-iconstruct:aws-cdk-lib.ICfn*'); - exclusions.push('construct-interface-extends-iconstruct:aws-cdk-lib.alexa_ask.ICfn*'); - - return exclusions; -} - -// Get all AWS modules from aws-cdk-lib -function getAwsModules() { - const cdkLibPath = path.resolve(__dirname, '../../../../packages/aws-cdk-lib'); - const entries = fs.readdirSync(cdkLibPath, { withFileTypes: true }); - - return entries - .filter(entry => entry.isDirectory() && entry.name.startsWith('aws-')) - .map(entry => entry.name.replace('-', '_')); -} From f0d857b1ae978062a515a74fb69871eecbc1161f Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Tue, 12 Aug 2025 17:47:10 +0100 Subject: [PATCH 15/26] Removed unused code --- tools/@aws-cdk/cdk-build-tools/lib/lint.ts | 3 +-- tools/@aws-cdk/cdk-build-tools/lib/package-info.ts | 5 ----- tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts | 1 - 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/tools/@aws-cdk/cdk-build-tools/lib/lint.ts b/tools/@aws-cdk/cdk-build-tools/lib/lint.ts index 426478b5fae95..ef5d522419264 100644 --- a/tools/@aws-cdk/cdk-build-tools/lib/lint.ts +++ b/tools/@aws-cdk/cdk-build-tools/lib/lint.ts @@ -48,6 +48,5 @@ export async function lintCurrentPackage( ], { timers }); } - const lintExclusions = options.lintExclusions ? options.lintExclusions.join(' ') : ''; - await shell([path.join(__dirname, '..', 'bin', 'cdk-awslint'), lintExclusions], { timers, env }); + await shell([path.join(__dirname, '..', 'bin', 'cdk-awslint')], { timers, env }); } diff --git a/tools/@aws-cdk/cdk-build-tools/lib/package-info.ts b/tools/@aws-cdk/cdk-build-tools/lib/package-info.ts index f865ad23fcebb..afcb0781a93cd 100644 --- a/tools/@aws-cdk/cdk-build-tools/lib/package-info.ts +++ b/tools/@aws-cdk/cdk-build-tools/lib/package-info.ts @@ -182,11 +182,6 @@ export interface CDKBuildOptions { * Whether the jsii assembly should be compressed into a .jsii.gz file or left uncompressed as a .jsii file. */ compressAssembly?: boolean; - - /** - * Patterns to be excluded from linting - */ - lintExclusions?: string[]; } export interface CDKPackageOptions { diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts index ad0aaa54da18e..2156c068af4b0 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts @@ -59,7 +59,6 @@ export class ResourceClass extends ClassType { ) { const resourceInterface = new InterfaceType(scope, { export: true, - // name: interfaceNameFromResource(resource, suffix), name: `I${resource.name}${suffix ?? ''}Ref`, docs: { summary: `Reference to an instance of ${resource.name}.`, From 27d75eeaea6832d7f18f95caed0d76f4f8020095 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 19 Aug 2025 14:09:59 +0200 Subject: [PATCH 16/26] Rewrite to an indirecting interface --- .../aws-pipes-targets-alpha/package.json | 6 +- tools/@aws-cdk/spec2cdk/lib/cdk/cdk.ts | 1 + .../spec2cdk/lib/cdk/resource-class.ts | 73 ++-- .../spec2cdk/lib/cdk/resource-decider.ts | 137 +++---- .../spec2cdk/lib/naming/conventions.ts | 11 + .../test/__snapshots__/resources.test.ts.snap | 352 +++++++++++++----- 6 files changed, 386 insertions(+), 194 deletions(-) diff --git a/packages/@aws-cdk/aws-pipes-targets-alpha/package.json b/packages/@aws-cdk/aws-pipes-targets-alpha/package.json index 1101be17265e6..8cbe9a5eca4eb 100644 --- a/packages/@aws-cdk/aws-pipes-targets-alpha/package.json +++ b/packages/@aws-cdk/aws-pipes-targets-alpha/package.json @@ -82,7 +82,7 @@ "license": "Apache-2.0", "devDependencies": { "@aws-cdk/cdk-build-tools": "0.0.0", - "@aws-cdk/integ-runner": "^2.189.2", + "@aws-cdk/integ-runner": "^2.189.3", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^29.5.14", "jest": "^29", @@ -115,8 +115,6 @@ ] }, "jsiiRosetta": { - "exampleDependencies": { - "@aws-cdk/aws-pipes-sources-alpha": "^0.0.0" - } + "exampleDependencies": {} } } diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/cdk.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/cdk.ts index 195a844ac2bc2..e1477cacd98cd 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/cdk.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/cdk.ts @@ -37,6 +37,7 @@ export class CdkCore extends ExternalModule { public readonly CfnTag = Type.fromName(this, 'CfnTag'); public readonly TagManager = $T(Type.fromName(this, 'TagManager')); public readonly TagType = $T(Type.fromName(this, 'TagType')); + public readonly Fn = $T(Type.fromName(this, 'Fn')); public readonly ITaggable = Type.fromName(this, 'ITaggable'); public readonly ITaggableV2 = Type.fromName(this, 'ITaggableV2'); public readonly IResolvable = Type.fromName(this, 'IResolvable'); diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts index 2156c068af4b0..02d06cc277190 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts @@ -46,7 +46,7 @@ const $this = $E(expr.this_()); export class ResourceClass extends ClassType { private readonly propsType: StructType; - private readonly resourceInterface: InterfaceType; + private readonly refInterface: InterfaceType; private readonly decider: ResourceDecider; private readonly converter: TypeConverter; private readonly module: Module; @@ -57,12 +57,12 @@ export class ResourceClass extends ClassType { private readonly resource: Resource, private readonly suffix?: string, ) { - const resourceInterface = new InterfaceType(scope, { + // IBucketRef { bucketRef: BucketRef } + const refInterface = new InterfaceType(scope, { export: true, name: `I${resource.name}${suffix ?? ''}Ref`, docs: { - summary: `Reference to an instance of ${resource.name}.`, - stability: Stability.External, + summary: `Indicates that this resource can be referenced as a ${resource.name}.`, }, }); @@ -78,10 +78,10 @@ export class ResourceClass extends ClassType { }), }, extends: CDK_CORE.CfnResource, - implements: [CDK_CORE.IInspectable, resourceInterface.type, ...ResourceDecider.taggabilityInterfaces(resource)], + implements: [CDK_CORE.IInspectable, refInterface.type, ...ResourceDecider.taggabilityInterfaces(resource)], }); - this.resourceInterface = resourceInterface; + this.refInterface = refInterface; this.module = Module.of(this); this.propsType = new StructType(this.scope, { @@ -117,21 +117,7 @@ export class ResourceClass extends ClassType { cfnMapping.add(prop.cfnMapping); } - // Build the shared interface - for (const identifier of this.decider.primaryIdentifierProps ?? []) { - this.resourceInterface.addProperty({ - ...identifier, - immutable: true, - }); - } - - // Add the arn too, unless it is duplicated in the resourceIdentifier already - if (this.decider.arnProperty && this.resourceInterface.properties.every((p) => p.name !== this.decider.arnProperty!.name)) { - this.resourceInterface.addProperty({ - ...this.decider.arnProperty, - immutable: true, - }); - } + this.buildReferenceInterface(); // Build the members of this class this.addProperty({ @@ -181,6 +167,51 @@ export class ResourceClass extends ClassType { this.makeMustRenderStructs(); } + /** + * Build the reference interface for this resource + */ + private buildReferenceInterface() { + // BucketRef { bucketName, bucketArn } + const refPropsStruct = new StructType(this.scope, { + export: true, + name: `${this.resource.name}${this.suffix ?? ''}Ref`, + docs: { + summary: `A reference to a ${this.resource.name} resource.`, + stability: Stability.External, + }, + }); + + // Build the shared interface + for (const { declaration } of this.decider.referenceProps ?? []) { + refPropsStruct.addProperty(declaration); + } + + // Add the arn too, unless it is duplicated in the resourceIdentifier already + if (this.decider.arnProperty && this.refInterface.properties.every((p) => p.name !== this.decider.arnProperty!.name)) { + refPropsStruct.addProperty({ + ...this.decider.arnProperty, + }); + } + + const refProperty = this.refInterface.addProperty({ + name: `${this.decider.camelResourceName}Ref`, + type: refPropsStruct.type, + immutable: true, + docs: { + summary: `A reference to a ${this.resource.name} resource.`, + }, + }); + + this.addProperty({ + name: refProperty.name, + type: refProperty.type, + getterBody: Block.with( + stmt.ret(expr.object(Object.fromEntries(this.decider.referenceProps.map(({ declaration, cfnValue }) => [declaration.name, cfnValue])))), + ), + immutable: true, + }); + } + private makeFromCloudFormationFactory() { const factory = this.addMethod({ name: '_fromCloudFormation', diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts index a4f47a954645a..0f14392209451 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts @@ -4,12 +4,17 @@ import { CDK_CORE } from './cdk'; import { PropertyMapping } from './cloudformation-mapping'; import { NON_RESOLVABLE_PROPERTY_NAMES, TaggabilityStyle, resourceTaggabilityStyle } from './tagging'; import { TypeConverter } from './type-converter'; -import { attributePropertyName, cloudFormationDocLink, propertyNameFromCloudFormation } from '../naming'; +import { attributePropertyName, cloudFormationDocLink, propertyNameFromCloudFormation, referencePropertyName } from '../naming'; import { splitDocumentation } from '../util'; // This convenience typewriter builder is used all over the place const $this = $E(expr.this_()); +interface ReferenceProp { + readonly declaration: PropertySpec; + readonly cfnValue: Expression; +} + /** * Decide how properties get mapped between model types, Typescript types, and CloudFormation */ @@ -29,18 +34,20 @@ export class ResourceDecider { * The arn returned by the resource, if applicable. */ public readonly arnProperty?: PropertySpec; - public readonly primaryIdentifierProps = new Array(); + public readonly referenceProps = new Array(); public readonly propsProperties = new Array(); public readonly classProperties = new Array(); public readonly classAttributeProperties = new Array(); + public readonly camelResourceName: string; constructor(private readonly resource: Resource, private readonly converter: TypeConverter) { + this.camelResourceName = this.resource.name.charAt(0).toLowerCase() + this.resource.name.slice(1); this.taggability = resourceTaggabilityStyle(this.resource); this.convertProperties(); this.convertAttributes(); - this.convertPrimaryIdentifier(); + this.convertReferenceProps(); this.arnProperty = this.findArn(); this.propsProperties.sort((p1, p2) => p1.propertySpec.name.localeCompare(p2.propertySpec.name)); @@ -79,73 +86,51 @@ export class ResourceDecider { return; } - private convertPrimaryIdentifier() { - if (this.resource.primaryIdentifier === undefined) { return; } - for (let i = 0; i < (this.resource.primaryIdentifier).length; i++) { - const cfnName = this.resource.primaryIdentifier[i]; - const att = this.findAttributeByName(attributePropertyName(cfnName)); - const prop = this.findPropertyByName(propertyNameFromCloudFormation(cfnName)); - if (att) { - this.primaryIdentifierProps.push(att); - } else if (prop) { - const propSpec = prop.propertySpec; - - // Build an attribute out of the property we're getting - // Create initializer for new attribute, if possible - let initializer: Expression | undefined = undefined; - if (propSpec.type === Type.STRING) { // handling only this case for now. - // The fact that a property is part of a primary identifier does not necessarily imply that it can be read. - // Example: AWS::ApiGateway::RequestValidator has a primary identifier composed of - // [ "/properties/RestApiId", "/properties/RequestValidatorId" ]. But Ref only returns the validator ID. - // Handling only the case where the primary identifier is a single property, which is the most common case. - if (this.resource.primaryIdentifier!.length === 1) { - initializer = CDK_CORE.tokenAsString($this.ref); - } - } - - // If we cannot come up with an initializer, we're dropping this property on the floor - if (!initializer) { continue; } - - // Build an attribute spec out of the property spec - const attrPropertySpec = this.convertPropertySpecToRefAttribute(propSpec); - - // Add the new attribute to the relevant places - this.classAttributeProperties.push({ - propertySpec: attrPropertySpec, - initializer, + private convertReferenceProps() { + // Primary identifier. We assume all parts are strings. + const primaryIdentifier = this.resource.primaryIdentifier ?? []; + if (primaryIdentifier.length === 1) { + this.referenceProps.push({ + declaration: { + name: referencePropertyName(primaryIdentifier[0], this.resource.name), + type: Type.STRING, + immutable: true, + docs: { + summary: `The ${primaryIdentifier[0]} of the ${this.resource.name} resource.`, + }, + }, + cfnValue: $this.ref, + }); + } else if (primaryIdentifier.length > 1) { + for (const [i, cfnName] of enumerate(primaryIdentifier)) { + this.referenceProps.push({ + declaration: { + name: referencePropertyName(cfnName, this.resource.name), + type: Type.STRING, + immutable: true, + docs: { + summary: `The ${cfnName} of the ${this.resource.name} resource.`, + }, + }, + cfnValue: splitSelect('|', i, $this.ref), }); - - this.primaryIdentifierProps.push(attrPropertySpec); } } - } - - private convertPropertySpecToRefAttribute(propSpec: PropertySpec): PropertySpec { - return { - ...propSpec, - name: attributePropertyName(propSpec.name[0].toUpperCase() + propSpec.name.slice(1)), - docs: { - ...propSpec.docs, - summary: (propSpec.docs?.summary ?? '').concat('\nThis property gets determined after the resource is created.'), - remarks: (propSpec.docs?.remarks ?? '').concat('@cloudformationAttribute Ref'), - }, - immutable: true, - optional: false, - }; - } - private findPropertyByName(name: string): ClassProperty | undefined { - const props = this.classProperties.filter((prop) => prop.propertySpec.name === name); - // there's no way we have multiple properties with the same name - if (props.length > 0) { return props[0]; } - return; - } - - private findAttributeByName(name: string): PropertySpec | undefined { - const atts = this.classAttributeProperties.filter((att) => att.propertySpec.name === name); - // there's no way we have multiple attributes with the same name - if (atts.length > 0) { return atts[0].propertySpec; } - return; + const arnProp = this.findArn(); + if (arnProp) { + this.referenceProps.push({ + declaration: { + name: referencePropertyName(arnProp.name, this.resource.name), + type: Type.STRING, + immutable: true, + docs: { + summary: `The ARN of the ${this.resource.name} resource.`, + }, + }, + cfnValue: $this[arnProp.name], + }); + } } /** @@ -418,12 +403,20 @@ export class ResourceDecider { return CDK_CORE.TagType.AUTOSCALING_GROUP; case 'map': return CDK_CORE.TagType.MAP; + default: + assertNever(variant); } - - throw new Error(`Unknown variant: ${this.resource.tagInformation?.variant}`); } } +/** + * Utility function to ensure exhaustive checks for never type. + */ +function assertNever(x: never): never { + // eslint-disable-next-line @cdklabs/no-throw-default-error + throw new Error(`Unexpected object: ${x}`); +} + export interface PropsProperty { readonly propertySpec: PropertySpec; readonly validateRequiredInConstructor: boolean; @@ -461,3 +454,11 @@ export function deprecationMessage(property: Property): string | undefined { return undefined; } + +function splitSelect(sep: string, n: number, base: Expression) { + return CDK_CORE.Fn.select(expr.lit(n), CDK_CORE.Fn.split(expr.lit(sep), base)); +} + +function enumerate(xs: A[]): Array<[number, A]> { + return xs.map((x, i) => [i, x]); +} diff --git a/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts b/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts index a22926e56cb66..3dd05a9694284 100644 --- a/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts +++ b/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts @@ -91,6 +91,17 @@ export function attributePropertyName(attrName: string) { return propertyNameFromCloudFormation(`attr${attrName.replace(/[^a-zA-Z0-9]/g, '')}`); } +/** + * Make sure the resource name is included in the property + */ +export function referencePropertyName(propName: string, resourceName: string) { + if (['arn', 'id', 'name', 'url'].includes(propName.toLowerCase())) { + return `${camelcase(resourceName)}${propName.charAt(0).toUpperCase()}${propName.slice(1)}`; + } + + return camelcase(propName); +} + /** * Generate a name for the given declaration so that we can generate helper symbols for it that won't class * diff --git a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap index 8924263781031..65a9e47c20f1b 100644 --- a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap +++ b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap @@ -8,18 +8,13 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Reference to an instance of Resource. - * - * @stability external + * Indicates that this resource can be referenced as a Resource. */ export interface IResourceRef { /** - * The identifier of the resource. - * This property gets determined after the resource is created. - * - * @cloudformationAttribute Ref + * A reference to a Resource resource. */ - readonly attrId: string; + readonly resourceRef: ResourceRef; } /** @@ -57,14 +52,6 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR return ret; } - /** - * The identifier of the resource. - * This property gets determined after the resource is created. - * - * @cloudformationAttribute Ref - */ - public readonly attrId: string; - /** * The identifier of the resource. */ @@ -81,10 +68,15 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR "properties": props }); - this.attrId = cdk.Token.asString(this.ref); this.id = props.id; } + public get resourceRef(): ResourceRef { + return { + "resourceId": this.ref + }; + } + protected get cfnProperties(): Record { return { "id": this.id @@ -122,6 +114,19 @@ export interface CfnResourceProps { readonly id?: string; } +/** + * A reference to a Resource resource. + * + * @struct + * @stability external + */ +export interface ResourceRef { + /** + * The Id of the Resource resource. + */ + readonly resourceId: string; +} + /** * Determine whether the given properties match those of a \`CfnResourceProps\` * @@ -173,17 +178,13 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Reference to an instance of Resource. - * - * @stability external + * Indicates that this resource can be referenced as a Resource. */ export interface IResourceRef { /** - * The identifier of the resource - * - * @cloudformationAttribute Id + * A reference to a Resource resource. */ - readonly attrId: string; + readonly resourceRef: ResourceRef; } /** @@ -242,6 +243,12 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR this.attrId = cdk.Token.asString(this.getAtt("Id", cdk.ResolutionTypeHint.STRING)); } + public get resourceRef(): ResourceRef { + return { + "resourceId": this.ref + }; + } + protected get cfnProperties(): Record { return {}; } @@ -272,6 +279,19 @@ export interface CfnResourceProps { } +/** + * A reference to a Resource resource. + * + * @struct + * @stability external + */ +export interface ResourceRef { + /** + * The Id of the Resource resource. + */ + readonly resourceId: string; +} + /** * Determine whether the given properties match those of a \`CfnResourceProps\` * @@ -319,24 +339,13 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Reference to an instance of Something. - * - * @stability external + * Indicates that this resource can be referenced as a Something. */ export interface ISomethingRef { /** - * The identifier of the resource - * - * @cloudformationAttribute Id - */ - readonly attrId: string; - - /** - * The arn for something - * - * @cloudformationAttribute SomethingArn + * A reference to a Something resource. */ - readonly attrSomethingArn: string; + readonly somethingRef: SomethingRef; } /** @@ -403,6 +412,13 @@ export class CfnSomething extends cdk.CfnResource implements cdk.IInspectable, I this.attrSomethingArn = cdk.Token.asString(this.getAtt("SomethingArn", cdk.ResolutionTypeHint.STRING)); } + public get somethingRef(): SomethingRef { + return { + "somethingId": this.ref, + "attrSomethingArn": this.attrSomethingArn + }; + } + protected get cfnProperties(): Record { return {}; } @@ -433,6 +449,31 @@ export interface CfnSomethingProps { } +/** + * A reference to a Something resource. + * + * @struct + * @stability external + */ +export interface SomethingRef { + /** + * The Id of the Something resource. + */ + readonly somethingId: string; + + /** + * The ARN of the Something resource. + */ + readonly attrSomethingArn: string; + + /** + * The arn for something + * + * @cloudformationAttribute SomethingArn + */ + readonly attrSomethingArn: string; +} + /** * Determine whether the given properties match those of a \`CfnSomethingProps\` * @@ -480,24 +521,13 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Reference to an instance of Resource. - * - * @stability external + * Indicates that this resource can be referenced as a Resource. */ export interface IResourceRef { /** - * The identifier of the resource - * - * @cloudformationAttribute Id - */ - readonly attrId: string; - - /** - * The arn for the resource - * - * @cloudformationAttribute Arn + * A reference to a Resource resource. */ - readonly attrArn: string; + readonly resourceRef: ResourceRef; } /** @@ -564,6 +594,13 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR this.attrId = cdk.Token.asString(this.getAtt("Id", cdk.ResolutionTypeHint.STRING)); } + public get resourceRef(): ResourceRef { + return { + "resourceId": this.ref, + "attrArn": this.attrArn + }; + } + protected get cfnProperties(): Record { return {}; } @@ -594,6 +631,31 @@ export interface CfnResourceProps { } +/** + * A reference to a Resource resource. + * + * @struct + * @stability external + */ +export interface ResourceRef { + /** + * The Id of the Resource resource. + */ + readonly resourceId: string; + + /** + * The ARN of the Resource resource. + */ + readonly attrArn: string; + + /** + * The arn for the resource + * + * @cloudformationAttribute Arn + */ + readonly attrArn: string; +} + /** * Determine whether the given properties match those of a \`CfnResourceProps\` * @@ -641,17 +703,13 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Reference to an instance of Resource. - * - * @stability external + * Indicates that this resource can be referenced as a Resource. */ export interface IResourceRef { /** - * The identifier of the resource - * - * @cloudformationAttribute Id + * A reference to a Resource resource. */ - readonly attrId: string; + readonly resourceRef: ResourceRef; } /** @@ -716,6 +774,12 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR this.arn = props.arn; } + public get resourceRef(): ResourceRef { + return { + "resourceId": this.ref + }; + } + protected get cfnProperties(): Record { return { "arn": this.arn @@ -753,6 +817,19 @@ export interface CfnResourceProps { readonly arn?: string; } +/** + * A reference to a Resource resource. + * + * @struct + * @stability external + */ +export interface ResourceRef { + /** + * The Id of the Resource resource. + */ + readonly resourceId: string; +} + /** * Determine whether the given properties match those of a \`CfnResourceProps\` * @@ -804,17 +881,13 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Reference to an instance of Resource. - * - * @stability external + * Indicates that this resource can be referenced as a Resource. */ export interface IResourceRef { /** - * The arn of the resource - * - * @cloudformationAttribute Arn + * A reference to a Resource resource. */ - readonly attrArn: string; + readonly resourceRef: ResourceRef; } /** @@ -873,6 +946,13 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR this.attrArn = cdk.Token.asString(this.getAtt("Arn", cdk.ResolutionTypeHint.STRING)); } + public get resourceRef(): ResourceRef { + return { + "resourceArn": this.ref, + "attrArn": this.attrArn + }; + } + protected get cfnProperties(): Record { return {}; } @@ -903,6 +983,31 @@ export interface CfnResourceProps { } +/** + * A reference to a Resource resource. + * + * @struct + * @stability external + */ +export interface ResourceRef { + /** + * The Arn of the Resource resource. + */ + readonly resourceArn: string; + + /** + * The ARN of the Resource resource. + */ + readonly attrArn: string; + + /** + * The arn of the resource + * + * @cloudformationAttribute Arn + */ + readonly attrArn: string; +} + /** * Determine whether the given properties match those of a \`CfnResourceProps\` * @@ -950,24 +1055,13 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Reference to an instance of Resource. - * - * @stability external + * Indicates that this resource can be referenced as a Resource. */ export interface IResourceRef { /** - * The identifier of the resource - * - * @cloudformationAttribute Id - */ - readonly attrId: string; - - /** - * Another identifier of the resource - * - * @cloudformationAttribute Another + * A reference to a Resource resource. */ - readonly attrAnother: string; + readonly resourceRef: ResourceRef; } /** @@ -1034,6 +1128,13 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR this.attrId = cdk.Token.asString(this.getAtt("Id", cdk.ResolutionTypeHint.STRING)); } + public get resourceRef(): ResourceRef { + return { + "resourceId": cdk.Fn.select(0, cdk.Fn.split("|", this.ref)), + "another": cdk.Fn.select(1, cdk.Fn.split("|", this.ref)) + }; + } + protected get cfnProperties(): Record { return {}; } @@ -1064,6 +1165,24 @@ export interface CfnResourceProps { } +/** + * A reference to a Resource resource. + * + * @struct + * @stability external + */ +export interface ResourceRef { + /** + * The Id of the Resource resource. + */ + readonly resourceId: string; + + /** + * The Another of the Resource resource. + */ + readonly another: string; +} + /** * Determine whether the given properties match those of a \`CfnResourceProps\` * @@ -1111,12 +1230,13 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Reference to an instance of Resource. - * - * @stability external + * Indicates that this resource can be referenced as a Resource. */ export interface IResourceRef { - + /** + * A reference to a Resource resource. + */ + readonly resourceRef: ResourceRef; } /** @@ -1179,6 +1299,13 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR this.id = props.id; } + public get resourceRef(): ResourceRef { + return { + "resourceId": cdk.Fn.select(0, cdk.Fn.split("|", this.ref)), + "anotherId": cdk.Fn.select(1, cdk.Fn.split("|", this.ref)) + }; + } + protected get cfnProperties(): Record { return { "anotherId": this.anotherId, @@ -1224,6 +1351,24 @@ export interface CfnResourceProps { readonly id?: string; } +/** + * A reference to a Resource resource. + * + * @struct + * @stability external + */ +export interface ResourceRef { + /** + * The Id of the Resource resource. + */ + readonly resourceId: string; + + /** + * The AnotherId of the Resource resource. + */ + readonly anotherId: string; +} + /** * Determine whether the given properties match those of a \`CfnResourceProps\` * @@ -1278,18 +1423,13 @@ import * as cfn_parse from "aws-cdk-lib/core/lib/helpers-internal"; import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** - * Reference to an instance of Resource. - * - * @stability external + * Indicates that this resource can be referenced as a Resource. */ export interface IResourceRef { /** - * The identifier of the resource. - * This property gets determined after the resource is created. - * - * @cloudformationAttribute Ref + * A reference to a Resource resource. */ - readonly attrId: string; + readonly resourceRef: ResourceRef; } /** @@ -1327,14 +1467,6 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR return ret; } - /** - * The identifier of the resource. - * This property gets determined after the resource is created. - * - * @cloudformationAttribute Ref - */ - public readonly attrId: string; - /** * The identifier of the resource. */ @@ -1351,10 +1483,15 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR "properties": props }); - this.attrId = cdk.Token.asString(this.ref); this.id = props.id; } + public get resourceRef(): ResourceRef { + return { + "resourceId": this.ref + }; + } + protected get cfnProperties(): Record { return { "id": this.id @@ -1392,6 +1529,19 @@ export interface CfnResourceProps { readonly id?: string; } +/** + * A reference to a Resource resource. + * + * @struct + * @stability external + */ +export interface ResourceRef { + /** + * The Id of the Resource resource. + */ + readonly resourceId: string; +} + /** * Determine whether the given properties match those of a \`CfnResourceProps\` * From e2fde343846d354d3347e3be7a70b3b57d5244e9 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 19 Aug 2025 15:47:00 +0200 Subject: [PATCH 17/26] Naming fixes --- .../spec2cdk/lib/cdk/resource-class.ts | 45 +++-- .../spec2cdk/lib/cdk/resource-decider.ts | 47 +++-- yarn.lock | 190 +++++++++++++++++- 3 files changed, 238 insertions(+), 44 deletions(-) diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts index 02d06cc277190..729685d7fd186 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts @@ -24,7 +24,7 @@ import { } from '@cdklabs/typewriter'; import { CDK_CORE, CONSTRUCTS } from './cdk'; import { CloudFormationMapping } from './cloudformation-mapping'; -import { ResourceDecider } from './resource-decider'; +import { ResourceDecider, shouldBuildReferenceInterface } from './resource-decider'; import { TypeConverter } from './type-converter'; import { classNameFromResource, @@ -46,7 +46,7 @@ const $this = $E(expr.this_()); export class ResourceClass extends ClassType { private readonly propsType: StructType; - private readonly refInterface: InterfaceType; + private readonly refInterface?: InterfaceType; private readonly decider: ResourceDecider; private readonly converter: TypeConverter; private readonly module: Module; @@ -57,14 +57,17 @@ export class ResourceClass extends ClassType { private readonly resource: Resource, private readonly suffix?: string, ) { - // IBucketRef { bucketRef: BucketRef } - const refInterface = new InterfaceType(scope, { - export: true, - name: `I${resource.name}${suffix ?? ''}Ref`, - docs: { - summary: `Indicates that this resource can be referenced as a ${resource.name}.`, - }, - }); + let refInterface: InterfaceType | undefined; + if (shouldBuildReferenceInterface(resource)) { + // IBucketRef { bucketRef: BucketRef } + refInterface = new InterfaceType(scope, { + export: true, + name: `I${resource.name}${suffix ?? ''}Ref`, + docs: { + summary: `Indicates that this resource can be referenced as a ${resource.name}.`, + }, + }); + } super(scope, { export: true, @@ -78,7 +81,7 @@ export class ResourceClass extends ClassType { }), }, extends: CDK_CORE.CfnResource, - implements: [CDK_CORE.IInspectable, refInterface.type, ...ResourceDecider.taggabilityInterfaces(resource)], + implements: [CDK_CORE.IInspectable, refInterface?.type, ...ResourceDecider.taggabilityInterfaces(resource)].filter(isDefined), }); this.refInterface = refInterface; @@ -171,6 +174,10 @@ export class ResourceClass extends ClassType { * Build the reference interface for this resource */ private buildReferenceInterface() { + if (!shouldBuildReferenceInterface(this.resource)) { + return; + } + // BucketRef { bucketName, bucketArn } const refPropsStruct = new StructType(this.scope, { export: true, @@ -186,14 +193,7 @@ export class ResourceClass extends ClassType { refPropsStruct.addProperty(declaration); } - // Add the arn too, unless it is duplicated in the resourceIdentifier already - if (this.decider.arnProperty && this.refInterface.properties.every((p) => p.name !== this.decider.arnProperty!.name)) { - refPropsStruct.addProperty({ - ...this.decider.arnProperty, - }); - } - - const refProperty = this.refInterface.addProperty({ + const refProperty = this.refInterface!.addProperty({ name: `${this.decider.camelResourceName}Ref`, type: refPropsStruct.type, immutable: true, @@ -448,3 +448,10 @@ export class ResourceClass extends ClassType { } } } + +/** + * Type guard to filter out undefined values. + */ +function isDefined(x: T | undefined): x is T { + return x !== undefined; +} diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts index 0f14392209451..d825779f82e36 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts @@ -15,6 +15,17 @@ interface ReferenceProp { readonly cfnValue: Expression; } +// We temporarily only do this for a few services, to experiment +const REFERENCE_PROP_SERVICES = [ + 'iam', + 'apigateway', + 'ec2', + 'cloudfront', + 'kms', + 's3', + 'lambda', +]; + /** * Decide how properties get mapped between model types, Typescript types, and CloudFormation */ @@ -30,10 +41,6 @@ export class ResourceDecider { private readonly taggability?: TaggabilityStyle; - /** - * The arn returned by the resource, if applicable. - */ - public readonly arnProperty?: PropertySpec; public readonly referenceProps = new Array(); public readonly propsProperties = new Array(); public readonly classProperties = new Array(); @@ -48,7 +55,6 @@ export class ResourceDecider { this.convertAttributes(); this.convertReferenceProps(); - this.arnProperty = this.findArn(); this.propsProperties.sort((p1, p2) => p1.propertySpec.name.localeCompare(p2.propertySpec.name)); this.classProperties.sort((p1, p2) => p1.propertySpec.name.localeCompare(p2.propertySpec.name)); @@ -74,16 +80,21 @@ export class ResourceDecider { } } - private findArn() { - // A list of possible names for the arn, in order of importance. - // This is relevant because some resources, like AWS::VpcLattice::AccessLogSubscription - // has both `Arn` and `ResourceArn`, and we want to select the `Arn` property. + /** + * Find an ARN property for this resource + * + * Returns `undefined` if no ARN property is found, or if the ARN property is already + * included in the primary identifier. + */ + private findArnProperty() { const possibleArnNames = ['Arn', `${this.resource.name}Arn`]; - for (const arn of possibleArnNames) { - const att = this.classAttributeProperties.find((a) => a.propertySpec.name === attributePropertyName(arn)); - if (att) { return att.propertySpec; } + for (const name of possibleArnNames) { + const prop = this.resource.attributes[name]; + if (prop && !this.resource.primaryIdentifier?.includes(name)) { + return name; + } } - return; + return undefined; } private convertReferenceProps() { @@ -117,18 +128,18 @@ export class ResourceDecider { } } - const arnProp = this.findArn(); + const arnProp = this.findArnProperty(); if (arnProp) { this.referenceProps.push({ declaration: { - name: referencePropertyName(arnProp.name, this.resource.name), + name: referencePropertyName(arnProp, this.resource.name), type: Type.STRING, immutable: true, docs: { summary: `The ARN of the ${this.resource.name} resource.`, }, }, - cfnValue: $this[arnProp.name], + cfnValue: $this[attributePropertyName(arnProp)], }); } } @@ -462,3 +473,7 @@ function splitSelect(sep: string, n: number, base: Expression) { function enumerate(xs: A[]): Array<[number, A]> { return xs.map((x, i) => [i, x]); } + +export function shouldBuildReferenceInterface(resource: Resource) { + return true || REFERENCE_PROP_SERVICES.some(s => resource.cloudFormationType.toLowerCase().startsWith(`aws::${s}::`)); +} diff --git a/yarn.lock b/yarn.lock index 67e0c508ddd67..82ca36f851d18 100644 --- a/yarn.lock +++ b/yarn.lock @@ -66,6 +66,14 @@ "@aws-cdk/service-spec-types" "^0.0.153" "@cdklabs/tskb" "^0.0.3" +"@aws-cdk/aws-service-spec@0.1.90": + version "0.1.90" + resolved "https://registry.npmjs.org/@aws-cdk/aws-service-spec/-/aws-service-spec-0.1.90.tgz#6e767e926629c6de926bbe5def5a9fa450d29d25" + integrity sha512-jpkEL6rj/nG8mu5wWbG7fQhmrdi20ZCpcgxZmsBLM9a//GUiXw+5X5F1+ABYBIaXdaRagmcP1R3FuPzNZoq2cw== + dependencies: + "@aws-cdk/service-spec-types" "^0.0.156" + "@cdklabs/tskb" "^0.0.3" + "@aws-cdk/aws-service-spec@^0.1.89": version "0.1.89" resolved "https://registry.npmjs.org/@aws-cdk/aws-service-spec/-/aws-service-spec-0.1.89.tgz" @@ -92,6 +100,16 @@ optionalDependencies: fsevents "2.3.2" +"@aws-cdk/integ-runner@^2.189.3": + version "2.190.0" + resolved "https://registry.npmjs.org/@aws-cdk/integ-runner/-/integ-runner-2.190.0.tgz#bbd8bb8bc4f5c0540ba479cf460f131afcd540c6" + integrity sha512-cP/1e9SfnFNJZoMQYDc4/xRueuNpOAT+iKTkjhxLzQ43RY3uruRnHPl4Chm5kSLZuLaERcYOTlXYZQYzR/fzxg== + dependencies: + "@aws-cdk/aws-service-spec" "0.1.90" + aws-cdk "2.1025.0" + optionalDependencies: + fsevents "2.3.2" + "@aws-cdk/lambda-layer-kubectl-v24@^2.0.242": version "2.0.242" resolved "https://registry.npmjs.org/@aws-cdk/lambda-layer-kubectl-v24/-/lambda-layer-kubectl-v24-2.0.242.tgz" @@ -159,6 +177,13 @@ dependencies: "@cdklabs/tskb" "^0.0.3" +"@aws-cdk/service-spec-types@^0.0.156": + version "0.0.156" + resolved "https://registry.npmjs.org/@aws-cdk/service-spec-types/-/service-spec-types-0.0.156.tgz#dfcdaba90a49452edc6f8f93dd6992adcc22a2c1" + integrity sha512-LTtI7HFaeYUor8kmSQ7CHwxSRuJhWRagzjrO/zBnk+c44QDJQavfNPj8B+EPi7zu03lv/d3FfSMPNbyt7j82cQ== + dependencies: + "@cdklabs/tskb" "^0.0.3" + "@aws-crypto/crc32@5.2.0": version "5.2.0" resolved "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz" @@ -2534,12 +2559,14 @@ "@dabh/diagnostics@^2.0.2": version "2.0.3" - resolved "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz" + resolved "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA== dependencies: colorspace "1.1.x" enabled "2.0.x" kuler "^2.0.0" + +"@emnapi/core@^1.1.0": version "1.4.5" resolved "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz#bfbb0cbbbb9f96ec4e2c4fd917b7bbe5495ceccb" integrity sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q== @@ -2572,6 +2599,136 @@ esquery "^1.6.0" jsdoc-type-pratt-parser "~4.1.0" +"@esbuild/aix-ppc64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz#a1414903bb38027382f85f03dda6065056757727" + integrity sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA== + +"@esbuild/android-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz#c859994089e9767224269884061f89dae6fb51c6" + integrity sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w== + +"@esbuild/android-arm@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz#96a8f2ca91c6cd29ea90b1af79d83761c8ba0059" + integrity sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw== + +"@esbuild/android-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz#a3a626c4fec4a024a9fa8c7679c39996e92916f0" + integrity sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA== + +"@esbuild/darwin-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz#a5e1252ca2983d566af1c0ea39aded65736fc66d" + integrity sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw== + +"@esbuild/darwin-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz#5271b0df2bb12ce8df886704bfdd1c7cc01385d2" + integrity sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg== + +"@esbuild/freebsd-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz#d0a0e7fdf19733b8bb1566b81df1aa0bb7e46ada" + integrity sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA== + +"@esbuild/freebsd-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz#2de8b2e0899d08f1cb1ef3128e159616e7e85343" + integrity sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw== + +"@esbuild/linux-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz#a4209efadc0c2975716458484a4e90c237c48ae9" + integrity sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w== + +"@esbuild/linux-arm@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz#ccd9e291c24cd8d9142d819d463e2e7200d25b19" + integrity sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg== + +"@esbuild/linux-ia32@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz#006ad1536d0c2b28fb3a1cf0b53bcb85aaf92c4d" + integrity sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg== + +"@esbuild/linux-loong64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz#127b3fbfb2c2e08b1397e985932f718f09a8f5c4" + integrity sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ== + +"@esbuild/linux-mips64el@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz#837d1449517791e3fa7d82675a2d06d9f56cb340" + integrity sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw== + +"@esbuild/linux-ppc64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz#aa2e3bd93ab8df084212f1895ca4b03c42d9e0fe" + integrity sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ== + +"@esbuild/linux-riscv64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz#a340620e31093fef72767dd28ab04214b3442083" + integrity sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg== + +"@esbuild/linux-s390x@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz#ddfed266c8c13f5efb3105a0cd47f6dcd0e79e71" + integrity sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg== + +"@esbuild/linux-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz#9a4f78c75c051e8c060183ebb39a269ba936a2ac" + integrity sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ== + +"@esbuild/netbsd-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz#902c80e1d678047926387230bc037e63e00697d0" + integrity sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw== + +"@esbuild/netbsd-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz#2d9eb4692add2681ff05a14ce99de54fbed7079c" + integrity sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg== + +"@esbuild/openbsd-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz#89c3b998c6de739db38ab7fb71a8a76b3fa84a45" + integrity sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ== + +"@esbuild/openbsd-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz#2f01615cf472b0e48c077045cfd96b5c149365cc" + integrity sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ== + +"@esbuild/openharmony-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz#a201f720cd2c3ebf9a6033fcc3feb069a54b509a" + integrity sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg== + +"@esbuild/sunos-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz#07046c977985a3334667f19e6ab3a01a80862afb" + integrity sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w== + +"@esbuild/win32-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz#4a5470caf0d16127c05d4833d4934213c69392d1" + integrity sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ== + +"@esbuild/win32-ia32@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz#3de3e8470b7b328d99dbc3e9ec1eace207e5bbc4" + integrity sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg== + +"@esbuild/win32-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz#610d7ea539d2fcdbe39237b5cc175eb2c4451f9c" + integrity sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw== + "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.7.0": version "4.7.0" resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz" @@ -3378,7 +3535,7 @@ "@octokit/core@^3.5.1", "@octokit/core@^3.6.0": version "3.6.0" - resolved "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz" + resolved "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz#3376cb9f3008d9b3d110370d90e0a1fcd5fe6085" integrity sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q== dependencies: "@octokit/auth-token" "^2.4.4" @@ -3389,6 +3546,7 @@ before-after-hook "^2.2.0" universal-user-agent "^6.0.0" +"@octokit/core@^5.0.2": version "5.2.2" resolved "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz#252805732de9b4e8e4f658d34b80c4c9b2534761" integrity sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg== @@ -3627,11 +3785,13 @@ "@sinclair/typebox@^0.27.8": version "0.27.8" - resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz" + resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== - version "0.34.38" - resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz#2365df7c23406a4d79413a766567bfbca708b49d" - integrity sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA== + +"@sinclair/typebox@^0.34.0": + version "0.34.40" + resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.40.tgz#740056ea8d8aaada2ac1ce414c2f074798283b92" + integrity sha512-gwBNIP8ZAYev/ORDWW0QvxdwPXwxBtLsdsJgSc7eDIRt8ubP+rxUBzPsrwnu16fgEF8Bx4lh/+mvQvJzcTM6Kw== "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.1": version "1.8.6" @@ -4594,7 +4754,7 @@ dependencies: "@typescript-eslint/types" "8.38.0" "@typescript-eslint/visitor-keys" "8.38.0" - + "@typescript-eslint/tsconfig-utils@8.38.0", "@typescript-eslint/tsconfig-utils@^8.38.0": version "8.38.0" resolved "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.38.0.tgz#6de4ce224a779601a8df667db56527255c42c4d0" @@ -5090,6 +5250,13 @@ aws-cdk@2.1023.0: optionalDependencies: fsevents "2.3.2" +aws-cdk@2.1025.0: + version "2.1025.0" + resolved "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1025.0.tgz#6887de917cc6ab3aaee121b919a68d40d31708e0" + integrity sha512-qKYM+RG5+U/UbGpjTt8ZaxBEfKJMPdOmtPtFNidsIGlrdIWSIFdNcFYi13zo33FkMk6ZFA6yBnjfDry3fNR+hQ== + optionalDependencies: + fsevents "2.3.2" + aws-sdk-client-mock-jest@4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/aws-sdk-client-mock-jest/-/aws-sdk-client-mock-jest-4.1.0.tgz" @@ -9118,7 +9285,7 @@ jsesc@^3.0.2: version "3.1.0" resolved "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz" integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== - + jsii-diff@1.113.0: version "1.113.0" resolved "https://registry.npmjs.org/jsii-diff/-/jsii-diff-1.113.0.tgz#fe326ce10b7c9f95f157dc8ad8b75eda95a344b0" @@ -9130,7 +9297,7 @@ jsii-diff@1.113.0: jsii-reflect "^1.113.0" log4js "^6.9.1" yargs "^16.2.0" - + jsii-pacmak@1.113.0: version "1.113.0" resolved "https://registry.npmjs.org/jsii-pacmak/-/jsii-pacmak-1.113.0.tgz#98a70008546a63e73e68a0a2deabbc8b5c4b6aa4" @@ -12902,6 +13069,11 @@ undici-types@~5.26.4: resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +undici-types@~7.8.0: + version "7.8.0" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz#de00b85b710c54122e44fbfd911f8d70174cd294" + integrity sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw== + undici@^5.25.4: version "5.29.0" resolved "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz" From 585defee3e83e403d935916ce85ca2af81a91db1 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 19 Aug 2025 15:54:36 +0200 Subject: [PATCH 18/26] Final touches --- tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts b/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts index 3dd05a9694284..e1c8459dbade0 100644 --- a/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts +++ b/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts @@ -95,6 +95,10 @@ export function attributePropertyName(attrName: string) { * Make sure the resource name is included in the property */ export function referencePropertyName(propName: string, resourceName: string) { + // Some primaryIdentifier components are structurally deep, like AWS::QuickSight::RefreshSchedule's + // 'schedule/scheduleId', or AWS::S3::StorageLens's `configuration/id`. Only return the last part. + propName = propName.split('/').pop() ?? propName; + if (['arn', 'id', 'name', 'url'].includes(propName.toLowerCase())) { return `${camelcase(resourceName)}${propName.charAt(0).toUpperCase()}${propName.slice(1)}`; } From e9df3222c9d7314374702d557ccaa376f98e5b9b Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 19 Aug 2025 16:59:08 +0200 Subject: [PATCH 19/26] Update tests --- .../test/__snapshots__/resources.test.ts.snap | 37 +++---------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap index 65a9e47c20f1b..58a5e3e45f94c 100644 --- a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap +++ b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap @@ -415,7 +415,7 @@ export class CfnSomething extends cdk.CfnResource implements cdk.IInspectable, I public get somethingRef(): SomethingRef { return { "somethingId": this.ref, - "attrSomethingArn": this.attrSomethingArn + "somethingArn": this.attrSomethingArn }; } @@ -464,14 +464,7 @@ export interface SomethingRef { /** * The ARN of the Something resource. */ - readonly attrSomethingArn: string; - - /** - * The arn for something - * - * @cloudformationAttribute SomethingArn - */ - readonly attrSomethingArn: string; + readonly somethingArn: string; } /** @@ -597,7 +590,7 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR public get resourceRef(): ResourceRef { return { "resourceId": this.ref, - "attrArn": this.attrArn + "resourceArn": this.attrArn }; } @@ -646,14 +639,7 @@ export interface ResourceRef { /** * The ARN of the Resource resource. */ - readonly attrArn: string; - - /** - * The arn for the resource - * - * @cloudformationAttribute Arn - */ - readonly attrArn: string; + readonly resourceArn: string; } /** @@ -948,8 +934,7 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR public get resourceRef(): ResourceRef { return { - "resourceArn": this.ref, - "attrArn": this.attrArn + "resourceArn": this.ref }; } @@ -994,18 +979,6 @@ export interface ResourceRef { * The Arn of the Resource resource. */ readonly resourceArn: string; - - /** - * The ARN of the Resource resource. - */ - readonly attrArn: string; - - /** - * The arn of the resource - * - * @cloudformationAttribute Arn - */ - readonly attrArn: string; } /** From d8825afc034f7d65cd87050544de5404fefefe93 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 20 Aug 2025 11:44:53 +0200 Subject: [PATCH 20/26] Updates --- tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts | 4 ++-- tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts | 4 ++++ tools/@aws-cdk/spec2cdk/test/conventions.test.ts | 13 +++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 tools/@aws-cdk/spec2cdk/test/conventions.test.ts diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts index d825779f82e36..a8db9a5c4c041 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-decider.ts @@ -4,7 +4,7 @@ import { CDK_CORE } from './cdk'; import { PropertyMapping } from './cloudformation-mapping'; import { NON_RESOLVABLE_PROPERTY_NAMES, TaggabilityStyle, resourceTaggabilityStyle } from './tagging'; import { TypeConverter } from './type-converter'; -import { attributePropertyName, cloudFormationDocLink, propertyNameFromCloudFormation, referencePropertyName } from '../naming'; +import { attributePropertyName, camelcasedResourceName, cloudFormationDocLink, propertyNameFromCloudFormation, referencePropertyName } from '../naming'; import { splitDocumentation } from '../util'; // This convenience typewriter builder is used all over the place @@ -48,7 +48,7 @@ export class ResourceDecider { public readonly camelResourceName: string; constructor(private readonly resource: Resource, private readonly converter: TypeConverter) { - this.camelResourceName = this.resource.name.charAt(0).toLowerCase() + this.resource.name.slice(1); + this.camelResourceName = camelcasedResourceName(resource); this.taggability = resourceTaggabilityStyle(this.resource); this.convertProperties(); diff --git a/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts b/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts index e1c8459dbade0..e290eb1ae1cdf 100644 --- a/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts +++ b/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts @@ -47,6 +47,10 @@ export function structNameFromTypeDefinition(def: TypeDefinition) { return `${def.name}Property`; } +export function camelcasedResourceName(res: Resource, suffix?: string) { + return `${camelcase(res.name)}${suffix ?? ''}`; +} + export function classNameFromResource(res: Resource, suffix?: string) { return `Cfn${res.name}${suffix ?? ''}`; } diff --git a/tools/@aws-cdk/spec2cdk/test/conventions.test.ts b/tools/@aws-cdk/spec2cdk/test/conventions.test.ts new file mode 100644 index 0000000000000..8ddb28d7a69c4 --- /dev/null +++ b/tools/@aws-cdk/spec2cdk/test/conventions.test.ts @@ -0,0 +1,13 @@ +import { camelcasedResourceName } from '../lib/naming'; + +test('test the ref-naminification of OIDCProvider', () => { + const name = camelcasedResourceName({ + name: 'OIDCProvider', + cloudFormationType: 'AWS::IAM::OIDCProvider', + attributes: {}, + properties: {}, + $id: '', + }); + + expect(name).toEqual('oidcProvider'); +}); From 0e519614a652f369520fd0291cf587ef31d0d022 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Mon, 25 Aug 2025 17:17:03 +0200 Subject: [PATCH 21/26] Add IConstruct --- tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts index 729685d7fd186..8d64a3c61df5e 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts @@ -63,6 +63,7 @@ export class ResourceClass extends ClassType { refInterface = new InterfaceType(scope, { export: true, name: `I${resource.name}${suffix ?? ''}Ref`, + extends: [CONSTRUCTS.IConstruct], docs: { summary: `Indicates that this resource can be referenced as a ${resource.name}.`, }, From 6b1941ef2a1cb4d2bfc740478c5ce0f91c8a544b Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Fri, 29 Aug 2025 12:50:16 +0100 Subject: [PATCH 22/26] NameRef -> NameReference in ResourceClass --- tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts index 8d64a3c61df5e..0887297a61fcd 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts @@ -182,7 +182,7 @@ export class ResourceClass extends ClassType { // BucketRef { bucketName, bucketArn } const refPropsStruct = new StructType(this.scope, { export: true, - name: `${this.resource.name}${this.suffix ?? ''}Ref`, + name: `${this.resource.name}${this.suffix ?? ''}Reference`, docs: { summary: `A reference to a ${this.resource.name} resource.`, stability: Stability.External, From 601b8d58cfbba349801237e42b5998fb3f764cd5 Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Mon, 1 Sep 2025 15:47:46 +0100 Subject: [PATCH 23/26] Experimental --- packages/awslint/lib/rules/docs.ts | 4 ++++ tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/packages/awslint/lib/rules/docs.ts b/packages/awslint/lib/rules/docs.ts index ed70eda0273b8..5de5306098019 100644 --- a/packages/awslint/lib/rules/docs.ts +++ b/packages/awslint/lib/rules/docs.ts @@ -84,6 +84,10 @@ docsLinter.add({ if (isModuleExperimental(e.ctx.assembly)) { return; } + if ((e.ctx.kind === 'type' && CoreTypes.isCfnType(e.ctx.documentable)) + || (e.ctx.kind === 'interface-property' && CoreTypes.isCfnType(e.ctx.containingType))) { + return; + } const sym = e.ctx.documentable; e.assert(sym.docs.docs.stability !== Stability.Experimental, e.ctx.errorKey); }, diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts index 0887297a61fcd..68c275885ef26 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts @@ -66,6 +66,7 @@ export class ResourceClass extends ClassType { extends: [CONSTRUCTS.IConstruct], docs: { summary: `Indicates that this resource can be referenced as a ${resource.name}.`, + stability: Stability.Experimental, }, }); } From 345907cc78790e8d525b0a9b5ac78809b2a02ffe Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Mon, 1 Sep 2025 16:21:56 +0100 Subject: [PATCH 24/26] Update snapshots --- .../test/__snapshots__/resources.test.ts.snap | 90 +++++++++++-------- 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap index 58a5e3e45f94c..b894cf0c9fdb7 100644 --- a/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap +++ b/tools/@aws-cdk/spec2cdk/test/__snapshots__/resources.test.ts.snap @@ -9,12 +9,14 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** * Indicates that this resource can be referenced as a Resource. + * + * @stability experimental */ -export interface IResourceRef { +export interface IResourceRef extends constructs.IConstruct { /** * A reference to a Resource resource. */ - readonly resourceRef: ResourceRef; + readonly resourceRef: ResourceReference; } /** @@ -71,7 +73,7 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR this.id = props.id; } - public get resourceRef(): ResourceRef { + public get resourceRef(): ResourceReference { return { "resourceId": this.ref }; @@ -120,7 +122,7 @@ export interface CfnResourceProps { * @struct * @stability external */ -export interface ResourceRef { +export interface ResourceReference { /** * The Id of the Resource resource. */ @@ -179,12 +181,14 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** * Indicates that this resource can be referenced as a Resource. + * + * @stability experimental */ -export interface IResourceRef { +export interface IResourceRef extends constructs.IConstruct { /** * A reference to a Resource resource. */ - readonly resourceRef: ResourceRef; + readonly resourceRef: ResourceReference; } /** @@ -243,7 +247,7 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR this.attrId = cdk.Token.asString(this.getAtt("Id", cdk.ResolutionTypeHint.STRING)); } - public get resourceRef(): ResourceRef { + public get resourceRef(): ResourceReference { return { "resourceId": this.ref }; @@ -285,7 +289,7 @@ export interface CfnResourceProps { * @struct * @stability external */ -export interface ResourceRef { +export interface ResourceReference { /** * The Id of the Resource resource. */ @@ -340,12 +344,14 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** * Indicates that this resource can be referenced as a Something. + * + * @stability experimental */ -export interface ISomethingRef { +export interface ISomethingRef extends constructs.IConstruct { /** * A reference to a Something resource. */ - readonly somethingRef: SomethingRef; + readonly somethingRef: SomethingReference; } /** @@ -412,7 +418,7 @@ export class CfnSomething extends cdk.CfnResource implements cdk.IInspectable, I this.attrSomethingArn = cdk.Token.asString(this.getAtt("SomethingArn", cdk.ResolutionTypeHint.STRING)); } - public get somethingRef(): SomethingRef { + public get somethingRef(): SomethingReference { return { "somethingId": this.ref, "somethingArn": this.attrSomethingArn @@ -455,7 +461,7 @@ export interface CfnSomethingProps { * @struct * @stability external */ -export interface SomethingRef { +export interface SomethingReference { /** * The Id of the Something resource. */ @@ -515,12 +521,14 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** * Indicates that this resource can be referenced as a Resource. + * + * @stability experimental */ -export interface IResourceRef { +export interface IResourceRef extends constructs.IConstruct { /** * A reference to a Resource resource. */ - readonly resourceRef: ResourceRef; + readonly resourceRef: ResourceReference; } /** @@ -587,7 +595,7 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR this.attrId = cdk.Token.asString(this.getAtt("Id", cdk.ResolutionTypeHint.STRING)); } - public get resourceRef(): ResourceRef { + public get resourceRef(): ResourceReference { return { "resourceId": this.ref, "resourceArn": this.attrArn @@ -630,7 +638,7 @@ export interface CfnResourceProps { * @struct * @stability external */ -export interface ResourceRef { +export interface ResourceReference { /** * The Id of the Resource resource. */ @@ -690,12 +698,14 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** * Indicates that this resource can be referenced as a Resource. + * + * @stability experimental */ -export interface IResourceRef { +export interface IResourceRef extends constructs.IConstruct { /** * A reference to a Resource resource. */ - readonly resourceRef: ResourceRef; + readonly resourceRef: ResourceReference; } /** @@ -760,7 +770,7 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR this.arn = props.arn; } - public get resourceRef(): ResourceRef { + public get resourceRef(): ResourceReference { return { "resourceId": this.ref }; @@ -809,7 +819,7 @@ export interface CfnResourceProps { * @struct * @stability external */ -export interface ResourceRef { +export interface ResourceReference { /** * The Id of the Resource resource. */ @@ -868,12 +878,14 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** * Indicates that this resource can be referenced as a Resource. + * + * @stability experimental */ -export interface IResourceRef { +export interface IResourceRef extends constructs.IConstruct { /** * A reference to a Resource resource. */ - readonly resourceRef: ResourceRef; + readonly resourceRef: ResourceReference; } /** @@ -932,7 +944,7 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR this.attrArn = cdk.Token.asString(this.getAtt("Arn", cdk.ResolutionTypeHint.STRING)); } - public get resourceRef(): ResourceRef { + public get resourceRef(): ResourceReference { return { "resourceArn": this.ref }; @@ -974,7 +986,7 @@ export interface CfnResourceProps { * @struct * @stability external */ -export interface ResourceRef { +export interface ResourceReference { /** * The Arn of the Resource resource. */ @@ -1029,12 +1041,14 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** * Indicates that this resource can be referenced as a Resource. + * + * @stability experimental */ -export interface IResourceRef { +export interface IResourceRef extends constructs.IConstruct { /** * A reference to a Resource resource. */ - readonly resourceRef: ResourceRef; + readonly resourceRef: ResourceReference; } /** @@ -1101,7 +1115,7 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR this.attrId = cdk.Token.asString(this.getAtt("Id", cdk.ResolutionTypeHint.STRING)); } - public get resourceRef(): ResourceRef { + public get resourceRef(): ResourceReference { return { "resourceId": cdk.Fn.select(0, cdk.Fn.split("|", this.ref)), "another": cdk.Fn.select(1, cdk.Fn.split("|", this.ref)) @@ -1144,7 +1158,7 @@ export interface CfnResourceProps { * @struct * @stability external */ -export interface ResourceRef { +export interface ResourceReference { /** * The Id of the Resource resource. */ @@ -1204,12 +1218,14 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** * Indicates that this resource can be referenced as a Resource. + * + * @stability experimental */ -export interface IResourceRef { +export interface IResourceRef extends constructs.IConstruct { /** * A reference to a Resource resource. */ - readonly resourceRef: ResourceRef; + readonly resourceRef: ResourceReference; } /** @@ -1272,7 +1288,7 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR this.id = props.id; } - public get resourceRef(): ResourceRef { + public get resourceRef(): ResourceReference { return { "resourceId": cdk.Fn.select(0, cdk.Fn.split("|", this.ref)), "anotherId": cdk.Fn.select(1, cdk.Fn.split("|", this.ref)) @@ -1330,7 +1346,7 @@ export interface CfnResourceProps { * @struct * @stability external */ -export interface ResourceRef { +export interface ResourceReference { /** * The Id of the Resource resource. */ @@ -1397,12 +1413,14 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors"; /** * Indicates that this resource can be referenced as a Resource. + * + * @stability experimental */ -export interface IResourceRef { +export interface IResourceRef extends constructs.IConstruct { /** * A reference to a Resource resource. */ - readonly resourceRef: ResourceRef; + readonly resourceRef: ResourceReference; } /** @@ -1459,7 +1477,7 @@ export class CfnResource extends cdk.CfnResource implements cdk.IInspectable, IR this.id = props.id; } - public get resourceRef(): ResourceRef { + public get resourceRef(): ResourceReference { return { "resourceId": this.ref }; @@ -1508,7 +1526,7 @@ export interface CfnResourceProps { * @struct * @stability external */ -export interface ResourceRef { +export interface ResourceReference { /** * The Id of the Resource resource. */ From 9e82000c4beb135e2474ffd9abf6e947fdbe3544 Mon Sep 17 00:00:00 2001 From: Rico Hermans Date: Tue, 2 Sep 2025 10:13:32 +0200 Subject: [PATCH 25/26] feat: implement new shared interfaces for L2 resources (ref-interfaces #2) (#35271) Implementing the interfaces from https://github.com/aws/aws-cdk/pull/35032 for L2s. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --------- Co-authored-by: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> --- ...integ.pipeline-elastic-beanstalk-deploy.ts | 38 +++++---- .../test/databrew/integ.start-job-run.ts | 23 +++++- .../@aws-cdk/aws-ec2-alpha/lib/subnet-v2.ts | 26 +++++- .../@aws-cdk/aws-ec2-alpha/lib/vpc-v2-base.ts | 48 ++++++++++- .../aws-cdk-lib/aws-apigateway/lib/api-key.ts | 10 ++- .../aws-apigateway/lib/domain-name.ts | 17 +++- .../aws-apigateway/lib/gateway-response.ts | 24 +++++- .../aws-apigateway/lib/resource.ts | 13 ++- .../aws-cdk-lib/aws-apigateway/lib/restapi.ts | 23 +++++- .../aws-cdk-lib/aws-apigateway/lib/stage.ts | 13 ++- .../aws-apigateway/lib/usage-plan.ts | 10 ++- .../aws-apigateway/lib/vpc-link.ts | 10 ++- .../test/integ-assets/appsync-js-pipeline.js | 10 +-- .../test/integ-assets/appsync-js-resolver.js | 23 +----- .../js-resolver-assertion/index.js | 30 ++----- .../verify/eventapi-lambda-direct/handler.js | 21 +---- .../test/verify/eventapi-lambda-ds/handler.js | 5 +- .../test/verify/iam-query/iam-query.js | 38 +-------- .../verify/lambda-tutorial/lambda-tutorial.js | 71 +--------------- .../aws-cloudfront/lib/cache-policy.ts | 30 ++++++- .../aws-cloudfront/lib/distribution.ts | 28 ++++++- .../lib/experimental/edge-function.ts | 13 +++ .../aws-cloudfront/lib/function.ts | 10 ++- .../aws-cloudfront/lib/key-group.ts | 10 ++- .../aws-cloudfront/lib/key-value-store.ts | 12 ++- .../lib/origin-access-identity.ts | 14 +++- .../lib/origin-request-policy.ts | 18 +++- .../aws-cloudfront/lib/public-key.ts | 9 +- .../aws-cloudfront/lib/realtime-log-config.ts | 6 +- .../lib/response-headers-policy.ts | 24 +++++- .../aws-cloudfront/lib/vpc-origin.ts | 23 +++++- .../aws-cloudfront/lib/web-distribution.ts | 19 ++++- .../lib/elastic-beanstalk/deploy-action.ts | 14 +++- .../aws-cdk-lib/aws-ec2/lib/bastion-host.ts | 8 +- .../aws-ec2/lib/client-vpn-endpoint-types.ts | 3 +- .../aws-ec2/lib/client-vpn-endpoint.ts | 25 +++++- packages/aws-cdk-lib/aws-ec2/lib/instance.ts | 26 +++++- packages/aws-cdk-lib/aws-ec2/lib/key-pair.ts | 20 ++++- .../aws-ec2/lib/launch-template.ts | 24 +++++- .../aws-cdk-lib/aws-ec2/lib/network-acl.ts | 33 ++++++-- .../aws-ec2/lib/placement-group.ts | 15 +++- .../aws-cdk-lib/aws-ec2/lib/prefix-list.ts | 26 +++++- .../aws-cdk-lib/aws-ec2/lib/security-group.ts | 23 +++++- packages/aws-cdk-lib/aws-ec2/lib/volume.ts | 25 +++++- .../aws-ec2/lib/vpc-endpoint-service.ts | 13 ++- .../aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts | 15 +++- .../aws-cdk-lib/aws-ec2/lib/vpc-flow-logs.ts | 22 ++++- packages/aws-cdk-lib/aws-ec2/lib/vpc.ts | 82 ++++++++++++++++--- packages/aws-cdk-lib/aws-ec2/lib/vpn.ts | 15 +++- .../aws-cdk-lib/aws-iam/lib/access-key.ts | 6 +- packages/aws-cdk-lib/aws-iam/lib/group.ts | 11 ++- .../aws-iam/lib/instance-profile.ts | 13 ++- packages/aws-cdk-lib/aws-iam/lib/lazy-role.ts | 5 ++ .../aws-cdk-lib/aws-iam/lib/managed-policy.ts | 32 +++++++- .../aws-iam/lib/oidc-provider-native.ts | 16 +++- .../aws-cdk-lib/aws-iam/lib/oidc-provider.ts | 23 ++++-- packages/aws-cdk-lib/aws-iam/lib/policy.ts | 15 +++- .../aws-iam/lib/private/immutable-role.ts | 8 ++ .../aws-iam/lib/private/imported-role.ts | 20 ++++- .../aws-iam/lib/private/precreated-role.ts | 8 ++ packages/aws-cdk-lib/aws-iam/lib/role.ts | 43 ++++++++-- .../aws-cdk-lib/aws-iam/lib/saml-provider.ts | 11 ++- packages/aws-cdk-lib/aws-iam/lib/user.ts | 18 +++- .../aws-iam/test/custom-resource/index.js | 1 + packages/aws-cdk-lib/aws-kms/lib/alias.ts | 24 +++++- packages/aws-cdk-lib/aws-kms/lib/key.ts | 11 ++- packages/aws-cdk-lib/aws-lambda/lib/alias.ts | 16 +++- .../aws-lambda/lib/code-signing-config.ts | 16 +++- .../aws-lambda/lib/event-source-mapping.ts | 18 +++- .../aws-lambda/lib/function-base.ts | 25 +++++- .../aws-lambda/lib/lambda-version.ts | 22 ++++- packages/aws-cdk-lib/aws-lambda/lib/layers.ts | 15 +++- .../aws-cdk-lib/aws-s3/lib/bucket-policy.ts | 8 +- packages/aws-cdk-lib/aws-s3/lib/bucket.ts | 19 +++-- packages/awslint/lib/rules/resource.ts | 6 ++ 75 files changed, 1088 insertions(+), 380 deletions(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-codepipeline-actions/test/integ.pipeline-elastic-beanstalk-deploy.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-codepipeline-actions/test/integ.pipeline-elastic-beanstalk-deploy.ts index ef7e08a3123b5..57610933c508b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-codepipeline-actions/test/integ.pipeline-elastic-beanstalk-deploy.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-codepipeline-actions/test/integ.pipeline-elastic-beanstalk-deploy.ts @@ -2,11 +2,13 @@ import * as path from 'path'; import * as codepipeline from 'aws-cdk-lib/aws-codepipeline'; import * as elasticbeanstalk from 'aws-cdk-lib/aws-elasticbeanstalk'; import * as iam from 'aws-cdk-lib/aws-iam'; +import { IManagedPolicy, ManagedPolicyReference } from 'aws-cdk-lib/aws-iam'; import * as s3 from 'aws-cdk-lib/aws-s3'; import * as deploy from 'aws-cdk-lib/aws-s3-deployment'; -import { App, Fn, RemovalPolicy, Stack } from 'aws-cdk-lib'; +import { App, Fn, RemovalPolicy, Stack, UnscopedValidationError } from 'aws-cdk-lib'; import * as integ from '@aws-cdk/integ-tests-alpha'; import * as cpactions from 'aws-cdk-lib/aws-codepipeline-actions'; +import { Node } from 'constructs'; /** * To validate that the deployment actually succeeds, perform the following actions: @@ -43,16 +45,26 @@ const artifact = new deploy.BucketDeployment(stack, 'DeployApp', { extract: false, }); +function makePolicy(arn: string): IManagedPolicy { + return { + managedPolicyArn: arn, + get managedPolicyRef(): ManagedPolicyReference { + return { + policyArn: this.managedPolicyArn, + }; + }, + get node(): Node { + throw new UnscopedValidationError('The result of fromAwsManagedPolicyName can not be used in this API'); + }, + }; +} + const serviceRole = new iam.Role(stack, 'service-role', { roleName: 'codepipeline-elasticbeanstalk-action-test-serivce-role', assumedBy: new iam.ServicePrincipal('elasticbeanstalk.amazonaws.com'), managedPolicies: [ - { - managedPolicyArn: 'arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkEnhancedHealth', - }, - { - managedPolicyArn: 'arn:aws:iam::aws:policy/AWSElasticBeanstalkManagedUpdatesCustomerRolePolicy', - }, + makePolicy('arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkEnhancedHealth'), + makePolicy('arn:aws:iam::aws:policy/AWSElasticBeanstalkManagedUpdatesCustomerRolePolicy'), ], }); @@ -60,15 +72,9 @@ const instanceProfileRole = new iam.Role(stack, 'instance-profile-role', { roleName: 'codepipeline-elasticbeanstalk-action-test-instance-profile-role', assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'), managedPolicies: [ - { - managedPolicyArn: 'arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier', - }, - { - managedPolicyArn: 'arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker', - }, - { - managedPolicyArn: 'arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier', - }, + makePolicy('arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier'), + makePolicy('arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker'), + makePolicy('arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier'), ], }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/databrew/integ.start-job-run.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/databrew/integ.start-job-run.ts index 4d4634c39ea84..3bba2d26fae1e 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/databrew/integ.start-job-run.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/databrew/integ.start-job-run.ts @@ -1,9 +1,12 @@ import * as databrew from 'aws-cdk-lib/aws-databrew'; import * as iam from 'aws-cdk-lib/aws-iam'; +import { IManagedPolicy, ManagedPolicyReference } from 'aws-cdk-lib/aws-iam'; import * as s3 from 'aws-cdk-lib/aws-s3'; import * as sfn from 'aws-cdk-lib/aws-stepfunctions'; import * as cdk from 'aws-cdk-lib'; +import { UnscopedValidationError } from 'aws-cdk-lib'; import { GlueDataBrewStartJobRun } from 'aws-cdk-lib/aws-stepfunctions-tasks'; +import { Node } from 'constructs'; /* * Stack verification steps: @@ -11,6 +14,20 @@ import { GlueDataBrewStartJobRun } from 'aws-cdk-lib/aws-stepfunctions-tasks'; * * aws stepfunctions describe-execution --execution-arn : should return status as SUCCEEDED */ +function makePolicy(arn: string): IManagedPolicy { + return { + managedPolicyArn: arn, + get managedPolicyRef(): ManagedPolicyReference { + return { + policyArn: this.managedPolicyArn, + }; + }, + get node(): Node { + throw new UnscopedValidationError('The result of fromAwsManagedPolicyName can not be used in this API'); + }, + }; +} + class GlueDataBrewJobStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props: cdk.StackProps = {}) { super(scope, id, props); @@ -22,9 +39,9 @@ class GlueDataBrewJobStack extends cdk.Stack { }); const role = new iam.Role(this, 'DataBrew Role', { - managedPolicies: [{ - managedPolicyArn: 'arn:aws:iam::aws:policy/service-role/AWSGlueDataBrewServiceRole', - }], + managedPolicies: [ + makePolicy('arn:aws:iam::aws:policy/service-role/AWSGlueDataBrewServiceRole'), + ], path: '/', assumedBy: new iam.ServicePrincipal('databrew.amazonaws.com'), inlinePolicies: { diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/subnet-v2.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/subnet-v2.ts index 08ac4b2f42002..264f816f7f5a4 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/subnet-v2.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/subnet-v2.ts @@ -1,11 +1,21 @@ -import { Resource, Names, Lazy, Tags, Token, ValidationError, UnscopedValidationError } from 'aws-cdk-lib'; -import { CfnSubnet, CfnSubnetRouteTableAssociation, INetworkAcl, IRouteTable, ISubnet, NetworkAcl, SubnetNetworkAclAssociation, SubnetType } from 'aws-cdk-lib/aws-ec2'; +import { Lazy, Names, Resource, Tags, Token, UnscopedValidationError, ValidationError } from 'aws-cdk-lib'; +import { + CfnSubnet, + CfnSubnetRouteTableAssociation, + INetworkAcl, + IRouteTable, + ISubnet, + NetworkAcl, + SubnetNetworkAclAssociation, + SubnetType, +} from 'aws-cdk-lib/aws-ec2'; import { Construct, DependencyGroup, IDependable } from 'constructs'; import { IVpcV2 } from './vpc-v2-base'; import { CidrBlock, CidrBlockIpv6, defaultSubnetName } from './util'; import { RouteTable } from './route'; import { addConstructMetadata, MethodMetadata } from 'aws-cdk-lib/core/lib/metadata-resource'; import { propertyInjectable } from 'aws-cdk-lib/core/lib/prop-injectable'; +import { SubnetReference } from 'aws-cdk-lib/aws-ec2/lib/ec2.generated'; /** * Interface to define subnet CIDR @@ -194,6 +204,12 @@ export class SubnetV2 extends Resource implements ISubnetV2 { */ public readonly routeTable: IRouteTable = { routeTableId: attrs.routeTableId! }; + public get subnetRef(): SubnetReference { + return { + subnetId: this.subnetId, + }; + } + /** * Associate a Network ACL with this subnet * Required here since it is implemented in the ISubnetV2 @@ -245,6 +261,12 @@ export class SubnetV2 extends Resource implements ISubnetV2 { */ public readonly ipv6CidrBlock?: string; + public get subnetRef(): SubnetReference { + return { + subnetId: this.subnetId, + }; + } + /** * The type of subnet (public or private) that this subnet represents. * @attribute SubnetType diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2-base.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2-base.ts index 2b5fd5877ceba..cd361285acff3 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2-base.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2-base.ts @@ -1,11 +1,45 @@ -import { Aws, Resource, Annotations, ValidationError } from 'aws-cdk-lib'; -import { IVpc, ISubnet, SubnetSelection, SelectedSubnets, EnableVpnGatewayOptions, VpnGateway, VpnConnectionType, CfnVPCGatewayAttachment, CfnVPNGatewayRoutePropagation, VpnConnectionOptions, VpnConnection, ClientVpnEndpointOptions, ClientVpnEndpoint, InterfaceVpcEndpointOptions, InterfaceVpcEndpoint, GatewayVpcEndpointOptions, GatewayVpcEndpoint, FlowLogOptions, FlowLog, FlowLogResourceType, SubnetType, SubnetFilter } from 'aws-cdk-lib/aws-ec2'; +import { Annotations, Aws, Resource, ValidationError } from 'aws-cdk-lib'; +import { + CfnVPCGatewayAttachment, + CfnVPNGatewayRoutePropagation, + ClientVpnEndpoint, + ClientVpnEndpointOptions, + EnableVpnGatewayOptions, + FlowLog, + FlowLogOptions, + FlowLogResourceType, + GatewayVpcEndpoint, + GatewayVpcEndpointOptions, + InterfaceVpcEndpoint, + InterfaceVpcEndpointOptions, + ISubnet, + IVpc, + SelectedSubnets, + SubnetFilter, + SubnetSelection, + SubnetType, + VpnConnection, + VpnConnectionOptions, + VpnConnectionType, + VpnGateway, +} from 'aws-cdk-lib/aws-ec2'; import { allRouteTableIds, flatten, subnetGroupNameFromConstructId } from './util'; -import { IDependable, Dependable, IConstruct, DependencyGroup } from 'constructs'; -import { EgressOnlyInternetGateway, InternetGateway, NatConnectivityType, NatGateway, NatGatewayOptions, Route, VPCPeeringConnection, VPCPeeringConnectionOptions, VPNGatewayV2 } from './route'; +import { Dependable, DependencyGroup, IConstruct, IDependable } from 'constructs'; +import { + EgressOnlyInternetGateway, + InternetGateway, + NatConnectivityType, + NatGateway, + NatGatewayOptions, + Route, + VPCPeeringConnection, + VPCPeeringConnectionOptions, + VPNGatewayV2, +} from './route'; import { ISubnetV2 } from './subnet-v2'; import { AccountPrincipal, Effect, PolicyStatement, Role } from 'aws-cdk-lib/aws-iam'; import { IVPCCidrBlock } from './vpc-v2'; +import { VPCReference } from 'aws-cdk-lib/aws-ec2/lib/ec2.generated'; /** * Options to define EgressOnlyInternetGateway for VPC @@ -327,6 +361,12 @@ export abstract class VpcV2Base extends Resource implements IVpcV2 { }; } + public get vpcRef(): VPCReference { + return { + vpcId: this.vpcId, + }; + } + /** * Adds a VPN Gateway to this VPC * @deprecated use enableVpnGatewayV2 for compatibility with VPCV2.Route diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/api-key.ts b/packages/aws-cdk-lib/aws-apigateway/lib/api-key.ts index 4b64d47d74e88..476fbfc88e3ec 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/api-key.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/api-key.ts @@ -1,5 +1,5 @@ import { Construct } from 'constructs'; -import { CfnApiKey } from './apigateway.generated'; +import { ApiKeyReference, CfnApiKey, IApiKeyRef } from './apigateway.generated'; import { ResourceOptions } from './resource'; import { IRestApi } from './restapi'; import { IStage } from './stage'; @@ -14,7 +14,7 @@ import { propertyInjectable } from '../../core/lib/prop-injectable'; * API keys are alphanumeric string values that you distribute to * app developer customers to grant access to your API */ -export interface IApiKey extends IResourceBase { +export interface IApiKey extends IResourceBase, IApiKeyRef { /** * The API key ID. * @attribute @@ -138,6 +138,12 @@ abstract class ApiKeyBase extends Resource implements IApiKey { resourceArns: [this.keyArn], }); } + + public get apiKeyRef(): ApiKeyReference { + return { + apiKeyId: this.keyId, + }; + } } /** diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/domain-name.ts b/packages/aws-cdk-lib/aws-apigateway/lib/domain-name.ts index f55bf1a809e29..947aa702669ee 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/domain-name.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/domain-name.ts @@ -1,12 +1,12 @@ import { Construct } from 'constructs'; -import { CfnDomainName } from './apigateway.generated'; +import { CfnDomainName, DomainNameReference, IDomainNameRef } from './apigateway.generated'; import { BasePathMapping, BasePathMappingOptions } from './base-path-mapping'; import { EndpointType, IRestApi } from './restapi'; import { IStage } from './stage'; import * as apigwv2 from '../../aws-apigatewayv2'; import * as acm from '../../aws-certificatemanager'; import { IBucket } from '../../aws-s3'; -import { IResource, Names, Resource, Token } from '../../core'; +import { Arn, IResource, Names, Resource, Stack, Token } from '../../core'; import { ValidationError } from '../../core/lib/errors'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; @@ -94,7 +94,7 @@ export interface DomainNameProps extends DomainNameOptions { readonly mapping?: IRestApi; } -export interface IDomainName extends IResource { +export interface IDomainName extends IResource, IDomainNameRef { /** * The domain name (e.g. `example.com`) * @@ -132,12 +132,22 @@ export class DomainName extends Resource implements IDomainName { public readonly domainName = attrs.domainName; public readonly domainNameAliasDomainName = attrs.domainNameAliasTarget; public readonly domainNameAliasHostedZoneId = attrs.domainNameAliasHostedZoneId; + + public readonly domainNameRef = { + domainName: this.domainName, + domainNameArn: Arn.format({ + service: 'apigateway', + resource: 'domainnames', + resourceName: attrs.domainName, + }, Stack.of(scope)), + }; } return new Import(scope, id); } public readonly domainName: string; + public readonly domainNameRef: DomainNameReference; public readonly domainNameAliasDomainName: string; public readonly domainNameAliasHostedZoneId: string; private readonly basePaths = new Set(); @@ -168,6 +178,7 @@ export class DomainName extends Resource implements IDomainName { }); this.domainName = resource.ref; + this.domainNameRef = resource.domainNameRef; this.domainNameAliasDomainName = edge ? resource.attrDistributionDomainName diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/gateway-response.ts b/packages/aws-cdk-lib/aws-apigateway/lib/gateway-response.ts index 7eb62ee350e2f..d28ae7291dced 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/gateway-response.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/gateway-response.ts @@ -1,5 +1,10 @@ import { Construct } from 'constructs'; -import { CfnGatewayResponse, CfnGatewayResponseProps } from './apigateway.generated'; +import { + CfnGatewayResponse, + CfnGatewayResponseProps, + GatewayResponseReference, + IGatewayResponseRef, +} from './apigateway.generated'; import { IRestApi } from './restapi'; import { IResource, Resource } from '../../core'; import { addConstructMetadata } from '../../core/lib/metadata-resource'; @@ -8,7 +13,7 @@ import { propertyInjectable } from '../../core/lib/prop-injectable'; /** * Represents gateway response resource. */ -export interface IGatewayResponse extends IResource { +export interface IGatewayResponse extends IResource, IGatewayResponseRef { } /** @@ -61,6 +66,20 @@ export class GatewayResponse extends Resource implements IGatewayResponse { /** Uniquely identifies this class. */ public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-apigateway.GatewayResponse'; + /** + * Reference an existing GatewayResponse given a gateway response ID. + */ + public static fromGatewayResponseId(scope: Construct, id: string, gatewayResponseId: string): IGatewayResponse { + class Import extends Resource implements IGatewayResponse { + public readonly gatewayResponseRef = { + gatewayResponseId: gatewayResponseId, + }; + } + return new Import(scope, id); + } + + public readonly gatewayResponseRef: GatewayResponseReference; + constructor(scope: Construct, id: string, props: GatewayResponseProps) { super(scope, id); // Enhanced CDK Analytics Telemetry @@ -86,6 +105,7 @@ export class GatewayResponse extends Resource implements IGatewayResponse { }); } + this.gatewayResponseRef = resource.gatewayResponseRef; this.node.defaultChild = resource; } diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/resource.ts b/packages/aws-cdk-lib/aws-apigateway/lib/resource.ts index 6354f91908e72..0ab22237c352f 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/resource.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/resource.ts @@ -1,16 +1,16 @@ import { Construct } from 'constructs'; -import { CfnResource, CfnResourceProps } from './apigateway.generated'; +import { CfnResource, CfnResourceProps, IResourceRef, ResourceReference } from './apigateway.generated'; import { Cors, CorsOptions } from './cors'; import { Integration } from './integration'; import { MockIntegration } from './integrations'; -import { Method, MethodOptions, AuthorizationType } from './method'; +import { AuthorizationType, Method, MethodOptions } from './method'; import { IRestApi, RestApi } from './restapi'; import { IResource as IResourceBase, Resource as ResourceConstruct } from '../../core'; import { ValidationError } from '../../core/lib/errors'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; -export interface IResource extends IResourceBase { +export interface IResource extends IResourceBase, IResourceRef { /** * The parent of this resource or undefined for the root resource. */ @@ -383,6 +383,13 @@ export abstract class ResourceBase extends ResourceConstruct implements IResourc public get url(): string { return this.restApi.urlForPath(this.path); } + + public get resourceRef(): ResourceReference { + return { + resourceId: this.resourceId, + restApiId: this.api.restApiId, + }; + } } /** diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/restapi.ts b/packages/aws-cdk-lib/aws-apigateway/lib/restapi.ts index b008a77e3c19e..24e34c51dc85a 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/restapi.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/restapi.ts @@ -2,7 +2,7 @@ import { Construct } from 'constructs'; import { ApiDefinition } from './api-definition'; import { ApiKey, ApiKeyOptions, IApiKey } from './api-key'; import { ApiGatewayMetrics } from './apigateway-canned-metrics.generated'; -import { CfnAccount, CfnRestApi } from './apigateway.generated'; +import { CfnAccount, CfnRestApi, IRestApiRef, RestApiReference } from './apigateway.generated'; import { CorsOptions } from './cors'; import { Deployment } from './deployment'; import { DomainName, DomainNameOptions } from './domain-name'; @@ -17,7 +17,18 @@ import { UsagePlan, UsagePlanProps } from './usage-plan'; import * as cloudwatch from '../../aws-cloudwatch'; import * as ec2 from '../../aws-ec2'; import * as iam from '../../aws-iam'; -import { ArnFormat, CfnOutput, IResource as IResourceBase, Resource, Stack, Token, FeatureFlags, RemovalPolicy, Size, Lazy } from '../../core'; +import { + ArnFormat, + CfnOutput, + FeatureFlags, + IResource as IResourceBase, + Lazy, + RemovalPolicy, + Resource, + Size, + Stack, + Token, +} from '../../core'; import { ValidationError } from '../../core/lib/errors'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; @@ -27,7 +38,7 @@ import { APIGATEWAY_DISABLE_CLOUDWATCH_ROLE } from '../../cx-api'; const RESTAPI_SYMBOL = Symbol.for('@aws-cdk/aws-apigateway.RestApiBase'); const APIGATEWAY_RESTAPI_SYMBOL = Symbol.for('@aws-cdk/aws-apigateway.RestApi'); -export interface IRestApi extends IResourceBase { +export interface IRestApi extends IResourceBase, IRestApiRef { /** * The ID of this API Gateway RestApi. * @attribute @@ -738,6 +749,12 @@ export abstract class RestApiBase extends Resource implements IRestApi, iam.IRes ...props, }).attachTo(this); } + + public get restApiRef(): RestApiReference { + return { + restApiId: this.restApiId, + }; + } } /** diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/stage.ts b/packages/aws-cdk-lib/aws-apigateway/lib/stage.ts index 1e519e97efe6b..90e17c621619e 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/stage.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/stage.ts @@ -1,8 +1,8 @@ import { Construct } from 'constructs'; import { AccessLogFormat, IAccessLogDestination } from './access-log'; -import { IApiKey, ApiKeyOptions, ApiKey } from './api-key'; +import { ApiKey, ApiKeyOptions, IApiKey } from './api-key'; import { ApiGatewayMetrics } from './apigateway-canned-metrics.generated'; -import { CfnStage } from './apigateway.generated'; +import { CfnStage, IStageRef, StageReference } from './apigateway.generated'; import { Deployment } from './deployment'; import { IRestApi, RestApiBase } from './restapi'; import { parseMethodOptionsPath } from './util'; @@ -15,7 +15,7 @@ import { propertyInjectable } from '../../core/lib/prop-injectable'; /** * Represents an APIGateway Stage. */ -export interface IStage extends IResource { +export interface IStage extends IResource, IStageRef { /** * Name of this stage. * @attribute @@ -357,6 +357,13 @@ export abstract class StageBase extends Resource implements IStage { ...props, }).attachTo(this); } + + public get stageRef(): StageReference { + return { + stageName: this.stageName, + restApiId: this.restApi.restApiId, + }; + } } @propertyInjectable diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/usage-plan.ts b/packages/aws-cdk-lib/aws-apigateway/lib/usage-plan.ts index 97f516d629f7c..90ed23e22dee8 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/usage-plan.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/usage-plan.ts @@ -1,6 +1,6 @@ import { Construct } from 'constructs'; import { IApiKey } from './api-key'; -import { CfnUsagePlan, CfnUsagePlanKey } from './apigateway.generated'; +import { CfnUsagePlan, CfnUsagePlanKey, IUsagePlanRef, UsagePlanReference } from './apigateway.generated'; import { Method } from './method'; import { IRestApi } from './restapi'; import { Stage } from './stage'; @@ -161,7 +161,7 @@ export interface AddApiKeyOptions { /** * A UsagePlan, either managed by this CDK app, or imported. */ -export interface IUsagePlan extends IResource { +export interface IUsagePlan extends IResource, IUsagePlanRef { /** * Id of the usage plan * @attribute @@ -211,6 +211,12 @@ abstract class UsagePlanBase extends Resource implements IUsagePlan { resource.overrideLogicalId(options?.overrideLogicalId); } } + + public get usagePlanRef(): UsagePlanReference { + return { + usagePlanId: this.usagePlanId, + }; + } } @propertyInjectable diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/vpc-link.ts b/packages/aws-cdk-lib/aws-apigateway/lib/vpc-link.ts index 544d23e64dfec..983e12a2c4b7c 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/vpc-link.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/vpc-link.ts @@ -1,5 +1,5 @@ import { Construct } from 'constructs'; -import { CfnVpcLink } from './apigateway.generated'; +import { CfnVpcLink, IVpcLinkRef, VpcLinkReference } from './apigateway.generated'; import * as elbv2 from '../../aws-elasticloadbalancingv2'; import { IResource, Lazy, Names, Resource } from '../../core'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; @@ -8,7 +8,7 @@ import { propertyInjectable } from '../../core/lib/prop-injectable'; /** * Represents an API Gateway VpcLink */ -export interface IVpcLink extends IResource { +export interface IVpcLink extends IResource, IVpcLinkRef { /** * Physical ID of the VpcLink resource * @attribute @@ -56,6 +56,9 @@ export class VpcLink extends Resource implements IVpcLink { public static fromVpcLinkId(scope: Construct, id: string, vpcLinkId: string): IVpcLink { class Import extends Resource implements IVpcLink { public vpcLinkId = vpcLinkId; + public vpcLinkRef = { + vpcLinkId: vpcLinkId, + }; } return new Import(scope, id); @@ -67,6 +70,8 @@ export class VpcLink extends Resource implements IVpcLink { */ public readonly vpcLinkId: string; + public readonly vpcLinkRef: VpcLinkReference; + private readonly _targets = new Array(); constructor(scope: Construct, id: string, props: VpcLinkProps = {}) { @@ -83,6 +88,7 @@ export class VpcLink extends Resource implements IVpcLink { targetArns: Lazy.list({ produce: () => this.renderTargets() }), }); + this.vpcLinkRef = cfnResource.vpcLinkRef; this.vpcLinkId = cfnResource.ref; if (props.targets) { diff --git a/packages/aws-cdk-lib/aws-appsync/test/integ-assets/appsync-js-pipeline.js b/packages/aws-cdk-lib/aws-appsync/test/integ-assets/appsync-js-pipeline.js index cfc6716b9273a..9fc18f5a4a73e 100644 --- a/packages/aws-cdk-lib/aws-appsync/test/integ-assets/appsync-js-pipeline.js +++ b/packages/aws-cdk-lib/aws-appsync/test/integ-assets/appsync-js-pipeline.js @@ -1,9 +1 @@ -// The before step -export function request(...args) { - return {} -} - -// The after step -export function response(ctx) { - return ctx.prev.result -} +"use strict";var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:!0}),mod);var appsync_js_pipeline_exports={};__export(appsync_js_pipeline_exports,{request:()=>request,response:()=>response});module.exports=__toCommonJS(appsync_js_pipeline_exports);function request(...args){return{}}function response(ctx){return ctx.prev.result}0&&(module.exports={request,response}); diff --git a/packages/aws-cdk-lib/aws-appsync/test/integ-assets/appsync-js-resolver.js b/packages/aws-cdk-lib/aws-appsync/test/integ-assets/appsync-js-resolver.js index 74a309765f2c2..3ba08eb272a15 100644 --- a/packages/aws-cdk-lib/aws-appsync/test/integ-assets/appsync-js-resolver.js +++ b/packages/aws-cdk-lib/aws-appsync/test/integ-assets/appsync-js-resolver.js @@ -1,22 +1 @@ -import { util } from '@aws-appsync/utils' - -export function request(ctx) { - const id = util.autoId() - const name = ctx.args.name; - - ctx.args.input = { - id, - name, - } - - return { - version: '2018-05-29', - operation: 'PutItem', - key: { id: util.dynamodb.toDynamoDB(ctx.args.input.id) }, - attributeValues: util.dynamodb.toMapValues(ctx.args.input), - }; -} - -export function response(ctx) { - return ctx.result; -} +"use strict";var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:!0}),mod);var appsync_js_resolver_exports={};__export(appsync_js_resolver_exports,{request:()=>request,response:()=>response});module.exports=__toCommonJS(appsync_js_resolver_exports);var import_utils=require("@aws-appsync/utils");function request(ctx){const id=import_utils.util.autoId(),name=ctx.args.name;return ctx.args.input={id,name},{version:"2018-05-29",operation:"PutItem",key:{id:import_utils.util.dynamodb.toDynamoDB(ctx.args.input.id)},attributeValues:import_utils.util.dynamodb.toMapValues(ctx.args.input)}}function response(ctx){return ctx.result}0&&(module.exports={request,response}); diff --git a/packages/aws-cdk-lib/aws-appsync/test/integ-assets/js-resolver-assertion/index.js b/packages/aws-cdk-lib/aws-appsync/test/integ-assets/js-resolver-assertion/index.js index db0dbed85dfd5..9bc4764c5e5da 100644 --- a/packages/aws-cdk-lib/aws-appsync/test/integ-assets/js-resolver-assertion/index.js +++ b/packages/aws-cdk-lib/aws-appsync/test/integ-assets/js-resolver-assertion/index.js @@ -1,24 +1,6 @@ -exports.handler = async function(event) { - console.log(event); - - let myHeaders = new Headers(); - myHeaders.append("x-api-key", event.apiKey); - myHeaders.append("Content-Type", "application/json"); - - const query = JSON.stringify({ - query: "mutation MyMutation {\n addTest(name: \"123\") {\n id\n name\n }\n}", - variables: {} - }); - - const requestOptions = { - method: 'POST', - headers: myHeaders, - body: query, - redirect: 'follow' - }; - - const response = await fetch(event.hostname, requestOptions) - .then(response => response.json()) - - return response; -} +"use strict";exports.handler=async function(event){console.log(event);let myHeaders=new Headers;myHeaders.append("x-api-key",event.apiKey),myHeaders.append("Content-Type","application/json");const query=JSON.stringify({query:`mutation MyMutation { + addTest(name: "123") { + id + name + } +}`,variables:{}}),requestOptions={method:"POST",headers:myHeaders,body:query,redirect:"follow"};return await fetch(event.hostname,requestOptions).then(response2=>response2.json())}; diff --git a/packages/aws-cdk-lib/aws-appsync/test/verify/eventapi-lambda-direct/handler.js b/packages/aws-cdk-lib/aws-appsync/test/verify/eventapi-lambda-direct/handler.js index 4025ef824c917..9aa0f644f3e1a 100644 --- a/packages/aws-cdk-lib/aws-appsync/test/verify/eventapi-lambda-direct/handler.js +++ b/packages/aws-cdk-lib/aws-appsync/test/verify/eventapi-lambda-direct/handler.js @@ -1,20 +1 @@ -exports.handler = async (context) => { - if (context.info.operation === 'PUBLISH') { - return { - events: context.events.map((ev) => { - // Transform the event - return { - id: ev.id, - payload: { - ...ev.payload, - with: `hello world from ${ev.id}` - } - } - }) - } - } else if (context.info.operation === 'SUBSCRIBE') { - - } else { - throw new Error('Unknown operation'); - } -}; \ No newline at end of file +"use strict";exports.handler=async context=>{if(context.info.operation==="PUBLISH")return{events:context.events.map(ev=>({id:ev.id,payload:{...ev.payload,with:`hello world from ${ev.id}`}}))};if(context.info.operation!=="SUBSCRIBE")throw new Error("Unknown operation")}; diff --git a/packages/aws-cdk-lib/aws-appsync/test/verify/eventapi-lambda-ds/handler.js b/packages/aws-cdk-lib/aws-appsync/test/verify/eventapi-lambda-ds/handler.js index b26d65260d76b..8dcb10945793e 100644 --- a/packages/aws-cdk-lib/aws-appsync/test/verify/eventapi-lambda-ds/handler.js +++ b/packages/aws-cdk-lib/aws-appsync/test/verify/eventapi-lambda-ds/handler.js @@ -1,4 +1 @@ -exports.handler = async (event, context) => { - console.log("Do something with the events!"); - console.log(event); -}; \ No newline at end of file +"use strict";exports.handler=async(event,context)=>{console.log("Do something with the events!"),console.log(event)}; diff --git a/packages/aws-cdk-lib/aws-appsync/test/verify/iam-query/iam-query.js b/packages/aws-cdk-lib/aws-appsync/test/verify/iam-query/iam-query.js index 11e895d2e2c54..243023f19292e 100644 --- a/packages/aws-cdk-lib/aws-appsync/test/verify/iam-query/iam-query.js +++ b/packages/aws-cdk-lib/aws-appsync/test/verify/iam-query/iam-query.js @@ -1,40 +1,6 @@ -require('isomorphic-fetch'); -const AWS = require('aws-sdk/global'); -const gql = require('graphql-tag'); -const appsync = require('aws-appsync'); - -const config = { - url: process.env.APPSYNC_ENDPOINT, - region: process.env.AWS_REGION, - auth: { - type: appsync.AUTH_TYPE.AWS_IAM, - credentials: AWS.config.credentials, - }, - disableOffline: true -}; - -const getTests = -`query getTests { +"use strict";require("isomorphic-fetch");const AWS=require("aws-sdk/global"),gql=require("graphql-tag"),appsync=require("aws-appsync"),config={url:process.env.APPSYNC_ENDPOINT,region:process.env.AWS_REGION,auth:{type:appsync.AUTH_TYPE.AWS_IAM,credentials:AWS.config.credentials},disableOffline:!0},getTests=`query getTests { getTests { id version } -}`; - -const client = new appsync.AWSAppSyncClient(config); - -exports.handler = (event, context, callback) => { - - (async () => { - try { - const result = await client.query({ - query: gql(getTests) - }); - console.log(result.data); - callback(null, result.data); - } catch (e) { - console.warn('Error sending mutation: ', e); - callback(Error(e)); - } - })(); -}; \ No newline at end of file +}`,client=new appsync.AWSAppSyncClient(config);exports.handler=(event,context,callback)=>{(async()=>{try{const result=await client.query({query:gql(getTests)});console.log(result.data),callback(null,result.data)}catch(e){console.warn("Error sending mutation: ",e),callback(Error(e))}})()}; diff --git a/packages/aws-cdk-lib/aws-appsync/test/verify/lambda-tutorial/lambda-tutorial.js b/packages/aws-cdk-lib/aws-appsync/test/verify/lambda-tutorial/lambda-tutorial.js index 5a08f83ef4f0a..2fd7fd0a41753 100644 --- a/packages/aws-cdk-lib/aws-appsync/test/verify/lambda-tutorial/lambda-tutorial.js +++ b/packages/aws-cdk-lib/aws-appsync/test/verify/lambda-tutorial/lambda-tutorial.js @@ -1,70 +1 @@ -exports.handler = (event, context, callback) => { - console.log("Received event {}", JSON.stringify(event, 3)); - var posts = { - "1": {"id": "1", "title": "First book", "author": "Author1", "url": "https://amazon.com/", "content": "SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1", "ups": "100", "downs": "10"}, - "2": {"id": "2", "title": "Second book", "author": "Author2", "url": "https://amazon.com", "content": "SAMPLE TEXT AUTHOR 2 SAMPLE TEXT AUTHOR 2 SAMPLE TEXT", "ups": "100", "downs": "10"}, - "3": {"id": "3", "title": "Third book", "author": "Author3", "url": null, "content": null, "ups": null, "downs": null }, - "4": {"id": "4", "title": "Fourth book", "author": "Author4", "url": "https://www.amazon.com/", "content": "SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4", "ups": "1000", "downs": "0"}, - "5": {"id": "5", "title": "Fifth book", "author": "Author5", "url": "https://www.amazon.com/", "content": "SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT", "ups": "50", "downs": "0"} }; - - var relatedPosts = { - "1": [posts['4']], - "2": [posts['3'], posts['5']], - "3": [posts['2'], posts['1']], - "4": [posts['2'], posts['1']], - "5": [] - }; - const isBatch = Array.isArray(event); - if (isBatch) { - console.log("Got an BatchInvoke Request. The payload has %d items to resolve.", event.length); - const field = event[0].field; - switch(field) { - case "relatedPostsMaxBatchSize": - case "relatedPosts": - var results = []; - // the response MUST contain the same number - // of entries as the payload array - for (var i=0; i< event.length; i++) { - console.log("post {}", JSON.stringify(event[i].source)); - results.push(relatedPosts[event[i].source.id]); - } - console.log("results {}", JSON.stringify(results)); - callback(null, results); - break; - default: - callback("Unknown field, unable to resolve" + field, null); - break; - } - } - else { - console.log("Got an Invoke Request."); - switch(event.field) { - case "getPost": - var id = event.arguments.id; - callback(null, posts[id]); - break; - case "allPosts": - var values = []; - for(var d in posts){ - values.push(posts[d]); - } - callback(null, values); - break; - case "addPost": - // return the arguments back - callback(null, event.arguments); - break; - case "addPostErrorWithData": - var id = event.arguments.id; - var result = posts[id]; - // attached additional error information to the post - result.errorMessage = 'Error with the mutation, data has changed'; - result.errorType = 'MUTATION_ERROR'; - callback(null, result); - break; - default: - callback("Unknown field, unable to resolve" + event.field, null); - break; - } - } -}; \ No newline at end of file +"use strict";exports.handler=(event,context,callback)=>{console.log("Received event {}",JSON.stringify(event,3));var posts={1:{id:"1",title:"First book",author:"Author1",url:"https://amazon.com/",content:"SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1",ups:"100",downs:"10"},2:{id:"2",title:"Second book",author:"Author2",url:"https://amazon.com",content:"SAMPLE TEXT AUTHOR 2 SAMPLE TEXT AUTHOR 2 SAMPLE TEXT",ups:"100",downs:"10"},3:{id:"3",title:"Third book",author:"Author3",url:null,content:null,ups:null,downs:null},4:{id:"4",title:"Fourth book",author:"Author4",url:"https://www.amazon.com/",content:"SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4",ups:"1000",downs:"0"},5:{id:"5",title:"Fifth book",author:"Author5",url:"https://www.amazon.com/",content:"SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT",ups:"50",downs:"0"}},relatedPosts={1:[posts[4]],2:[posts[3],posts[5]],3:[posts[2],posts[1]],4:[posts[2],posts[1]],5:[]};if(Array.isArray(event)){console.log("Got an BatchInvoke Request. The payload has %d items to resolve.",event.length);const field=event[0].field;switch(field){case"relatedPostsMaxBatchSize":case"relatedPosts":for(var results=[],i=0;i.vpce-svc-xxxxxxxxxxxxxxxx @@ -172,6 +177,10 @@ export class VpcEndpointService extends Resource implements IVpcEndpointService }); } } + + public get vpcEndpointServiceRef(): VPCEndpointServiceReference { + return this.endpointService.vpcEndpointServiceRef; + } } /** diff --git a/packages/aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts b/packages/aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts index 4e1d9c501e88f..4ba09e67bb364 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts @@ -1,6 +1,6 @@ import { Construct } from 'constructs'; import { Connections, IConnectable } from './connections'; -import { CfnVPCEndpoint } from './ec2.generated'; +import { CfnVPCEndpoint, IVPCEndpointRef, VPCEndpointReference } from './ec2.generated'; import { Peer } from './peer'; import { Port } from './port'; import { ISecurityGroup, SecurityGroup } from './security-group'; @@ -15,7 +15,7 @@ import { propertyInjectable } from '../../core/lib/prop-injectable'; /** * A VPC endpoint. */ -export interface IVpcEndpoint extends IResource { +export interface IVpcEndpoint extends IResource, IVPCEndpointRef { /** * The VPC endpoint identifier. * @attribute @@ -28,6 +28,12 @@ export abstract class VpcEndpoint extends Resource implements IVpcEndpoint { protected policyDocument?: iam.PolicyDocument; + public get vpcEndpointRef(): VPCEndpointReference { + return { + vpcEndpointId: this.vpcEndpointId, + }; + } + /** * Adds a statement to the policy document of the VPC endpoint. The statement * must have a Principal. @@ -981,6 +987,11 @@ export class InterfaceVpcEndpoint extends VpcEndpoint implements IInterfaceVpcEn defaultPort: Port.tcp(attrs.port), securityGroups, }); + public get vpcEndpointRef(): VPCEndpointReference { + return { + vpcEndpointId: this.vpcEndpointId, + }; + } } return new Import(scope, id); diff --git a/packages/aws-cdk-lib/aws-ec2/lib/vpc-flow-logs.ts b/packages/aws-cdk-lib/aws-ec2/lib/vpc-flow-logs.ts index f217f2206b363..fd87ef934d8c5 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/vpc-flow-logs.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/vpc-flow-logs.ts @@ -1,10 +1,20 @@ import { Construct } from 'constructs'; -import { CfnFlowLog } from './ec2.generated'; +import { CfnFlowLog, FlowLogReference, IFlowLogRef } from './ec2.generated'; import { ISubnet, IVpc } from './vpc'; import * as iam from '../../aws-iam'; import * as logs from '../../aws-logs'; import * as s3 from '../../aws-s3'; -import { IResource, PhysicalName, RemovalPolicy, Resource, FeatureFlags, Stack, Tags, CfnResource, ValidationError } from '../../core'; +import { + CfnResource, + FeatureFlags, + IResource, + PhysicalName, + RemovalPolicy, + Resource, + Stack, + Tags, + ValidationError, +} from '../../core'; import { addConstructMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; import { S3_CREATE_DEFAULT_LOGGING_POLICY } from '../../cx-api'; @@ -17,7 +27,7 @@ const NAME_TAG: string = 'Name'; /** * A FlowLog */ -export interface IFlowLog extends IResource { +export interface IFlowLog extends IResource, IFlowLogRef { /** * The Id of the VPC Flow Log * @@ -804,6 +814,12 @@ abstract class FlowLogBase extends Resource implements IFlowLog { * @attribute */ public abstract readonly flowLogId: string; + + public get flowLogRef(): FlowLogReference { + return { + flowLogId: this.flowLogId, + }; + } } /** diff --git a/packages/aws-cdk-lib/aws-ec2/lib/vpc.ts b/packages/aws-cdk-lib/aws-ec2/lib/vpc.ts index deb37e89639e7..0724d67dc64fd 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/vpc.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/vpc.ts @@ -1,35 +1,80 @@ import { Construct, Dependable, DependencyGroup, IConstruct, IDependable, Node } from 'constructs'; import { ClientVpnEndpoint, ClientVpnEndpointOptions } from './client-vpn-endpoint'; import { - CfnEIP, CfnEgressOnlyInternetGateway, CfnInternetGateway, CfnNatGateway, CfnRoute, CfnRouteTable, CfnSubnet, - CfnSubnetRouteTableAssociation, CfnVPC, CfnVPCCidrBlock, CfnVPCGatewayAttachment, CfnVPNGatewayRoutePropagation, + CfnEgressOnlyInternetGateway, + CfnEIP, + CfnInternetGateway, + CfnNatGateway, + CfnRoute, + CfnRouteTable, + CfnSubnet, + CfnSubnetRouteTableAssociation, + CfnVPC, + CfnVPCCidrBlock, + CfnVPCGatewayAttachment, + CfnVPNGatewayRoutePropagation, + ISubnetRef, + IVPCRef, SubnetReference, VPCReference, } from './ec2.generated'; -import { AllocatedSubnet, IIpAddresses, RequestedSubnet, IpAddresses, IIpv6Addresses, Ipv6Addresses } from './ip-addresses'; +import { + AllocatedSubnet, + IIpAddresses, + IIpv6Addresses, + IpAddresses, + Ipv6Addresses, + RequestedSubnet, +} from './ip-addresses'; import { NatProvider } from './nat'; import { INetworkAcl, NetworkAcl, SubnetNetworkAclAssociation } from './network-acl'; import { SubnetFilter } from './subnet'; -import { allRouteTableIds, defaultSubnetName, flatten, ImportSubnetGroup, subnetGroupNameFromConstructId, subnetId } from './util'; -import { GatewayVpcEndpoint, GatewayVpcEndpointAwsService, GatewayVpcEndpointOptions, InterfaceVpcEndpoint, InterfaceVpcEndpointOptions } from './vpc-endpoint'; +import { + allRouteTableIds, + defaultSubnetName, + flatten, + ImportSubnetGroup, + subnetGroupNameFromConstructId, + subnetId, +} from './util'; +import { + GatewayVpcEndpoint, + GatewayVpcEndpointAwsService, + GatewayVpcEndpointOptions, + InterfaceVpcEndpoint, + InterfaceVpcEndpointOptions, +} from './vpc-endpoint'; import { FlowLog, FlowLogOptions, FlowLogResourceType } from './vpc-flow-logs'; import { VpcLookupOptions } from './vpc-lookup'; import { EnableVpnGatewayOptions, VpnConnection, VpnConnectionOptions, VpnConnectionType, VpnGateway } from './vpn'; import * as cxschema from '../../cloud-assembly-schema'; import { - Arn, Annotations, ContextProvider, - IResource, Fn, Lazy, Resource, Stack, Token, Tags, Names, CustomResource, FeatureFlags, - ValidationError, + Annotations, + Arn, + ContextProvider, + CustomResource, + FeatureFlags, + Fn, + IResource, + Lazy, + Names, + Resource, + Stack, + Tags, + Token, UnscopedValidationError, + ValidationError, } from '../../core'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; -import { RestrictDefaultSgProvider } from '../../custom-resource-handlers/dist/aws-ec2/restrict-default-sg-provider.generated'; +import { + RestrictDefaultSgProvider, +} from '../../custom-resource-handlers/dist/aws-ec2/restrict-default-sg-provider.generated'; import * as cxapi from '../../cx-api'; import { EC2_RESTRICT_DEFAULT_SECURITY_GROUP } from '../../cx-api'; const VPC_SUBNET_SYMBOL = Symbol.for('@aws-cdk/aws-ec2.VpcSubnet'); const FAKE_AZ_NAME = 'fake-az'; -export interface ISubnet extends IResource { +export interface ISubnet extends IResource, ISubnetRef { /** * The Availability Zone the subnet is located in */ @@ -74,7 +119,7 @@ export interface IRouteTable { readonly routeTableId: string; } -export interface IVpc extends IResource { +export interface IVpc extends IResource, IVPCRef { /** * Identifier for this VPC * @attribute @@ -471,6 +516,12 @@ abstract class VpcBase extends Resource implements IVpc { */ protected _vpnGatewayId?: string; + public get vpcRef(): VPCReference { + return { + vpcId: this.vpcId, + }; + } + /** * Returns IDs of selected subnets */ @@ -2099,6 +2150,8 @@ export class Subnet extends Resource implements ISubnet { */ public readonly routeTable: IRouteTable; + public readonly subnetRef: SubnetReference; + public readonly internetConnectivityEstablished: IDependable; private readonly _internetConnectivityEstablished = new DependencyGroup(); @@ -2129,6 +2182,7 @@ export class Subnet extends Resource implements ISubnet { this.subnetAvailabilityZone = subnet.attrAvailabilityZone; this.subnetIpv6CidrBlocks = subnet.attrIpv6CidrBlocks; this.subnetOutpostArn = subnet.attrOutpostArn; + this.subnetRef = subnet.subnetRef; // subnet.attrNetworkAclAssociationId is the default ACL after the subnet // was just created. However, the ACL can be replaced at a later time. @@ -2686,6 +2740,12 @@ class ImportedSubnet extends Resource implements ISubnet, IPublicSubnet, IPrivat }; } + public get subnetRef(): SubnetReference { + return { + subnetId: this.subnetId, + }; + } + public get availabilityZone(): string { if (!this._availabilityZone) { // eslint-disable-next-line max-len diff --git a/packages/aws-cdk-lib/aws-ec2/lib/vpn.ts b/packages/aws-cdk-lib/aws-ec2/lib/vpn.ts index 67c0cb987f6de..f59a079d697b0 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/vpn.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/vpn.ts @@ -5,6 +5,8 @@ import { CfnVPNConnection, CfnVPNConnectionRoute, CfnVPNGateway, + IVPNConnectionRef, + IVPNGatewayRef, VPNConnectionReference, VPNGatewayReference, } from './ec2.generated'; import { IVpc, SubnetSelection } from './vpc'; import * as cloudwatch from '../../aws-cloudwatch'; @@ -12,7 +14,7 @@ import { IResource, Resource, SecretValue, Token, ValidationError } from '../../ import { addConstructMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; -export interface IVpnConnection extends IResource { +export interface IVpnConnection extends IResource, IVPNConnectionRef { /** * The id of the VPN connection. * @attribute VpnConnectionId @@ -38,7 +40,7 @@ export interface IVpnConnection extends IResource { /** * The virtual private gateway interface */ -export interface IVpnGateway extends IResource { +export interface IVpnGateway extends IResource, IVPNGatewayRef { /** * The virtual private gateway Id @@ -172,6 +174,8 @@ export class VpnGateway extends Resource implements IVpnGateway { */ public readonly gatewayId: string; + public readonly vpnGatewayRef: VPNGatewayReference; + constructor(scope: Construct, id: string, props: VpnGatewayProps) { super(scope, id); // Enhanced CDK Analytics Telemetry @@ -182,6 +186,7 @@ export class VpnGateway extends Resource implements IVpnGateway { // to be created for the CfnVPNGateway (and 'Resource' would not do that). const vpnGW = new CfnVPNGateway(this, 'Default', props); this.gatewayId = vpnGW.ref; + this.vpnGatewayRef = vpnGW.vpnGatewayRef; } } @@ -220,6 +225,12 @@ export abstract class VpnConnectionBase extends Resource implements IVpnConnecti public abstract readonly customerGatewayId: string; public abstract readonly customerGatewayIp: string; public abstract readonly customerGatewayAsn: number; + + public get vpnConnectionRef(): VPNConnectionReference { + return { + vpnConnectionId: this.customerGatewayId, + }; + } } /** diff --git a/packages/aws-cdk-lib/aws-iam/lib/access-key.ts b/packages/aws-cdk-lib/aws-iam/lib/access-key.ts index 7904225107984..4794d5e951d12 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/access-key.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/access-key.ts @@ -1,5 +1,5 @@ import { Construct } from 'constructs'; -import { CfnAccessKey } from './iam.generated'; +import { AccessKeyReference, CfnAccessKey, IAccessKeyRef } from './iam.generated'; import { IUser } from './user'; import { IResource, Resource, SecretValue } from '../../core'; import { addConstructMetadata } from '../../core/lib/metadata-resource'; @@ -25,7 +25,7 @@ export enum AccessKeyStatus { * * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html */ -export interface IAccessKey extends IResource { +export interface IAccessKey extends IResource, IAccessKeyRef { /** * The Access Key ID. * @@ -79,6 +79,7 @@ export interface AccessKeyProps { export class AccessKey extends Resource implements IAccessKey { /** Uniquely identifies this class. */ public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-iam.AccessKey'; + public readonly accessKeyRef: AccessKeyReference; public readonly accessKeyId: string; public readonly secretAccessKey: SecretValue; @@ -93,6 +94,7 @@ export class AccessKey extends Resource implements IAccessKey { }); this.accessKeyId = accessKey.ref; + this.accessKeyRef = accessKey.accessKeyRef; this.secretAccessKey = SecretValue.resourceAttribute(accessKey.attrSecretAccessKey); } diff --git a/packages/aws-cdk-lib/aws-iam/lib/group.ts b/packages/aws-cdk-lib/aws-iam/lib/group.ts index bb9673cea5724..83c744a7775c5 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/group.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/group.ts @@ -1,5 +1,5 @@ import { Construct } from 'constructs'; -import { CfnGroup } from './iam.generated'; +import { CfnGroup, GroupReference, IGroupRef } from './iam.generated'; import { IIdentity } from './identity-base'; import { IManagedPolicy } from './managed-policy'; import { Policy } from './policy'; @@ -16,7 +16,7 @@ import { propertyInjectable } from '../../core/lib/prop-injectable'; * * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html */ -export interface IGroup extends IIdentity { +export interface IGroup extends IIdentity, IGroupRef { /** * Returns the IAM Group Name * @@ -85,6 +85,13 @@ abstract class GroupBase extends Resource implements IGroup { return new ArnPrincipal(this.groupArn).policyFragment; } + public get groupRef(): GroupReference { + return { + groupName: this.groupName, + groupArn: this.groupArn, + }; + } + /** * Attaches a policy to this group. * @param policy The policy to attach. diff --git a/packages/aws-cdk-lib/aws-iam/lib/instance-profile.ts b/packages/aws-cdk-lib/aws-iam/lib/instance-profile.ts index 4d30009fa20da..bad03c6bf0c46 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/instance-profile.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/instance-profile.ts @@ -1,15 +1,15 @@ import { Construct } from 'constructs'; -import { CfnInstanceProfile } from './iam.generated'; +import { CfnInstanceProfile, IInstanceProfileRef, InstanceProfileReference } from './iam.generated'; import { ServicePrincipal } from './principals'; import { IRole, Role } from './role'; -import { Resource, Arn, Stack, IResource, PhysicalName } from '../../core'; +import { Arn, IResource, PhysicalName, Resource, Stack } from '../../core'; import { addConstructMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; /** * Represents an IAM Instance Profile */ -export interface IInstanceProfile extends IResource { +export interface IInstanceProfile extends IResource, IInstanceProfileRef { /** * The InstanceProfile's name. * @attribute @@ -99,6 +99,13 @@ abstract class InstanceProfileBase extends Resource implements IInstanceProfile public get role(): IRole | undefined { return this._role; } + + public get instanceProfileRef(): InstanceProfileReference { + return { + instanceProfileName: this.instanceProfileName, + instanceProfileArn: this.instanceProfileArn, + }; + } } /** diff --git a/packages/aws-cdk-lib/aws-iam/lib/lazy-role.ts b/packages/aws-cdk-lib/aws-iam/lib/lazy-role.ts index 3bc1d1e503d36..caac20887d3f6 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/lazy-role.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/lazy-role.ts @@ -1,5 +1,6 @@ import { Construct } from 'constructs'; import { Grant } from './grant'; +import { RoleReference } from './iam.generated'; import { IManagedPolicy } from './managed-policy'; import { Policy } from './policy'; import { PolicyStatement } from './policy-statement'; @@ -99,6 +100,10 @@ export class LazyRole extends cdk.Resource implements IRole { return this.instantiate().roleArn; } + public get roleRef(): RoleReference { + return this.instantiate().roleRef; + } + /** * Returns the stable and unique string identifying the role (i.e. AIDAJQABLZS4A3QDU576Q) * diff --git a/packages/aws-cdk-lib/aws-iam/lib/managed-policy.ts b/packages/aws-cdk-lib/aws-iam/lib/managed-policy.ts index 93e53d082fb50..ccf4f43af17a4 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/managed-policy.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/managed-policy.ts @@ -1,13 +1,13 @@ -import { Construct } from 'constructs'; +import { Construct, Node } from 'constructs'; import { IGroup } from './group'; -import { CfnManagedPolicy } from './iam.generated'; +import { CfnManagedPolicy, IManagedPolicyRef, ManagedPolicyReference } from './iam.generated'; import { PolicyDocument } from './policy-document'; import { PolicyStatement } from './policy-statement'; import { AddToPrincipalPolicyResult, IGrantable, IPrincipal, PrincipalPolicyFragment } from './principals'; import { undefinedIfEmpty } from './private/util'; import { IRole } from './role'; import { IUser } from './user'; -import { ArnFormat, Resource, Stack, Arn, Aws, UnscopedValidationError } from '../../core'; +import { Arn, ArnFormat, Aws, Resource, Stack, UnscopedValidationError } from '../../core'; import { getCustomizeRolesConfig, PolicySynthesizer } from '../../core/lib/helpers-internal'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; @@ -15,7 +15,7 @@ import { propertyInjectable } from '../../core/lib/prop-injectable'; /** * A managed policy */ -export interface IManagedPolicy { +export interface IManagedPolicy extends IManagedPolicyRef { /** * The ARN of the managed policy * @attribute @@ -123,6 +123,11 @@ export class ManagedPolicy extends Resource implements IManagedPolicy, IGrantabl resource: 'policy', resourceName: managedPolicyName, }); + public get managedPolicyRef(): ManagedPolicyReference { + return { + policyArn: this.managedPolicyArn, + }; + } } return new Import(scope, id); } @@ -149,6 +154,11 @@ export class ManagedPolicy extends Resource implements IManagedPolicy, IGrantabl public static fromManagedPolicyArn(scope: Construct, id: string, managedPolicyArn: string): IManagedPolicy { class Import extends Resource implements IManagedPolicy { public readonly managedPolicyArn = managedPolicyArn; + public get managedPolicyRef(): ManagedPolicyReference { + return { + policyArn: this.managedPolicyArn, + }; + } } return new Import(scope, id); } @@ -172,6 +182,14 @@ export class ManagedPolicy extends Resource implements IManagedPolicy, IGrantabl resource: 'policy', resourceName: managedPolicyName, }); + public get managedPolicyRef(): ManagedPolicyReference { + return { + policyArn: this.managedPolicyArn, + }; + } + public get node(): Node { + throw new UnscopedValidationError('The result of fromAwsManagedPolicyName can not be used in this API'); + } } return new AwsManagedPolicy(); } @@ -279,6 +297,12 @@ export class ManagedPolicy extends Resource implements IManagedPolicy, IGrantabl this.node.addValidation({ validate: () => this.validateManagedPolicy() }); } + public get managedPolicyRef(): ManagedPolicyReference { + return { + policyArn: this.managedPolicyArn, + }; + } + /** * Adds a statement to the policy document. */ diff --git a/packages/aws-cdk-lib/aws-iam/lib/oidc-provider-native.ts b/packages/aws-cdk-lib/aws-iam/lib/oidc-provider-native.ts index 2d379f3e66643..0ecc6c8c67af5 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/oidc-provider-native.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/oidc-provider-native.ts @@ -1,5 +1,5 @@ import { Construct } from 'constructs'; -import { CfnOIDCProvider } from './iam.generated'; +import { CfnOIDCProvider, IOIDCProviderRef, OIDCProviderReference } from './iam.generated'; import { Arn, IResource, Resource, Token, ValidationError } from '../../core'; import { addConstructMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; @@ -8,7 +8,7 @@ import { propertyInjectable } from '../../core/lib/prop-injectable'; * Represents an IAM OpenID Connect provider. * */ -export interface IOidcProvider extends IResource { +export interface IOidcProvider extends IResource, IOIDCProviderRef { /** * The Amazon Resource Name (ARN) of the IAM OpenID Connect provider. * @@ -134,6 +134,12 @@ export class OidcProviderNative extends Resource implements IOidcProvider { class Import extends Resource implements IOidcProvider { public readonly oidcProviderArn = oidcProviderArn; public readonly oidcProviderIssuer = resourceName; + + public get oidcProviderRef(): OIDCProviderReference { + return { + oidcProviderArn: this.oidcProviderArn, + }; + } } return new Import(scope, id); @@ -227,4 +233,10 @@ export class OidcProviderNative extends Resource implements IOidcProvider { this.oidcProviderThumbprints = Token.asString(props.thumbprints); } + + public get oidcProviderRef(): OIDCProviderReference { + return { + oidcProviderArn: this.oidcProviderArn, + }; + } } diff --git a/packages/aws-cdk-lib/aws-iam/lib/oidc-provider.ts b/packages/aws-cdk-lib/aws-iam/lib/oidc-provider.ts index 00a2256f400b5..b3922e2fdbaea 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/oidc-provider.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/oidc-provider.ts @@ -1,12 +1,6 @@ import { Construct } from 'constructs'; -import { - Arn, - CustomResource, - FeatureFlags, - IResource, - Resource, - Token, -} from '../../core'; +import { IOIDCProviderRef, OIDCProviderReference } from './iam.generated'; +import { Arn, CustomResource, FeatureFlags, IResource, Resource, Token } from '../../core'; import { addConstructMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; import { OidcProvider } from '../../custom-resource-handlers/dist/aws-iam/oidc-provider.generated'; @@ -18,7 +12,7 @@ const RESOURCE_TYPE = 'Custom::AWSCDKOpenIdConnectProvider'; * Represents an IAM OpenID Connect provider. * */ -export interface IOpenIdConnectProvider extends IResource { +export interface IOpenIdConnectProvider extends IResource, IOIDCProviderRef { /** * The Amazon Resource Name (ARN) of the IAM OpenID Connect provider. */ @@ -137,6 +131,11 @@ export class OpenIdConnectProvider extends Resource implements IOpenIdConnectPro class Import extends Resource implements IOpenIdConnectProvider { public readonly openIdConnectProviderArn = openIdConnectProviderArn; public readonly openIdConnectProviderIssuer = resourceName; + public get oidcProviderRef(): OIDCProviderReference { + return { + oidcProviderArn: this.openIdConnectProviderArn, + }; + } } return new Import(scope, id); @@ -189,6 +188,12 @@ export class OpenIdConnectProvider extends Resource implements IOpenIdConnectPro this.openIdConnectProviderthumbprints = Token.asString(resource.getAtt('Thumbprints')); } + public get oidcProviderRef(): OIDCProviderReference { + return { + oidcProviderArn: this.openIdConnectProviderArn, + }; + } + private getOrCreateProvider() { return OidcProvider.getOrCreateProvider(this, RESOURCE_TYPE, { policyStatements: [ diff --git a/packages/aws-cdk-lib/aws-iam/lib/policy.ts b/packages/aws-cdk-lib/aws-iam/lib/policy.ts index 8ff9fd8df455f..8dff699522d64 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/policy.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/policy.ts @@ -1,13 +1,13 @@ import { Construct } from 'constructs'; import { IGroup } from './group'; -import { CfnPolicy } from './iam.generated'; +import { CfnPolicy, IPolicyRef, PolicyReference } from './iam.generated'; import { PolicyDocument } from './policy-document'; import { PolicyStatement } from './policy-statement'; import { AddToPrincipalPolicyResult, IGrantable, IPrincipal, PrincipalPolicyFragment } from './principals'; import { generatePolicyName, undefinedIfEmpty } from './private/util'; import { IRole } from './role'; import { IUser } from './user'; -import { IResource, Lazy, Resource, UnscopedValidationError } from '../../core'; +import { IResource, Lazy, Resource, UnscopedValidationError, ValidationError } from '../../core'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; @@ -16,7 +16,7 @@ import { propertyInjectable } from '../../core/lib/prop-injectable'; * * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage.html */ -export interface IPolicy extends IResource { +export interface IPolicy extends IResource, IPolicyRef { /** * The name of this policy. * @@ -117,6 +117,10 @@ export class Policy extends Resource implements IPolicy, IGrantable { public static fromPolicyName(scope: Construct, id: string, policyName: string): IPolicy { class Import extends Resource implements IPolicy { public readonly policyName = policyName; + + public get policyRef(): PolicyReference { + throw new ValidationError('Cannot use a Policy.fromPolicyName() here.', this); + } } return new Import(scope, id); @@ -128,6 +132,7 @@ export class Policy extends Resource implements IPolicy, IGrantable { public readonly document = new PolicyDocument(); public readonly grantPrincipal: IPrincipal; + public readonly policyRef: PolicyReference; private readonly _policyName: string; private readonly roles = new Array(); @@ -172,6 +177,10 @@ export class Policy extends Resource implements IPolicy, IGrantable { groups: undefinedIfEmpty(() => this.groups.map(g => g.groupName)), }); + this.policyRef = { + policyId: resource.attrId, + }; + this._policyName = this.physicalName!; this.force = props.force ?? false; diff --git a/packages/aws-cdk-lib/aws-iam/lib/private/immutable-role.ts b/packages/aws-cdk-lib/aws-iam/lib/private/immutable-role.ts index 8e127abbae815..b80a940b4e692 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/private/immutable-role.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/private/immutable-role.ts @@ -3,6 +3,7 @@ import { Resource } from '../../../core'; import { addConstructMetadata, MethodMetadata } from '../../../core/lib/metadata-resource'; import { propertyInjectable } from '../../../core/lib/prop-injectable'; import { Grant } from '../grant'; +import { RoleReference } from '../iam.generated'; import { IManagedPolicy } from '../managed-policy'; import { Policy } from '../policy'; import { PolicyStatement } from '../policy-statement'; @@ -49,6 +50,13 @@ export class ImmutableRole extends Resource implements IRole { this.node.defaultChild = role.node.defaultChild; } + public get roleRef(): RoleReference { + return { + roleName: this.roleName, + roleArn: this.roleArn, + }; + } + @MethodMetadata() public attachInlinePolicy(_policy: Policy): void { // do nothing diff --git a/packages/aws-cdk-lib/aws-iam/lib/private/imported-role.ts b/packages/aws-cdk-lib/aws-iam/lib/private/imported-role.ts index 862d562f0154e..a55b0e0f96729 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/private/imported-role.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/private/imported-role.ts @@ -1,15 +1,22 @@ import { Construct } from 'constructs'; import { MAX_POLICY_NAME_LEN } from './util'; -import { FeatureFlags, Names, Resource, Token, TokenComparison, Annotations } from '../../../core'; +import { Annotations, FeatureFlags, Names, Resource, Token, TokenComparison } from '../../../core'; import { addConstructMetadata, MethodMetadata } from '../../../core/lib/metadata-resource'; import { propertyInjectable } from '../../../core/lib/prop-injectable'; import { IAM_IMPORTED_ROLE_STACK_SAFE_DEFAULT_POLICY_NAME } from '../../../cx-api'; import { Grant } from '../grant'; +import { RoleReference } from '../iam.generated'; import { IManagedPolicy, ManagedPolicy } from '../managed-policy'; import { Policy } from '../policy'; import { PolicyStatement } from '../policy-statement'; -import { IComparablePrincipal, IPrincipal, ArnPrincipal, AddToPrincipalPolicyResult, PrincipalPolicyFragment } from '../principals'; -import { IRole, FromRoleArnOptions } from '../role'; +import { + AddToPrincipalPolicyResult, + ArnPrincipal, + IComparablePrincipal, + IPrincipal, + PrincipalPolicyFragment, +} from '../principals'; +import { FromRoleArnOptions, IRole } from '../role'; import { AttachedPolicies } from '../util'; export interface ImportedRoleProps extends FromRoleArnOptions { @@ -46,6 +53,13 @@ export class ImportedRole extends Resource implements IRole, IComparablePrincipa this.principalAccount = props.account; } + public get roleRef(): RoleReference { + return { + roleName: this.roleName, + roleArn: this.roleArn, + }; + } + @MethodMetadata() public addToPolicy(statement: PolicyStatement): boolean { return this.addToPrincipalPolicy(statement).statementAdded; diff --git a/packages/aws-cdk-lib/aws-iam/lib/private/precreated-role.ts b/packages/aws-cdk-lib/aws-iam/lib/private/precreated-role.ts index 49945af103cc8..a4ce53077cc84 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/private/precreated-role.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/private/precreated-role.ts @@ -4,6 +4,7 @@ import { PolicySynthesizer } from '../../../core/lib/helpers-internal'; import { addConstructMetadata, MethodMetadata } from '../../../core/lib/metadata-resource'; import { propertyInjectable } from '../../../core/lib/prop-injectable'; import { Grant } from '../grant'; +import { RoleReference } from '../iam.generated'; import { IManagedPolicy } from '../managed-policy'; import { Policy } from '../policy'; import { PolicyDocument } from '../policy-document'; @@ -105,6 +106,13 @@ export class PrecreatedRole extends Resource implements IRole { }); } + public get roleRef(): RoleReference { + return { + roleName: this.roleName, + roleArn: this.roleArn, + }; + } + @MethodMetadata() public attachInlinePolicy(policy: Policy): void { const statements = policy.document.toJSON()?.Statement; diff --git a/packages/aws-cdk-lib/aws-iam/lib/role.ts b/packages/aws-cdk-lib/aws-iam/lib/role.ts index a036dd24900dc..50a60aba63b98 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/role.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/role.ts @@ -1,12 +1,19 @@ -import { Construct, IConstruct, DependencyGroup, Node } from 'constructs'; +import { Construct, DependencyGroup, IConstruct, Node } from 'constructs'; import { Grant } from './grant'; -import { CfnRole } from './iam.generated'; +import { CfnRole, IRoleRef, RoleReference } from './iam.generated'; import { IIdentity } from './identity-base'; import { IManagedPolicy, ManagedPolicy } from './managed-policy'; import { Policy } from './policy'; import { PolicyDocument } from './policy-document'; import { PolicyStatement } from './policy-statement'; -import { AccountPrincipal, AddToPrincipalPolicyResult, ArnPrincipal, IPrincipal, PrincipalPolicyFragment, ServicePrincipal } from './principals'; +import { + AccountPrincipal, + AddToPrincipalPolicyResult, + ArnPrincipal, + IPrincipal, + PrincipalPolicyFragment, + ServicePrincipal, +} from './principals'; import { defaultAddPrincipalToAssumeRole } from './private/assume-role-policy'; import { ImmutableRole } from './private/immutable-role'; import { ImportedRole } from './private/imported-role'; @@ -14,8 +21,25 @@ import { MutatingPolicyDocumentAdapter } from './private/policydoc-adapter'; import { PrecreatedRole } from './private/precreated-role'; import { AttachedPolicies, UniqueStringSet } from './private/util'; import * as cxschema from '../../cloud-assembly-schema'; -import { ArnFormat, Duration, Resource, Stack, Token, TokenComparison, Aspects, Annotations, RemovalPolicy, ContextProvider, ValidationError } from '../../core'; -import { getCustomizeRolesConfig, getPrecreatedRoleConfig, CUSTOMIZE_ROLES_CONTEXT_KEY, CustomizeRoleConfig } from '../../core/lib/helpers-internal'; +import { + Annotations, + ArnFormat, + Aspects, + ContextProvider, + Duration, + RemovalPolicy, + Resource, + Stack, + Token, + TokenComparison, + ValidationError, +} from '../../core'; +import { + CUSTOMIZE_ROLES_CONTEXT_KEY, + CustomizeRoleConfig, + getCustomizeRolesConfig, + getPrecreatedRoleConfig, +} from '../../core/lib/helpers-internal'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; import { mutatingAspectPrio32333 } from '../../core/lib/private/aspect-prio'; import { propertyInjectable } from '../../core/lib/prop-injectable'; @@ -577,6 +601,13 @@ export class Role extends Resource implements IRole { this.node.addValidation({ validate: () => this.validateRole() }); } + public get roleRef(): RoleReference { + return { + roleName: this.roleName, + roleArn: this.roleArn, + }; + } + /** * Adds a permission to the role's default policy document. * If there is no default policy attached to this role, it will be created. @@ -787,7 +818,7 @@ export class Role extends Resource implements IRole { /** * A Role object */ -export interface IRole extends IIdentity { +export interface IRole extends IIdentity, IRoleRef { /** * Returns the ARN of this role. * diff --git a/packages/aws-cdk-lib/aws-iam/lib/saml-provider.ts b/packages/aws-cdk-lib/aws-iam/lib/saml-provider.ts index d9a29348baae0..211e40e19ba8c 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/saml-provider.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/saml-provider.ts @@ -1,6 +1,6 @@ import * as fs from 'fs'; import { Construct } from 'constructs'; -import { CfnSAMLProvider } from './iam.generated'; +import { CfnSAMLProvider, ISAMLProviderRef, SAMLProviderReference } from './iam.generated'; import { IResource, Resource, Token, ValidationError } from '../../core'; import { addConstructMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; @@ -8,7 +8,7 @@ import { propertyInjectable } from '../../core/lib/prop-injectable'; /** * A SAML provider */ -export interface ISamlProvider extends IResource { +export interface ISamlProvider extends IResource, ISAMLProviderRef { /** * The Amazon Resource Name (ARN) of the provider * @@ -83,6 +83,7 @@ export class SamlProvider extends Resource implements ISamlProvider { public static fromSamlProviderArn(scope: Construct, id: string, samlProviderArn: string): ISamlProvider { class Import extends Resource implements ISamlProvider { public readonly samlProviderArn = samlProviderArn; + public samlProviderRef: SAMLProviderReference = { samlProviderArn }; } return new Import(scope, id); } @@ -105,4 +106,10 @@ export class SamlProvider extends Resource implements ISamlProvider { this.samlProviderArn = samlProvider.ref; } + + public get samlProviderRef(): SAMLProviderReference { + return { + samlProviderArn: this.samlProviderArn, + }; + } } diff --git a/packages/aws-cdk-lib/aws-iam/lib/user.ts b/packages/aws-cdk-lib/aws-iam/lib/user.ts index 547ae436ba7d8..67caa906d33c6 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/user.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/user.ts @@ -1,6 +1,6 @@ import { Construct } from 'constructs'; import { IGroup } from './group'; -import { CfnUser, CfnUserToGroupAddition } from './iam.generated'; +import { CfnUser, CfnUserToGroupAddition, IUserRef, UserReference } from './iam.generated'; import { IIdentity } from './identity-base'; import { IManagedPolicy } from './managed-policy'; import { Policy } from './policy'; @@ -16,7 +16,7 @@ import { propertyInjectable } from '../../core/lib/prop-injectable'; * * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html */ -export interface IUser extends IIdentity { +export interface IUser extends IIdentity, IUserRef { /** * The user's name * @attribute @@ -229,6 +229,13 @@ export class User extends Resource implements IIdentity, IUser { public addManagedPolicy(_policy: IManagedPolicy): void { throw new ValidationError('Cannot add managed policy to imported User', this); } + + public get userRef(): UserReference { + return { + userName: this.userName, + userArn: this.userArn, + }; + } } return new Import(scope, id); @@ -297,6 +304,13 @@ export class User extends Resource implements IIdentity, IUser { } } + public get userRef(): UserReference { + return { + userName: this.userName, + userArn: this.userArn, + }; + } + /** * Adds this user to a group. */ diff --git a/packages/aws-cdk-lib/aws-iam/test/custom-resource/index.js b/packages/aws-cdk-lib/aws-iam/test/custom-resource/index.js index e69de29bb2d1d..3918c74e44633 100644 --- a/packages/aws-cdk-lib/aws-iam/test/custom-resource/index.js +++ b/packages/aws-cdk-lib/aws-iam/test/custom-resource/index.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/aws-cdk-lib/aws-kms/lib/alias.ts b/packages/aws-cdk-lib/aws-kms/lib/alias.ts index 801ace2813050..46c12d809e1a4 100644 --- a/packages/aws-cdk-lib/aws-kms/lib/alias.ts +++ b/packages/aws-cdk-lib/aws-kms/lib/alias.ts @@ -1,6 +1,6 @@ import { Construct } from 'constructs'; import { IKey } from './key'; -import { CfnAlias } from './kms.generated'; +import { AliasReference, CfnAlias, IAliasRef, KeyReference } from './kms.generated'; import * as iam from '../../aws-iam'; import * as perms from './private/perms'; import { FeatureFlags, RemovalPolicy, Resource, Stack, Token, Tokenization, ValidationError } from '../../core'; @@ -15,7 +15,7 @@ const DISALLOWED_PREFIX = REQUIRED_ALIAS_PREFIX + 'aws/'; * A KMS Key alias. * An alias can be used in all places that expect a key. */ -export interface IAlias extends IKey { +export interface IAlias extends IKey, IAliasRef { /** * The name of the alias. * @@ -62,6 +62,16 @@ abstract class AliasBase extends Resource implements IAlias { public abstract readonly aliasTargetKey: IKey; + public get aliasRef(): AliasReference { + return { + aliasName: this.aliasName, + }; + } + + public get keyRef(): KeyReference { + return this.aliasTargetKey.keyRef; + } + /** * The ARN of the alias. * @@ -209,6 +219,10 @@ export class Alias extends AliasBase { return { statementAdded: false }; } + public get keyRef(): KeyReference { + return this.aliasTargetKey.keyRef; + } + public grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant { if (!FeatureFlags.of(this).isEnabled(KMS_APPLY_IMPORTED_ALIAS_PERMISSIONS_TO_PRINCIPAL)) { return iam.Grant.drop(grantee, ''); @@ -229,6 +243,12 @@ export class Alias extends AliasBase { }); } + public get aliasRef(): AliasReference { + return { + aliasName: this.aliasName, + }; + } + public grantDecrypt(grantee: iam.IGrantable): iam.Grant { return this.grant(grantee, ...perms.DECRYPT_ACTIONS); } diff --git a/packages/aws-cdk-lib/aws-kms/lib/key.ts b/packages/aws-cdk-lib/aws-kms/lib/key.ts index aeebd716af54f..5d279e1611ada 100644 --- a/packages/aws-cdk-lib/aws-kms/lib/key.ts +++ b/packages/aws-cdk-lib/aws-kms/lib/key.ts @@ -1,7 +1,7 @@ import { Construct } from 'constructs'; import { Alias } from './alias'; import { KeyLookupOptions } from './key-lookup'; -import { CfnKey } from './kms.generated'; +import { CfnKey, IKeyRef, KeyReference } from './kms.generated'; import * as perms from './private/perms'; import * as iam from '../../aws-iam'; import * as cxschema from '../../cloud-assembly-schema'; @@ -27,7 +27,7 @@ import * as cxapi from '../../cx-api'; /** * A KMS Key, either managed by this CDK app, or imported. */ -export interface IKey extends IResource { +export interface IKey extends IResource, IKeyRef { /** * The ARN of the key. * @@ -141,6 +141,13 @@ abstract class KeyBase extends Resource implements IKey { this.node.addValidation({ validate: () => this.policy?.validateForResourcePolicy() ?? [] }); } + public get keyRef(): KeyReference { + return { + keyArn: this.keyArn, + keyId: this.keyId, + }; + } + /** * Defines a new alias for the key. */ diff --git a/packages/aws-cdk-lib/aws-lambda/lib/alias.ts b/packages/aws-cdk-lib/aws-lambda/lib/alias.ts index e7b0797d34db3..9c4703d7adca5 100644 --- a/packages/aws-cdk-lib/aws-lambda/lib/alias.ts +++ b/packages/aws-cdk-lib/aws-lambda/lib/alias.ts @@ -3,7 +3,7 @@ import { Architecture } from './architecture'; import { EventInvokeConfigOptions } from './event-invoke-config'; import { IFunction, QualifiedFunctionBase } from './function-base'; import { extractQualifierFromArn, IVersion } from './lambda-version'; -import { CfnAlias } from './lambda.generated'; +import { AliasReference, CfnAlias, IAliasRef } from './lambda.generated'; import { ScalableFunctionAttribute } from './private/scalable-function-attribute'; import { AutoScalingOptions, IScalableFunctionAttribute } from './scalable-attribute-api'; import * as appscaling from '../../aws-applicationautoscaling'; @@ -14,7 +14,7 @@ import { ValidationError } from '../../core/lib/errors'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; -export interface IAlias extends IFunction { +export interface IAlias extends IFunction, IAliasRef { /** * Name of this alias. * @@ -109,6 +109,12 @@ export class Alias extends QualifiedFunctionBase implements IAlias { protected readonly canCreatePermissions = this._isStackAccount(); protected readonly qualifier = attrs.aliasName; + + public get aliasRef(): AliasReference { + return { + aliasArn: this.functionArn, + }; + } } return new Imported(scope, id); } @@ -202,6 +208,12 @@ export class Alias extends QualifiedFunctionBase implements IAlias { this.functionName = `${this.stack.splitArn(this.functionArn, ArnFormat.COLON_RESOURCE_NAME).resourceName!}:${this.aliasName}`; } + public get aliasRef(): AliasReference { + return { + aliasArn: this.functionArn, + }; + } + public get grantPrincipal() { return this.version.grantPrincipal; } diff --git a/packages/aws-cdk-lib/aws-lambda/lib/code-signing-config.ts b/packages/aws-cdk-lib/aws-lambda/lib/code-signing-config.ts index 613c9d1adf882..f398e6d07aed4 100644 --- a/packages/aws-cdk-lib/aws-lambda/lib/code-signing-config.ts +++ b/packages/aws-cdk-lib/aws-lambda/lib/code-signing-config.ts @@ -1,5 +1,5 @@ import { Construct } from 'constructs'; -import { CfnCodeSigningConfig } from './lambda.generated'; +import { CfnCodeSigningConfig, CodeSigningConfigReference, ICodeSigningConfigRef } from './lambda.generated'; import { ISigningProfile } from '../../aws-signer'; import { ArnFormat, IResource, Resource, Stack } from '../../core'; import { ValidationError } from '../../core/lib/errors'; @@ -25,7 +25,7 @@ export enum UntrustedArtifactOnDeployment { /** * A Code Signing Config */ -export interface ICodeSigningConfig extends IResource { +export interface ICodeSigningConfig extends IResource, ICodeSigningConfigRef { /** * The ARN of Code Signing Config * @attribute @@ -100,6 +100,12 @@ export class CodeSigningConfig extends Resource implements ICodeSigningConfig { constructor() { super(scope, id); } + + public get codeSigningConfigRef(): CodeSigningConfigReference { + return { + codeSigningConfigArn: this.codeSigningConfigArn, + }; + } } return new Import(); } @@ -128,4 +134,10 @@ export class CodeSigningConfig extends Resource implements ICodeSigningConfig { this.codeSigningConfigArn = resource.attrCodeSigningConfigArn; this.codeSigningConfigId = resource.attrCodeSigningConfigId; } + + public get codeSigningConfigRef(): CodeSigningConfigReference { + return { + codeSigningConfigArn: this.codeSigningConfigArn, + }; + } } diff --git a/packages/aws-cdk-lib/aws-lambda/lib/event-source-mapping.ts b/packages/aws-cdk-lib/aws-lambda/lib/event-source-mapping.ts index df14694d7bbc7..b89a3693013d3 100644 --- a/packages/aws-cdk-lib/aws-lambda/lib/event-source-mapping.ts +++ b/packages/aws-cdk-lib/aws-lambda/lib/event-source-mapping.ts @@ -1,7 +1,7 @@ import { Construct } from 'constructs'; import { IEventSourceDlq } from './dlq'; import { IFunction } from './function-base'; -import { CfnEventSourceMapping } from './lambda.generated'; +import { CfnEventSourceMapping, EventSourceMappingReference, IEventSourceMappingRef } from './lambda.generated'; import { ISchemaRegistry } from './schema-registry'; import * as iam from '../../aws-iam'; import { IKey } from '../../aws-kms'; @@ -352,7 +352,7 @@ export interface EventSourceMappingProps extends EventSourceMappingOptions { * Represents an event source mapping for a lambda function. * @see https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventsourcemapping.html */ -export interface IEventSourceMapping extends cdk.IResource { +export interface IEventSourceMapping extends cdk.IResource, IEventSourceMappingRef { /** * The identifier for this EventSourceMapping * @attribute @@ -401,6 +401,13 @@ export class EventSourceMapping extends cdk.Resource implements IEventSourceMapp class Import extends cdk.Resource implements IEventSourceMapping { public readonly eventSourceMappingId = eventSourceMappingId; public readonly eventSourceMappingArn = eventSourceMappingArn; + + public get eventSourceMappingRef(): EventSourceMappingReference { + return { + eventSourceMappingId, + eventSourceMappingArn, + }; + } } return new Import(scope, id); } @@ -570,6 +577,13 @@ export class EventSourceMapping extends cdk.Resource implements IEventSourceMapp this.eventSourceMappingArn = EventSourceMapping.formatArn(this, this.eventSourceMappingId); } + public get eventSourceMappingRef(): EventSourceMappingReference { + return { + eventSourceMappingId: this.eventSourceMappingId, + eventSourceMappingArn: this.eventSourceMappingArn, + }; + } + private validateKafkaConsumerGroupIdOrThrow(kafkaConsumerGroupId: string) { if (cdk.Token.isUnresolved(kafkaConsumerGroupId)) { return; diff --git a/packages/aws-cdk-lib/aws-lambda/lib/function-base.ts b/packages/aws-cdk-lib/aws-lambda/lib/function-base.ts index 0004962970d2b..646cf08f488dc 100644 --- a/packages/aws-cdk-lib/aws-lambda/lib/function-base.ts +++ b/packages/aws-cdk-lib/aws-lambda/lib/function-base.ts @@ -5,20 +5,20 @@ import { Architecture } from './architecture'; import { EventInvokeConfig, EventInvokeConfigOptions } from './event-invoke-config'; import { IEventSource } from './event-source'; import { EventSourceMapping, EventSourceMappingOptions } from './event-source-mapping'; -import { FunctionUrlAuthType, FunctionUrlOptions, FunctionUrl } from './function-url'; +import { FunctionUrl, FunctionUrlAuthType, FunctionUrlOptions } from './function-url'; import { IVersion } from './lambda-version'; -import { CfnPermission } from './lambda.generated'; +import { CfnPermission, FunctionReference, IFunctionRef, VersionReference } from './lambda.generated'; import { Permission } from './permission'; import { addAlias, flatMap } from './util'; import * as cloudwatch from '../../aws-cloudwatch'; import * as ec2 from '../../aws-ec2'; import * as iam from '../../aws-iam'; -import { Annotations, ArnFormat, IResource, Resource, Token, Stack, FeatureFlags } from '../../core'; +import { Annotations, ArnFormat, FeatureFlags, IResource, Resource, Stack, Token } from '../../core'; import { ValidationError } from '../../core/lib/errors'; import { MethodMetadata } from '../../core/lib/metadata-resource'; import * as cxapi from '../../cx-api'; -export interface IFunction extends IResource, ec2.IConnectable, iam.IGrantable { +export interface IFunction extends IResource, ec2.IConnectable, iam.IGrantable, IFunctionRef { /** * The name of the function. @@ -342,6 +342,13 @@ export abstract class FunctionBase extends Resource implements IFunction, ec2.IC */ private _hasAddedArrayTokenStatements: boolean = false; + public get functionRef(): FunctionReference { + return { + functionName: this.functionName, + functionArn: this.functionArn, + }; + } + /** * A warning will be added to functions under the following conditions: * - permissions that include `lambda:InvokeFunction` are added to the unqualified function. @@ -857,6 +864,16 @@ class LatestVersion extends FunctionBase implements IVersion { this.lambda = lambda; } + public get versionRef(): VersionReference { + return { + functionArn: this.functionRef.functionArn, + }; + } + + public get functionRef() { + return this.lambda.functionRef; + } + public get functionArn() { return `${this.lambda.functionArn}:${this.version}`; } diff --git a/packages/aws-cdk-lib/aws-lambda/lib/lambda-version.ts b/packages/aws-cdk-lib/aws-lambda/lib/lambda-version.ts index 4738d3b0ab95d..9b518678f73d9 100644 --- a/packages/aws-cdk-lib/aws-lambda/lib/lambda-version.ts +++ b/packages/aws-cdk-lib/aws-lambda/lib/lambda-version.ts @@ -5,7 +5,7 @@ import { Architecture } from './architecture'; import { EventInvokeConfigOptions } from './event-invoke-config'; import { Function } from './function'; import { IFunction, QualifiedFunctionBase } from './function-base'; -import { CfnVersion } from './lambda.generated'; +import { CfnVersion, IVersionRef, VersionReference } from './lambda.generated'; import { addAlias } from './util'; import * as cloudwatch from '../../aws-cloudwatch'; import { Fn, Lazy, RemovalPolicy, Token } from '../../core'; @@ -13,7 +13,7 @@ import { ValidationError } from '../../core/lib/errors'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; -export interface IVersion extends IFunction { +export interface IVersion extends IFunction, IVersionRef { /** * The most recently deployed version of this function. * @attribute @@ -154,6 +154,12 @@ export class Version extends QualifiedFunctionBase implements IVersion { } return this.functionArn; } + + public get versionRef(): VersionReference { + return { + functionArn: this.functionArn, + }; + } } return new Import(scope, id); } @@ -181,6 +187,12 @@ export class Version extends QualifiedFunctionBase implements IVersion { } return this.functionArn; } + + public get versionRef(): VersionReference { + return { + functionArn: this.functionArn, + }; + } } return new Import(scope, id); } @@ -231,6 +243,12 @@ export class Version extends QualifiedFunctionBase implements IVersion { } } + public get versionRef(): VersionReference { + return { + functionArn: this.functionArn, + }; + } + public get grantPrincipal() { return this.lambda.grantPrincipal; } diff --git a/packages/aws-cdk-lib/aws-lambda/lib/layers.ts b/packages/aws-cdk-lib/aws-lambda/lib/layers.ts index c5c196380a4bf..eb3b5d040e862 100644 --- a/packages/aws-cdk-lib/aws-lambda/lib/layers.ts +++ b/packages/aws-cdk-lib/aws-lambda/lib/layers.ts @@ -1,7 +1,12 @@ import { Construct } from 'constructs'; import { Architecture } from './architecture'; import { Code } from './code'; -import { CfnLayerVersion, CfnLayerVersionPermission } from './lambda.generated'; +import { + CfnLayerVersion, + CfnLayerVersionPermission, + ILayerVersionRef, + LayerVersionReference, +} from './lambda.generated'; import { Runtime } from './runtime'; import { IResource, RemovalPolicy, Resource } from '../../core'; import { ValidationError } from '../../core/lib/errors'; @@ -64,7 +69,7 @@ export interface LayerVersionProps extends LayerVersionOptions { readonly code: Code; } -export interface ILayerVersion extends IResource { +export interface ILayerVersion extends IResource, ILayerVersionRef { /** * The ARN of the Lambda Layer version that this Layer defines. * @attribute @@ -99,6 +104,12 @@ abstract class LayerVersionBase extends Resource implements ILayerVersion { public abstract readonly layerVersionArn: string; public abstract readonly compatibleRuntimes?: Runtime[]; + public get layerVersionRef(): LayerVersionReference { + return { + layerVersionArn: this.layerVersionArn, + }; + } + public addPermission(id: string, permission: LayerVersionPermission) { if (permission.organizationId != null && permission.accountId !== '*') { throw new ValidationError(`OrganizationId can only be specified if AwsAccountId is '*', but it is ${permission.accountId}`, this); diff --git a/packages/aws-cdk-lib/aws-s3/lib/bucket-policy.ts b/packages/aws-cdk-lib/aws-s3/lib/bucket-policy.ts index da61e88b52778..002dc781b3d1c 100644 --- a/packages/aws-cdk-lib/aws-s3/lib/bucket-policy.ts +++ b/packages/aws-cdk-lib/aws-s3/lib/bucket-policy.ts @@ -1,6 +1,6 @@ import { Construct } from 'constructs'; import { Bucket, IBucket } from './bucket'; -import { CfnBucket, CfnBucketPolicy } from './s3.generated'; +import { BucketPolicyReference, CfnBucket, CfnBucketPolicy, IBucketPolicyRef } from './s3.generated'; import { PolicyDocument } from '../../aws-iam'; import { RemovalPolicy, Resource, Token, Tokenization } from '../../core'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; @@ -49,7 +49,7 @@ export interface BucketPolicyProps { * */ @propertyInjectable -export class BucketPolicy extends Resource { +export class BucketPolicy extends Resource implements IBucketPolicyRef { /** Uniquely identifies this class. */ public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-s3.BucketPolicy'; @@ -88,11 +88,14 @@ export class BucketPolicy extends Resource { }(cfnBucketPolicy, id, { bucket, }); + // mark the Bucket as having this Policy bucket.policy = ret; return ret; } + public readonly bucketPolicyRef: BucketPolicyReference; + /** * A policy document containing permissions to add to the specified bucket. * For more information, see Access Policy Language Overview in the Amazon @@ -116,6 +119,7 @@ export class BucketPolicy extends Resource { bucket: this.bucket.bucketName, policyDocument: this.document, }); + this.bucketPolicyRef = this.resource.bucketPolicyRef; if (props.removalPolicy) { this.resource.applyRemovalPolicy(props.removalPolicy); diff --git a/packages/aws-cdk-lib/aws-s3/lib/bucket.ts b/packages/aws-cdk-lib/aws-s3/lib/bucket.ts index 30a2dc224a7b5..76482f0343498 100644 --- a/packages/aws-cdk-lib/aws-s3/lib/bucket.ts +++ b/packages/aws-cdk-lib/aws-s3/lib/bucket.ts @@ -5,18 +5,20 @@ import { IBucketNotificationDestination } from './destination'; import { BucketNotifications } from './notifications-resource'; import * as perms from './perms'; import { LifecycleRule, StorageClass } from './rule'; -import { CfnBucket } from './s3.generated'; +import { BucketReference, CfnBucket, IBucketRef } from './s3.generated'; import { parseBucketArn, parseBucketName } from './util'; import * as events from '../../aws-events'; import * as iam from '../../aws-iam'; import * as kms from '../../aws-kms'; import { + Annotations, CustomResource, Duration, FeatureFlags, Fn, IResource, Lazy, + PhysicalName, RemovalPolicy, Resource, ResourceProps, @@ -24,21 +26,21 @@ import { Tags, Token, Tokenization, - Annotations, - PhysicalName, } from '../../core'; import { UnscopedValidationError, ValidationError } from '../../core/lib/errors'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; import { CfnReference } from '../../core/lib/private/cfn-reference'; import { propertyInjectable } from '../../core/lib/prop-injectable'; -import { AutoDeleteObjectsProvider } from '../../custom-resource-handlers/dist/aws-s3/auto-delete-objects-provider.generated'; +import { + AutoDeleteObjectsProvider, +} from '../../custom-resource-handlers/dist/aws-s3/auto-delete-objects-provider.generated'; import * as cxapi from '../../cx-api'; import * as regionInformation from '../../region-info'; const AUTO_DELETE_OBJECTS_RESOURCE_TYPE = 'Custom::S3AutoDeleteObjects'; const AUTO_DELETE_OBJECTS_TAG = 'aws-cdk:auto-delete-objects'; -export interface IBucket extends IResource { +export interface IBucket extends IResource, IBucketRef { /** * The ARN of the bucket. * @attribute @@ -1150,6 +1152,13 @@ export abstract class BucketBase extends Resource implements IBucket { return ret; } + + public get bucketRef(): BucketReference { + return { + bucketArn: this.bucketArn, + bucketName: this.bucketName, + }; + } } export interface BlockPublicAccessOptions { diff --git a/packages/awslint/lib/rules/resource.ts b/packages/awslint/lib/rules/resource.ts index 243319b0defec..f9a51e89cd30e 100644 --- a/packages/awslint/lib/rules/resource.ts +++ b/packages/awslint/lib/rules/resource.ts @@ -79,6 +79,9 @@ export class ResourceReflection { /** * Attribute properties are all the properties that begin with the type name (e.g. bucketXxx). + * + * We are adding a `bucketRef` property as well that we don't necessarily want to hold to the same linter + * rules as the other attributes, so we don't consider it an attribute. */ private findAttributeProperties(): Attribute[] { const result = new Array(); @@ -87,6 +90,9 @@ export class ResourceReflection { if (p.protected) { continue; // skip any protected properties } + if (p.name.endsWith('Ref')) { + continue; // skip any "Ref" properties, these are not attributes + } const basename = camelize(this.cfn.basename); From 5f9fb8c1466abc4a8d91ba0267f71cc312ad3d4c Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Tue, 2 Sep 2025 15:26:13 +0100 Subject: [PATCH 26/26] feat: update references to use new shared resource interface (ref-interfaces #3) (#35282) Using the updated interfaces from https://github.com/aws/aws-cdk/pull/35271. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --------- Co-authored-by: Rico Huijbers Co-authored-by: Feng He Co-authored-by: Kazuho Cryer-Shinozuka Co-authored-by: Chooi Je Qin <42904912+jeqcho@users.noreply.github.com> Co-authored-by: claypack <56490116+claypack@users.noreply.github.com> Co-authored-by: Hung Tran <40334379+phuhung273@users.noreply.github.com> Co-authored-by: matoom-nomu <121716425+matoom-nomu@users.noreply.github.com> --- ...efaultTestDeployAssertB25F4037.assets.json | 5 +- .../cdk.out | 2 +- .../integ-distribution-function.assets.json | 9 +- .../integ-distribution-function.template.json | 10 +- .../integ.json | 5 +- .../manifest.json | 522 ++++++- .../tree.json | 266 +--- ...efaultTestDeployAssert9D427BC1.assets.json | 5 +- .../cdk.out | 2 +- .../integ-distribution-function.assets.json | 9 +- .../integ-distribution-function.template.json | 5 +- .../integ.json | 5 +- .../manifest.json | 508 ++++++- .../tree.json | 211 +-- ...dk-rds-integ-with-feature-flag.assets.json | 9 +- ...-rds-integ-with-feature-flag.template.json | 1 + .../aws-cdk-rds-integ.assets.json | 9 +- .../aws-cdk-rds-integ.template.json | 1 + .../test/integ.cluster.js.snapshot/cdk.out | 2 +- .../test/integ.cluster.js.snapshot/integ.json | 5 +- .../integ.cluster.js.snapshot/manifest.json | 679 ++++++++- ...efaultTestDeployAssert23E53F17.assets.json | 5 +- ...efaultTestDeployAssert8E2E540B.assets.json | 5 +- .../test/integ.cluster.js.snapshot/tree.json | 1237 +---------------- .../test/aws-rds/test/integ.cluster.ts | 2 +- .../test/integ.assets.bundling.docker-opts.ts | 5 +- ...efaultTestDeployAssert27FE8CA6.assets.json | 20 + ...aultTestDeployAssert27FE8CA6.template.json | 36 + .../index.js | 1 + .../cdk.out | 1 + .../evaluate-expression-nodejs22.assets.json | 34 + ...evaluate-expression-nodejs22.template.json | 201 +++ .../integ.json | 13 + .../manifest.json | 787 +++++++++++ .../tree.json | 1 + .../integ.evaluate-expression-nodejs22.ts | 27 + .../aws-apprunner-alpha/lib/service.ts | 4 +- .../bedrock/agents/api-schema.ts | 6 +- .../lib/github-repository.ts | 4 +- packages/@aws-cdk/aws-ec2-alpha/lib/util.ts | 4 +- .../@aws-cdk/aws-eks-v2-alpha/lib/cluster.ts | 4 +- .../lib/security-configuration.ts | 18 +- .../test/security-configuration.test.ts | 8 +- .../lib/recording-configuration.ts | 6 +- .../lib/geofence-collection.ts | 4 +- .../aws-location-alpha/lib/tracker.ts | 4 +- .../@aws-cdk/aws-msk-alpha/lib/cluster.ts | 6 +- .../@aws-cdk/aws-neptune-alpha/lib/cluster.ts | 8 +- .../aws-redshift-alpha/lib/cluster.ts | 4 +- .../lib/access-point.ts | 4 +- .../lib/endpoint-config.ts | 4 +- .../aws-apigateway/lib/access-log.ts | 8 +- .../aws-apigateway/lib/api-definition.ts | 13 +- .../aws-cdk-lib/aws-apigateway/lib/api-key.ts | 6 +- .../aws-apigateway/lib/base-path-mapping.ts | 13 +- .../aws-apigateway/lib/deployment.ts | 8 +- .../aws-apigateway/lib/domain-name.ts | 11 +- .../aws-cdk-lib/aws-apigateway/lib/method.ts | 25 +- .../aws-cdk-lib/aws-apigateway/lib/restapi.ts | 4 +- .../aws-apigateway/lib/usage-plan.ts | 8 +- .../aws-apigatewayv2/lib/http/integration.ts | 6 +- .../aws-apigatewayv2/lib/http/vpc-link.ts | 14 +- .../aws-appconfig/lib/configuration.ts | 83 +- .../aws-appconfig/lib/environment.ts | 4 +- .../aws-appconfig/lib/extension.ts | 6 +- .../aws-appsync/lib/appsync-common.ts | 4 +- .../aws-cdk-lib/aws-appsync/lib/eventapi.ts | 4 +- .../aws-cdk-lib/aws-appsync/lib/graphqlapi.ts | 6 +- .../aws-cdk-lib/aws-backup/lib/resource.ts | 4 +- packages/aws-cdk-lib/aws-backup/lib/vault.ts | 4 +- .../lib/managed-compute-environment.ts | 33 +- .../aws-certificatemanager/README.md | 11 + .../aws-certificatemanager/lib/certificate.ts | 13 + .../lib/private-certificate.ts | 13 + .../test/certificate.test.ts | 42 + .../test/dns-validated-certificate.test.ts | 2 - .../test/private-certificate.test.ts | 48 + .../aws-cloudfront/lib/distribution.ts | 20 +- .../aws-cloudfront/lib/function.ts | 9 +- .../aws-cloudfront/lib/key-group.ts | 7 +- .../lib/private/cache-behavior.ts | 12 +- .../lib/response-headers-policy.ts | 5 + .../aws-cloudfront/lib/web-distribution.ts | 2 +- .../aws-cloudfront/test/distribution.test.ts | 11 +- .../test/response-headers-policy.test.ts | 15 + .../test/web-distribution.test.ts | 5 +- .../aws-cloudtrail/lib/cloudtrail.ts | 8 +- .../aws-codecommit/lib/repository.ts | 4 +- .../lib/identitypool.ts | 18 +- .../aws-cognito/lib/user-pool-client.ts | 6 +- .../aws-cognito/lib/user-pool-group.ts | 6 +- .../aws-cdk-lib/aws-cognito/lib/user-pool.ts | 14 +- .../aws-config/lib/managed-rules.ts | 6 +- .../aws-ec2/lib/cfn-init-elements.ts | 4 +- .../lib/client-vpn-authorization-rule.ts | 9 +- .../aws-ec2/lib/client-vpn-endpoint.ts | 10 +- .../aws-ec2/lib/client-vpn-route.ts | 7 +- .../aws-cdk-lib/aws-ec2/lib/instance-types.ts | 52 + packages/aws-cdk-lib/aws-ec2/lib/instance.ts | 7 +- .../aws-ec2/lib/launch-template.ts | 7 +- .../aws-cdk-lib/aws-ec2/lib/network-acl.ts | 47 +- .../aws-ec2/lib/private/conversions.ts | 19 + packages/aws-cdk-lib/aws-ec2/lib/user-data.ts | 8 +- packages/aws-cdk-lib/aws-ec2/lib/volume.ts | 15 +- .../aws-cdk-lib/aws-ec2/lib/vpc-flow-logs.ts | 8 +- packages/aws-cdk-lib/aws-ec2/lib/vpc.ts | 2 +- .../client-vpn-authorization-rule.test.ts | 12 + .../aws-cdk-lib/aws-ecr/lib/repository.ts | 4 +- .../aws-ecs/lib/base/base-service.ts | 10 +- packages/aws-cdk-lib/aws-ecs/lib/cluster.ts | 6 +- .../aws-efs/lib/efs-file-system.ts | 4 +- .../aws-eks/lib/cluster-resource.ts | 4 +- packages/aws-cdk-lib/aws-eks/lib/cluster.ts | 4 +- .../lib/alb/trust-store-revocation.ts | 6 +- .../lib/alb/trust-store.ts | 8 +- .../aws-elasticsearch/lib/domain.ts | 6 +- .../aws-cdk-lib/aws-events-targets/README.md | 66 +- packages/aws-cdk-lib/aws-events/lib/rule.ts | 6 +- .../aws-cdk-lib/aws-fsx/lib/file-system.ts | 4 +- .../aws-fsx/lib/lustre-file-system.ts | 2 +- .../aws-cdk-lib/aws-iam/lib/managed-policy.ts | 34 +- .../aws-cdk-lib/aws-iam/lib/principals.ts | 12 +- packages/aws-cdk-lib/aws-iam/lib/user.ts | 2 +- packages/aws-cdk-lib/aws-kms/lib/key.ts | 4 +- packages/aws-cdk-lib/aws-lambda/lib/code.ts | 14 +- .../aws-cdk-lib/aws-lambda/lib/function.ts | 11 +- .../aws-logs/lib/cross-account-destination.ts | 4 +- .../aws-logs/lib/data-protection-policy.ts | 7 +- .../aws-cdk-lib/aws-logs/lib/log-group.ts | 4 +- .../aws-logs/lib/subscription-filter.ts | 2 +- .../aws-opensearchservice/lib/domain.ts | 10 +- packages/aws-cdk-lib/aws-rds/README.md | 18 + .../aws-rds/lib/aurora-cluster-instance.ts | 6 +- .../aws-cdk-lib/aws-rds/lib/cluster-engine.ts | 8 +- packages/aws-cdk-lib/aws-rds/lib/cluster.ts | 18 +- .../aws-rds/lib/instance-engine.ts | 6 +- packages/aws-cdk-lib/aws-rds/lib/instance.ts | 22 +- .../aws-cdk-lib/aws-rds/test/cluster.test.ts | 21 + .../aws-cdk-lib/aws-route53/lib/record-set.ts | 6 +- .../lib/vpc-endpoint-service-domain-name.ts | 8 +- .../aws-cdk-lib/aws-s3-assets/lib/asset.ts | 2 +- .../lib/bucket-deployment.ts | 7 +- .../aws-s3-notifications/lib/lambda.ts | 6 +- .../aws-s3-notifications/lib/sns.ts | 4 +- .../aws-s3-notifications/lib/sqs.ts | 4 +- .../aws-cdk-lib/aws-s3/lib/destination.ts | 4 +- .../aws-secretsmanager/lib/secret.ts | 4 +- .../aws-servicecatalog/lib/constraints.ts | 2 +- .../lib/private/association-manager.ts | 6 +- packages/aws-cdk-lib/aws-sns/lib/topic.ts | 10 +- .../bedrock/create-model-customization-job.ts | 17 +- .../lib/evaluate-expression.ts | 1 + .../lib/sagemaker/base-types.ts | 4 +- .../lib/sagemaker/create-endpoint-config.ts | 4 +- .../lib/sagemaker/create-transform-job.ts | 4 +- .../lib/stepfunctions/invoke-activity.ts | 6 +- .../test/evaluate-expression.test.ts | 15 + .../states/distributed-map/result-writer.ts | 6 +- .../aws-cdk-lib/aws-synthetics/lib/code.ts | 6 +- .../lib/provider-framework/provider.ts | 4 +- .../pipelines/test/testhelpers/test-app.ts | 6 +- .../lazify/test/no-double-getter.test.ts | 18 +- tools/@aws-cdk/spec2cdk/package.json | 2 +- yarn.lock | 7 + 164 files changed, 3756 insertions(+), 2221 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/asset.b8cec122f25692e8b194663d25a2ee5e0b65e55df966120791d6a3ddc08fc136/index.js create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/evaluate-expression-nodejs22.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/evaluate-expression-nodejs22.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.ts create mode 100644 packages/aws-cdk-lib/aws-ec2/lib/private/conversions.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/CF2RuntimeDefaultTestDeployAssertB25F4037.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/CF2RuntimeDefaultTestDeployAssertB25F4037.assets.json index 52bf1e5df20a8..e81eb8ba9e016 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/CF2RuntimeDefaultTestDeployAssertB25F4037.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/CF2RuntimeDefaultTestDeployAssertB25F4037.assets.json @@ -1,13 +1,14 @@ { - "version": "36.0.0", + "version": "48.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "CF2RuntimeDefaultTestDeployAssertB25F4037 Template", "source": { "path": "CF2RuntimeDefaultTestDeployAssertB25F4037.template.json", "packaging": "file" }, "destinations": { - "current_account-current_region": { + "current_account-current_region-d8d86b35": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/cdk.out index 1f0068d32659a..523a9aac37cbf 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"36.0.0"} \ No newline at end of file +{"version":"48.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/integ-distribution-function.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/integ-distribution-function.assets.json index 4f6d4c6f7b7c1..9b26b3be1b9a6 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/integ-distribution-function.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/integ-distribution-function.assets.json @@ -1,15 +1,16 @@ { - "version": "36.0.0", + "version": "48.0.0", "files": { - "f593b032ca2360f7f5beecafd32ec38ebe7a6cb5c25290e00d0066ebb69be3a2": { + "71d966b3880570a9720c508c102fad2c9fc7c38916f00d7a2906d9d1a0587ee5": { + "displayName": "integ-distribution-function Template", "source": { "path": "integ-distribution-function.template.json", "packaging": "file" }, "destinations": { - "current_account-eu-west-1": { + "current_account-eu-west-1-6a047c00": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-eu-west-1", - "objectKey": "f593b032ca2360f7f5beecafd32ec38ebe7a6cb5c25290e00d0066ebb69be3a2.json", + "objectKey": "71d966b3880570a9720c508c102fad2c9fc7c38916f00d7a2906d9d1a0587ee5.json", "region": "eu-west-1", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-eu-west-1" } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/integ-distribution-function.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/integ-distribution-function.template.json index 27290243856b4..51ff154349bef 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/integ-distribution-function.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/integ-distribution-function.template.json @@ -35,19 +35,13 @@ { "EventType": "viewer-request", "FunctionARN": { - "Fn::GetAtt": [ - "FunctionRequest95528B2F", - "FunctionARN" - ] + "Ref": "FunctionRequest95528B2F" } }, { "EventType": "viewer-response", "FunctionARN": { - "Fn::GetAtt": [ - "FunctionResponse4EF2D1D3", - "FunctionARN" - ] + "Ref": "FunctionResponse4EF2D1D3" } } ], diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/integ.json index 0d701e61e53a2..4a17dc264347a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "36.0.0", + "version": "48.0.0", "testCases": { "CF2Runtime/DefaultTest": { "stacks": [ @@ -8,5 +8,6 @@ "assertionStack": "CF2Runtime/DefaultTest/DeployAssert", "assertionStackName": "CF2RuntimeDefaultTestDeployAssertB25F4037" } - } + }, + "minimumCliVersion": "2.1024.0" } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/manifest.json index 59a615053acc1..62f45834ad37f 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "36.0.0", + "version": "48.0.0", "artifacts": { "integ-distribution-function.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}-eu-west-1", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-eu-west-1", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-eu-west-1/f593b032ca2360f7f5beecafd32ec38ebe7a6cb5c25290e00d0066ebb69be3a2.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-eu-west-1/71d966b3880570a9720c508c102fad2c9fc7c38916f00d7a2906d9d1a0587ee5.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -34,18 +34,59 @@ "integ-distribution-function.assets" ], "metadata": { + "/integ-distribution-function/FunctionRequest": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "code": "*", + "runtime": "*" + } + } + ], "/integ-distribution-function/FunctionRequest/Resource": [ { "type": "aws:cdk:logicalId", "data": "FunctionRequest95528B2F" } ], + "/integ-distribution-function/FunctionResponse": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "code": "*", + "runtime": "*" + } + } + ], "/integ-distribution-function/FunctionResponse/Resource": [ { "type": "aws:cdk:logicalId", "data": "FunctionResponse4EF2D1D3" } ], + "/integ-distribution-function/Dist": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "defaultBehavior": { + "origin": "*", + "cachePolicy": { + "cachePolicyId": "*" + }, + "functionAssociations": [ + { + "function": "*", + "eventType": "viewer-request" + }, + { + "function": "*", + "eventType": "viewer-response" + } + ] + } + } + } + ], "/integ-distribution-function/Dist/Resource": [ { "type": "aws:cdk:logicalId", @@ -144,6 +185,481 @@ "properties": { "file": "tree.json" } + }, + "aws-cdk-lib/feature-flag-report": { + "type": "cdk:feature-flag-report", + "properties": { + "module": "aws-cdk-lib", + "flags": { + "@aws-cdk/aws-signer:signingProfileNamePassedToCfn": { + "recommendedValue": true, + "explanation": "Pass signingProfileName to CfnSigningProfile" + }, + "@aws-cdk/core:newStyleStackSynthesis": { + "recommendedValue": true, + "explanation": "Switch to new stack synthesis method which enables CI/CD", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:stackRelativeExports": { + "recommendedValue": true, + "explanation": "Name exports based on the construct paths relative to the stack, rather than the global construct path", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-rds:lowercaseDbIdentifier": { + "recommendedValue": true, + "explanation": "Force lowercasing of RDS Cluster names in CDK", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": { + "recommendedValue": true, + "explanation": "Allow adding/removing multiple UsagePlanKeys independently", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeVersionProps": { + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeLayerVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`." + }, + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": { + "recommendedValue": true, + "explanation": "Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:checkSecretUsage": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this flag to make it impossible to accidentally use SecretValues in unsafe locations" + }, + "@aws-cdk/core:target-partitions": { + "recommendedValue": [ + "aws", + "aws-cn" + ], + "explanation": "What regions to include in lookup tables of environment agnostic stacks" + }, + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": { + "userValue": true, + "recommendedValue": true, + "explanation": "ECS extensions will automatically add an `awslogs` driver if no logging is specified" + }, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names." + }, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": { + "userValue": true, + "recommendedValue": true, + "explanation": "ARN format used by ECS. In the new ARN format, the cluster name is part of the resource ID." + }, + "@aws-cdk/aws-iam:minimizePolicies": { + "userValue": true, + "recommendedValue": true, + "explanation": "Minimize IAM policies by combining Statements" + }, + "@aws-cdk/core:validateSnapshotRemovalPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Error on snapshot removal policies on resources that do not support it." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate key aliases that include the stack name" + }, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to create an S3 bucket policy by default in cases where an AWS service would automatically create the Policy if one does not exist." + }, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict KMS key policy for encrypted Queues a bit more" + }, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make default CloudWatch Role behavior safe for multiple API Gateways in one environment" + }, + "@aws-cdk/core:enablePartitionLiterals": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make ARNs concrete if AWS partition is known" + }, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": { + "userValue": true, + "recommendedValue": true, + "explanation": "Event Rules may only push to encrypted SQS queues in the same account" + }, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": { + "userValue": true, + "recommendedValue": true, + "explanation": "Avoid setting the \"ECS\" deployment controller when adding a circuit breaker" + }, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature to by default create default policy names for imported roles that depend on the stack the role is in." + }, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use S3 Bucket Policy instead of ACLs for Server Access Logging" + }, + "@aws-cdk/aws-route53-patters:useCertificate": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use the official `Certificate` resource instead of `DnsValidatedCertificate`" + }, + "@aws-cdk/customresources:installLatestAwsSdkDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "Whether to install the latest SDK by default in AwsCustomResource" + }, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use unique resource name for Database Proxy" + }, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Remove CloudWatch alarms from deployment group" + }, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include authorizer configuration in the calculation of the API deployment logical ID." + }, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": { + "userValue": true, + "recommendedValue": true, + "explanation": "Define user data for a launch template by default when a machine image is provided." + }, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": { + "userValue": true, + "recommendedValue": true, + "explanation": "SecretTargetAttachments uses the ResourcePolicy of the attached Secret." + }, + "@aws-cdk/aws-redshift:columnId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Whether to use an ID to track Redshift column changes" + }, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable AmazonEMRServicePolicy_v2 managed policies" + }, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict access to the VPC default security group" + }, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a unique id for each RequestValidator added to a method" + }, + "@aws-cdk/aws-kms:aliasNameRef": { + "userValue": true, + "recommendedValue": true, + "explanation": "KMS Alias name and keyArn will have implicit reference to KMS Key" + }, + "@aws-cdk/aws-kms:applyImportedAliasPermissionsToPrincipal": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable grant methods on Aliases imported by name to use kms:ResourceAliases condition" + }, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a launch template when creating an AutoScalingGroup" + }, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include the stack prefix in the stack name generation process" + }, + "@aws-cdk/aws-efs:denyAnonymousAccess": { + "userValue": true, + "recommendedValue": true, + "explanation": "EFS denies anonymous clients accesses" + }, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables support for Multi-AZ with Standby deployment for opensearch domains" + }, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables aws-lambda-nodejs.Function to use the latest available NodeJs runtime as the default" + }, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, mount targets will have a stable logicalId that is linked to the associated subnet." + }, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a scope of InstanceParameterGroup for AuroraClusterInstance with each parameters will change." + }, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, will always use the arn for identifiers for CfnSourceApiAssociation in the GraphqlApi construct rather than id." + }, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, creating an RDS database cluster from a snapshot will only render credentials for snapshot credentials." + }, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the CodeCommit source action is using the default branch name 'main'." + }, + "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the logical ID of a Lambda permission for a Lambda action includes an alarm ID." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default value for crossAccountKeys to false." + }, + "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default pipeline type to V2." + }, + "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, IAM Policy created from KMS key grant will reduce the resource scope to this key only." + }, + "@aws-cdk/pipelines:reduceAssetRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from PipelineAssetsFileRole trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-eks:nodegroupNameAttribute": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, nodegroupName attribute of the provisioned EKS NodeGroup will not have the cluster name prefix." + }, + "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default volume type of the EBS volume will be GP3" + }, + "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, remove default deployment alarm settings" + }, + "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, the custom resource used for `AwsCustomResource` will configure the `logApiResponseData` property as true by default" + }, + "@aws-cdk/aws-s3:keepNotificationInImportedBucket": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, Adding notifications to a bucket in the current stack will not remove notification from imported stack." + }, + "@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask": { + "recommendedValue": true, + "explanation": "When enabled, use new props for S3 URI field in task definition of state machine for bedrock invoke model.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:explicitStackTags": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, stack tags need to be assigned explicitly on a Stack." + }, + "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": { + "userValue": false, + "recommendedValue": false, + "explanation": "When set to true along with canContainersAccessInstanceRole=false in ECS cluster, new updated commands will be added to UserData to block container accessing IMDS. **Applicable to Linux only. IMPORTANT: See [details.](#aws-cdkaws-ecsenableImdsBlockingDeprecatedFeature)**" + }, + "@aws-cdk/aws-ecs:disableEcsImdsBlocking": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, CDK synth will throw exception if canContainersAccessInstanceRole is false. **IMPORTANT: See [details.](#aws-cdkaws-ecsdisableEcsImdsBlocking)**" + }, + "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, we will only grant the necessary permissions when users specify cloudwatch log group through logConfiguration" + }, + "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled will allow you to specify a resource policy per replica, and not copy the source table policy to all replicas" + }, + "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, initOptions.timeout and resourceSignalTimeout values will be summed together." + }, + "@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a Lambda authorizer Permission created when using GraphqlApi will be properly scoped with a SourceArn." + }, + "@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the value of property `instanceResourceId` in construct `DatabaseInstanceReadReplica` will be set to the correct value which is `DbiResourceId` instead of currently `DbInstanceArn`" + }, + "@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CFN templates added with `cfn-include` will error if the template contains Resource Update or Create policies with CFN Intrinsics that include non-primitive values." + }, + "@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, both `@aws-sdk` and `@smithy` packages will be excluded from the Lambda Node.js 18.x runtime to prevent version mismatches in bundled applications." + }, + "@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resource of IAM Run Ecs policy generated by SFN EcsRunTask will reference the definition, instead of constructing ARN." + }, + "@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the BastionHost construct will use the latest Amazon Linux 2023 AMI, instead of Amazon Linux 2." + }, + "@aws-cdk/core:aspectStabilization": { + "recommendedValue": true, + "explanation": "When enabled, a stabilization loop will be run when invoking Aspects during synthesis.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, use a new method for DNS Name of user pool domain target without creating a custom resource." + }, + "@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default security group ingress rules will allow IPv6 ingress from anywhere" + }, + "@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default behaviour of OIDC provider will reject unauthorized connections" + }, + "@aws-cdk/core:enableAdditionalMetadataCollection": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will expand the scope of usage data collected to better inform CDK development and improve communication for security concerns and emerging issues." + }, + "@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": { + "userValue": false, + "recommendedValue": false, + "explanation": "[Deprecated] When enabled, Lambda will create new inline policies with AddToRolePolicy instead of adding to the Default Policy Statement" + }, + "@aws-cdk/aws-s3:setUniqueReplicationRoleName": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will automatically generate a unique role name that is used for s3 object replication." + }, + "@aws-cdk/pipelines:reduceStageRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from Stage addActions trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-events:requireEventBusPolicySid": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, grantPutEventsTo() will use resource policies with Statement IDs for service principals." + }, + "@aws-cdk/core:aspectPrioritiesMutating": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, Aspects added by the construct library on your behalf will be given a priority of MUTATING." + }, + "@aws-cdk/aws-dynamodb:retainTableReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, table replica will be default to the removal policy of source table unless specified otherwise." + }, + "@aws-cdk/cognito:logUserPoolClientSecretValue": { + "recommendedValue": false, + "explanation": "When disabled, the value of the user pool client secret will not be logged in the custom resource lambda function logs." + }, + "@aws-cdk/pipelines:reduceCrossAccountActionRoleTrustScope": { + "recommendedValue": true, + "explanation": "When enabled, scopes down the trust policy for the cross-account action role", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resultWriterV2 property of DistributedMap will be used insted of resultWriter" + }, + "@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions": { + "userValue": true, + "recommendedValue": true, + "explanation": "Add an S3 trust policy to a KMS key resource policy for SNS subscriptions." + }, + "@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the EgressOnlyGateway resource is only created if private subnets are defined in the dual-stack VPC." + }, + "@aws-cdk/aws-ec2-alpha:useResourceIdForVpcV2Migration": { + "recommendedValue": false, + "explanation": "When enabled, use resource IDs for VPC V2 migration" + }, + "@aws-cdk/aws-s3:publicAccessBlockedByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, setting any combination of options for BlockPublicAccess will automatically set true for any options not defined." + }, + "@aws-cdk/aws-lambda:useCdkManagedLogGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK creates and manages loggroup for the lambda function" + } + } + } } - } + }, + "minimumCliVersion": "2.1025.0" } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/tree.json index c96bc88fb7f51..4e0a956c0ae09 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function-runtime.js.snapshot/tree.json @@ -1,265 +1 @@ -{ - "version": "tree-0.1", - "tree": { - "id": "App", - "path": "", - "children": { - "integ-distribution-function": { - "id": "integ-distribution-function", - "path": "integ-distribution-function", - "children": { - "FunctionRequest": { - "id": "FunctionRequest", - "path": "integ-distribution-function/FunctionRequest", - "children": { - "Resource": { - "id": "Resource", - "path": "integ-distribution-function/FunctionRequest/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CloudFront::Function", - "aws:cdk:cloudformation:props": { - "autoPublish": true, - "functionCode": "function handler(event) { return event.request }", - "functionConfig": { - "comment": "eu-west-1integ-distributinFunctionRequest8E65DEEB", - "runtime": "cloudfront-js-1.0" - }, - "name": "eu-west-1integ-distributinFunctionRequest8E65DEEB" - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_cloudfront.CfnFunction", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_cloudfront.Function", - "version": "0.0.0" - } - }, - "FunctionResponse": { - "id": "FunctionResponse", - "path": "integ-distribution-function/FunctionResponse", - "children": { - "Resource": { - "id": "Resource", - "path": "integ-distribution-function/FunctionResponse/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CloudFront::Function", - "aws:cdk:cloudformation:props": { - "autoPublish": true, - "functionCode": "function handler(event) { return event.response }", - "functionConfig": { - "comment": "eu-west-1integ-distributiFunctionResponseDD4BADA1", - "runtime": "cloudfront-js-2.0" - }, - "name": "eu-west-1integ-distributiFunctionResponseDD4BADA1" - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_cloudfront.CfnFunction", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_cloudfront.Function", - "version": "0.0.0" - } - }, - "Dist": { - "id": "Dist", - "path": "integ-distribution-function/Dist", - "children": { - "Origin1": { - "id": "Origin1", - "path": "integ-distribution-function/Dist/Origin1", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - }, - "Resource": { - "id": "Resource", - "path": "integ-distribution-function/Dist/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CloudFront::Distribution", - "aws:cdk:cloudformation:props": { - "distributionConfig": { - "enabled": true, - "origins": [ - { - "domainName": "www.example.com", - "id": "integdistributionfunctionDistOrigin1D1E9DF17", - "customOriginConfig": { - "originProtocolPolicy": "https-only" - } - } - ], - "defaultCacheBehavior": { - "pathPattern": "*", - "targetOriginId": "integdistributionfunctionDistOrigin1D1E9DF17", - "cachePolicyId": "4135ea2d-6df8-44a3-9df3-4b5a84be39ad", - "compress": true, - "viewerProtocolPolicy": "allow-all", - "functionAssociations": [ - { - "functionArn": { - "Fn::GetAtt": [ - "FunctionRequest95528B2F", - "FunctionARN" - ] - }, - "eventType": "viewer-request" - }, - { - "functionArn": { - "Fn::GetAtt": [ - "FunctionResponse4EF2D1D3", - "FunctionARN" - ] - }, - "eventType": "viewer-response" - } - ] - }, - "httpVersion": "http2", - "ipv6Enabled": true - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_cloudfront.CfnDistribution", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_cloudfront.Distribution", - "version": "0.0.0" - } - }, - "RequestFunctionArn": { - "id": "RequestFunctionArn", - "path": "integ-distribution-function/RequestFunctionArn", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnOutput", - "version": "0.0.0" - } - }, - "RequestFunctionStage": { - "id": "RequestFunctionStage", - "path": "integ-distribution-function/RequestFunctionStage", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnOutput", - "version": "0.0.0" - } - }, - "ResponseFunctionArn": { - "id": "ResponseFunctionArn", - "path": "integ-distribution-function/ResponseFunctionArn", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnOutput", - "version": "0.0.0" - } - }, - "ResponseFunctionStage": { - "id": "ResponseFunctionStage", - "path": "integ-distribution-function/ResponseFunctionStage", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnOutput", - "version": "0.0.0" - } - }, - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "integ-distribution-function/BootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "0.0.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "integ-distribution-function/CheckBootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnRule", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.Stack", - "version": "0.0.0" - } - }, - "CF2Runtime": { - "id": "CF2Runtime", - "path": "CF2Runtime", - "children": { - "DefaultTest": { - "id": "DefaultTest", - "path": "CF2Runtime/DefaultTest", - "children": { - "Default": { - "id": "Default", - "path": "CF2Runtime/DefaultTest/Default", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - }, - "DeployAssert": { - "id": "DeployAssert", - "path": "CF2Runtime/DefaultTest/DeployAssert", - "children": { - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "CF2Runtime/DefaultTest/DeployAssert/BootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "0.0.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "CF2Runtime/DefaultTest/DeployAssert/CheckBootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnRule", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.Stack", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", - "version": "0.0.0" - } - }, - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.App", - "version": "0.0.0" - } - } -} \ No newline at end of file +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"integ-distribution-function":{"id":"integ-distribution-function","path":"integ-distribution-function","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"FunctionRequest":{"id":"FunctionRequest","path":"integ-distribution-function/FunctionRequest","constructInfo":{"fqn":"aws-cdk-lib.aws_cloudfront.Function","version":"0.0.0","metadata":[{"code":"*","runtime":"*"}]},"children":{"Resource":{"id":"Resource","path":"integ-distribution-function/FunctionRequest/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_cloudfront.CfnFunction","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::CloudFront::Function","aws:cdk:cloudformation:props":{"autoPublish":true,"functionCode":"function handler(event) { return event.request }","functionConfig":{"comment":"eu-west-1integ-distributinFunctionRequest8E65DEEB","runtime":"cloudfront-js-1.0"},"name":"eu-west-1integ-distributinFunctionRequest8E65DEEB"}}}}},"FunctionResponse":{"id":"FunctionResponse","path":"integ-distribution-function/FunctionResponse","constructInfo":{"fqn":"aws-cdk-lib.aws_cloudfront.Function","version":"0.0.0","metadata":[{"code":"*","runtime":"*"}]},"children":{"Resource":{"id":"Resource","path":"integ-distribution-function/FunctionResponse/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_cloudfront.CfnFunction","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::CloudFront::Function","aws:cdk:cloudformation:props":{"autoPublish":true,"functionCode":"function handler(event) { return event.response }","functionConfig":{"comment":"eu-west-1integ-distributiFunctionResponseDD4BADA1","runtime":"cloudfront-js-2.0"},"name":"eu-west-1integ-distributiFunctionResponseDD4BADA1"}}}}},"Dist":{"id":"Dist","path":"integ-distribution-function/Dist","constructInfo":{"fqn":"aws-cdk-lib.aws_cloudfront.Distribution","version":"0.0.0","metadata":[{"defaultBehavior":{"origin":"*","cachePolicy":{"cachePolicyId":"*"},"functionAssociations":[{"function":"*","eventType":"viewer-request"},{"function":"*","eventType":"viewer-response"}]}}]},"children":{"Origin1":{"id":"Origin1","path":"integ-distribution-function/Dist/Origin1","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"Resource":{"id":"Resource","path":"integ-distribution-function/Dist/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_cloudfront.CfnDistribution","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::CloudFront::Distribution","aws:cdk:cloudformation:props":{"distributionConfig":{"enabled":true,"origins":[{"domainName":"www.example.com","id":"integdistributionfunctionDistOrigin1D1E9DF17","customOriginConfig":{"originProtocolPolicy":"https-only"}}],"defaultCacheBehavior":{"pathPattern":"*","targetOriginId":"integdistributionfunctionDistOrigin1D1E9DF17","cachePolicyId":"4135ea2d-6df8-44a3-9df3-4b5a84be39ad","compress":true,"viewerProtocolPolicy":"allow-all","functionAssociations":[{"functionArn":{"Ref":"FunctionRequest95528B2F"},"eventType":"viewer-request"},{"functionArn":{"Ref":"FunctionResponse4EF2D1D3"},"eventType":"viewer-response"}]},"httpVersion":"http2","ipv6Enabled":true}}}}}},"RequestFunctionArn":{"id":"RequestFunctionArn","path":"integ-distribution-function/RequestFunctionArn","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"RequestFunctionStage":{"id":"RequestFunctionStage","path":"integ-distribution-function/RequestFunctionStage","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"ResponseFunctionArn":{"id":"ResponseFunctionArn","path":"integ-distribution-function/ResponseFunctionArn","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"ResponseFunctionStage":{"id":"ResponseFunctionStage","path":"integ-distribution-function/ResponseFunctionStage","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"BootstrapVersion":{"id":"BootstrapVersion","path":"integ-distribution-function/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"integ-distribution-function/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"CF2Runtime":{"id":"CF2Runtime","path":"CF2Runtime","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"CF2Runtime/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"CF2Runtime/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"CF2Runtime/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"CF2Runtime/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"CF2Runtime/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/DistributionFunctionDefaultTestDeployAssert9D427BC1.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/DistributionFunctionDefaultTestDeployAssert9D427BC1.assets.json index cc09fc7467d09..33940fe33e118 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/DistributionFunctionDefaultTestDeployAssert9D427BC1.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/DistributionFunctionDefaultTestDeployAssert9D427BC1.assets.json @@ -1,13 +1,14 @@ { - "version": "36.0.0", + "version": "48.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "DistributionFunctionDefaultTestDeployAssert9D427BC1 Template", "source": { "path": "DistributionFunctionDefaultTestDeployAssert9D427BC1.template.json", "packaging": "file" }, "destinations": { - "current_account-current_region": { + "current_account-current_region-d8d86b35": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/cdk.out index 1f0068d32659a..523a9aac37cbf 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"36.0.0"} \ No newline at end of file +{"version":"48.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/integ-distribution-function.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/integ-distribution-function.assets.json index 7a38a75b120a0..10f82ea6bdab5 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/integ-distribution-function.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/integ-distribution-function.assets.json @@ -1,15 +1,16 @@ { - "version": "36.0.0", + "version": "48.0.0", "files": { - "63f7f5881d7bc5ce53462b42e6c05e558d335432add6b977c8d03e31d2129fa3": { + "6bd62c570264de8125de1033fa877af2aae477e1df850f4b95eb21d74392cde4": { + "displayName": "integ-distribution-function Template", "source": { "path": "integ-distribution-function.template.json", "packaging": "file" }, "destinations": { - "current_account-eu-west-1": { + "current_account-eu-west-1-086938f6": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-eu-west-1", - "objectKey": "63f7f5881d7bc5ce53462b42e6c05e558d335432add6b977c8d03e31d2129fa3.json", + "objectKey": "6bd62c570264de8125de1033fa877af2aae477e1df850f4b95eb21d74392cde4.json", "region": "eu-west-1", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-eu-west-1" } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/integ-distribution-function.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/integ-distribution-function.template.json index a0f2c3d71b793..68ad544c3b92f 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/integ-distribution-function.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/integ-distribution-function.template.json @@ -23,10 +23,7 @@ { "EventType": "viewer-request", "FunctionARN": { - "Fn::GetAtt": [ - "Function76856677", - "FunctionARN" - ] + "Ref": "Function76856677" } } ], diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/integ.json index 6fd5eae8f7765..11e14b33e2606 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "36.0.0", + "version": "48.0.0", "testCases": { "DistributionFunction/DefaultTest": { "stacks": [ @@ -8,5 +8,6 @@ "assertionStack": "DistributionFunction/DefaultTest/DeployAssert", "assertionStackName": "DistributionFunctionDefaultTestDeployAssert9D427BC1" } - } + }, + "minimumCliVersion": "2.1024.0" } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/manifest.json index 93dabc383879f..282e8adaca11c 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "36.0.0", + "version": "48.0.0", "artifacts": { "integ-distribution-function.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}-eu-west-1", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-eu-west-1", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-eu-west-1/63f7f5881d7bc5ce53462b42e6c05e558d335432add6b977c8d03e31d2129fa3.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-eu-west-1/6bd62c570264de8125de1033fa877af2aae477e1df850f4b95eb21d74392cde4.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -34,12 +34,39 @@ "integ-distribution-function.assets" ], "metadata": { + "/integ-distribution-function/Function": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "code": "*" + } + } + ], "/integ-distribution-function/Function/Resource": [ { "type": "aws:cdk:logicalId", "data": "Function76856677" } ], + "/integ-distribution-function/Dist": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "defaultBehavior": { + "origin": "*", + "cachePolicy": { + "cachePolicyId": "*" + }, + "functionAssociations": [ + { + "function": "*", + "eventType": "viewer-request" + } + ] + } + } + } + ], "/integ-distribution-function/Dist/Resource": [ { "type": "aws:cdk:logicalId", @@ -126,6 +153,481 @@ "properties": { "file": "tree.json" } + }, + "aws-cdk-lib/feature-flag-report": { + "type": "cdk:feature-flag-report", + "properties": { + "module": "aws-cdk-lib", + "flags": { + "@aws-cdk/aws-signer:signingProfileNamePassedToCfn": { + "recommendedValue": true, + "explanation": "Pass signingProfileName to CfnSigningProfile" + }, + "@aws-cdk/core:newStyleStackSynthesis": { + "recommendedValue": true, + "explanation": "Switch to new stack synthesis method which enables CI/CD", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:stackRelativeExports": { + "recommendedValue": true, + "explanation": "Name exports based on the construct paths relative to the stack, rather than the global construct path", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-rds:lowercaseDbIdentifier": { + "recommendedValue": true, + "explanation": "Force lowercasing of RDS Cluster names in CDK", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": { + "recommendedValue": true, + "explanation": "Allow adding/removing multiple UsagePlanKeys independently", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeVersionProps": { + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeLayerVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`." + }, + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": { + "recommendedValue": true, + "explanation": "Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:checkSecretUsage": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this flag to make it impossible to accidentally use SecretValues in unsafe locations" + }, + "@aws-cdk/core:target-partitions": { + "recommendedValue": [ + "aws", + "aws-cn" + ], + "explanation": "What regions to include in lookup tables of environment agnostic stacks" + }, + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": { + "userValue": true, + "recommendedValue": true, + "explanation": "ECS extensions will automatically add an `awslogs` driver if no logging is specified" + }, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names." + }, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": { + "userValue": true, + "recommendedValue": true, + "explanation": "ARN format used by ECS. In the new ARN format, the cluster name is part of the resource ID." + }, + "@aws-cdk/aws-iam:minimizePolicies": { + "userValue": true, + "recommendedValue": true, + "explanation": "Minimize IAM policies by combining Statements" + }, + "@aws-cdk/core:validateSnapshotRemovalPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Error on snapshot removal policies on resources that do not support it." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate key aliases that include the stack name" + }, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to create an S3 bucket policy by default in cases where an AWS service would automatically create the Policy if one does not exist." + }, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict KMS key policy for encrypted Queues a bit more" + }, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make default CloudWatch Role behavior safe for multiple API Gateways in one environment" + }, + "@aws-cdk/core:enablePartitionLiterals": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make ARNs concrete if AWS partition is known" + }, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": { + "userValue": true, + "recommendedValue": true, + "explanation": "Event Rules may only push to encrypted SQS queues in the same account" + }, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": { + "userValue": true, + "recommendedValue": true, + "explanation": "Avoid setting the \"ECS\" deployment controller when adding a circuit breaker" + }, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature to by default create default policy names for imported roles that depend on the stack the role is in." + }, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use S3 Bucket Policy instead of ACLs for Server Access Logging" + }, + "@aws-cdk/aws-route53-patters:useCertificate": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use the official `Certificate` resource instead of `DnsValidatedCertificate`" + }, + "@aws-cdk/customresources:installLatestAwsSdkDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "Whether to install the latest SDK by default in AwsCustomResource" + }, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use unique resource name for Database Proxy" + }, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Remove CloudWatch alarms from deployment group" + }, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include authorizer configuration in the calculation of the API deployment logical ID." + }, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": { + "userValue": true, + "recommendedValue": true, + "explanation": "Define user data for a launch template by default when a machine image is provided." + }, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": { + "userValue": true, + "recommendedValue": true, + "explanation": "SecretTargetAttachments uses the ResourcePolicy of the attached Secret." + }, + "@aws-cdk/aws-redshift:columnId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Whether to use an ID to track Redshift column changes" + }, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable AmazonEMRServicePolicy_v2 managed policies" + }, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict access to the VPC default security group" + }, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a unique id for each RequestValidator added to a method" + }, + "@aws-cdk/aws-kms:aliasNameRef": { + "userValue": true, + "recommendedValue": true, + "explanation": "KMS Alias name and keyArn will have implicit reference to KMS Key" + }, + "@aws-cdk/aws-kms:applyImportedAliasPermissionsToPrincipal": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable grant methods on Aliases imported by name to use kms:ResourceAliases condition" + }, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a launch template when creating an AutoScalingGroup" + }, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include the stack prefix in the stack name generation process" + }, + "@aws-cdk/aws-efs:denyAnonymousAccess": { + "userValue": true, + "recommendedValue": true, + "explanation": "EFS denies anonymous clients accesses" + }, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables support for Multi-AZ with Standby deployment for opensearch domains" + }, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables aws-lambda-nodejs.Function to use the latest available NodeJs runtime as the default" + }, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, mount targets will have a stable logicalId that is linked to the associated subnet." + }, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a scope of InstanceParameterGroup for AuroraClusterInstance with each parameters will change." + }, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, will always use the arn for identifiers for CfnSourceApiAssociation in the GraphqlApi construct rather than id." + }, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, creating an RDS database cluster from a snapshot will only render credentials for snapshot credentials." + }, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the CodeCommit source action is using the default branch name 'main'." + }, + "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the logical ID of a Lambda permission for a Lambda action includes an alarm ID." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default value for crossAccountKeys to false." + }, + "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default pipeline type to V2." + }, + "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, IAM Policy created from KMS key grant will reduce the resource scope to this key only." + }, + "@aws-cdk/pipelines:reduceAssetRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from PipelineAssetsFileRole trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-eks:nodegroupNameAttribute": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, nodegroupName attribute of the provisioned EKS NodeGroup will not have the cluster name prefix." + }, + "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default volume type of the EBS volume will be GP3" + }, + "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, remove default deployment alarm settings" + }, + "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, the custom resource used for `AwsCustomResource` will configure the `logApiResponseData` property as true by default" + }, + "@aws-cdk/aws-s3:keepNotificationInImportedBucket": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, Adding notifications to a bucket in the current stack will not remove notification from imported stack." + }, + "@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask": { + "recommendedValue": true, + "explanation": "When enabled, use new props for S3 URI field in task definition of state machine for bedrock invoke model.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:explicitStackTags": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, stack tags need to be assigned explicitly on a Stack." + }, + "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": { + "userValue": false, + "recommendedValue": false, + "explanation": "When set to true along with canContainersAccessInstanceRole=false in ECS cluster, new updated commands will be added to UserData to block container accessing IMDS. **Applicable to Linux only. IMPORTANT: See [details.](#aws-cdkaws-ecsenableImdsBlockingDeprecatedFeature)**" + }, + "@aws-cdk/aws-ecs:disableEcsImdsBlocking": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, CDK synth will throw exception if canContainersAccessInstanceRole is false. **IMPORTANT: See [details.](#aws-cdkaws-ecsdisableEcsImdsBlocking)**" + }, + "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, we will only grant the necessary permissions when users specify cloudwatch log group through logConfiguration" + }, + "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled will allow you to specify a resource policy per replica, and not copy the source table policy to all replicas" + }, + "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, initOptions.timeout and resourceSignalTimeout values will be summed together." + }, + "@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a Lambda authorizer Permission created when using GraphqlApi will be properly scoped with a SourceArn." + }, + "@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the value of property `instanceResourceId` in construct `DatabaseInstanceReadReplica` will be set to the correct value which is `DbiResourceId` instead of currently `DbInstanceArn`" + }, + "@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CFN templates added with `cfn-include` will error if the template contains Resource Update or Create policies with CFN Intrinsics that include non-primitive values." + }, + "@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, both `@aws-sdk` and `@smithy` packages will be excluded from the Lambda Node.js 18.x runtime to prevent version mismatches in bundled applications." + }, + "@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resource of IAM Run Ecs policy generated by SFN EcsRunTask will reference the definition, instead of constructing ARN." + }, + "@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the BastionHost construct will use the latest Amazon Linux 2023 AMI, instead of Amazon Linux 2." + }, + "@aws-cdk/core:aspectStabilization": { + "recommendedValue": true, + "explanation": "When enabled, a stabilization loop will be run when invoking Aspects during synthesis.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, use a new method for DNS Name of user pool domain target without creating a custom resource." + }, + "@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default security group ingress rules will allow IPv6 ingress from anywhere" + }, + "@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default behaviour of OIDC provider will reject unauthorized connections" + }, + "@aws-cdk/core:enableAdditionalMetadataCollection": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will expand the scope of usage data collected to better inform CDK development and improve communication for security concerns and emerging issues." + }, + "@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": { + "userValue": false, + "recommendedValue": false, + "explanation": "[Deprecated] When enabled, Lambda will create new inline policies with AddToRolePolicy instead of adding to the Default Policy Statement" + }, + "@aws-cdk/aws-s3:setUniqueReplicationRoleName": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will automatically generate a unique role name that is used for s3 object replication." + }, + "@aws-cdk/pipelines:reduceStageRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from Stage addActions trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-events:requireEventBusPolicySid": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, grantPutEventsTo() will use resource policies with Statement IDs for service principals." + }, + "@aws-cdk/core:aspectPrioritiesMutating": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, Aspects added by the construct library on your behalf will be given a priority of MUTATING." + }, + "@aws-cdk/aws-dynamodb:retainTableReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, table replica will be default to the removal policy of source table unless specified otherwise." + }, + "@aws-cdk/cognito:logUserPoolClientSecretValue": { + "recommendedValue": false, + "explanation": "When disabled, the value of the user pool client secret will not be logged in the custom resource lambda function logs." + }, + "@aws-cdk/pipelines:reduceCrossAccountActionRoleTrustScope": { + "recommendedValue": true, + "explanation": "When enabled, scopes down the trust policy for the cross-account action role", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resultWriterV2 property of DistributedMap will be used insted of resultWriter" + }, + "@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions": { + "userValue": true, + "recommendedValue": true, + "explanation": "Add an S3 trust policy to a KMS key resource policy for SNS subscriptions." + }, + "@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the EgressOnlyGateway resource is only created if private subnets are defined in the dual-stack VPC." + }, + "@aws-cdk/aws-ec2-alpha:useResourceIdForVpcV2Migration": { + "recommendedValue": false, + "explanation": "When enabled, use resource IDs for VPC V2 migration" + }, + "@aws-cdk/aws-s3:publicAccessBlockedByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, setting any combination of options for BlockPublicAccess will automatically set true for any options not defined." + }, + "@aws-cdk/aws-lambda:useCdkManagedLogGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK creates and manages loggroup for the lambda function" + } + } + } } - } + }, + "minimumCliVersion": "2.1025.0" } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/tree.json index 33a20a46337cf..6a2d8646f77a4 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.distribution-function.js.snapshot/tree.json @@ -1,210 +1 @@ -{ - "version": "tree-0.1", - "tree": { - "id": "App", - "path": "", - "children": { - "integ-distribution-function": { - "id": "integ-distribution-function", - "path": "integ-distribution-function", - "children": { - "Function": { - "id": "Function", - "path": "integ-distribution-function/Function", - "children": { - "Resource": { - "id": "Resource", - "path": "integ-distribution-function/Function/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CloudFront::Function", - "aws:cdk:cloudformation:props": { - "autoPublish": true, - "functionCode": "function handler(event) { return event.request }", - "functionConfig": { - "comment": "eu-west-1integdistributionfunctionFunctionDCD62A02", - "runtime": "cloudfront-js-1.0" - }, - "name": "eu-west-1integdistributionfunctionFunctionDCD62A02" - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_cloudfront.CfnFunction", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_cloudfront.Function", - "version": "0.0.0" - } - }, - "Dist": { - "id": "Dist", - "path": "integ-distribution-function/Dist", - "children": { - "Origin1": { - "id": "Origin1", - "path": "integ-distribution-function/Dist/Origin1", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - }, - "Resource": { - "id": "Resource", - "path": "integ-distribution-function/Dist/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CloudFront::Distribution", - "aws:cdk:cloudformation:props": { - "distributionConfig": { - "enabled": true, - "origins": [ - { - "domainName": "www.example.com", - "id": "integdistributionfunctionDistOrigin1D1E9DF17", - "customOriginConfig": { - "originProtocolPolicy": "https-only" - } - } - ], - "defaultCacheBehavior": { - "pathPattern": "*", - "targetOriginId": "integdistributionfunctionDistOrigin1D1E9DF17", - "cachePolicyId": "4135ea2d-6df8-44a3-9df3-4b5a84be39ad", - "compress": true, - "viewerProtocolPolicy": "allow-all", - "functionAssociations": [ - { - "functionArn": { - "Fn::GetAtt": [ - "Function76856677", - "FunctionARN" - ] - }, - "eventType": "viewer-request" - } - ] - }, - "httpVersion": "http2", - "ipv6Enabled": true - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_cloudfront.CfnDistribution", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_cloudfront.Distribution", - "version": "0.0.0" - } - }, - "FunctionArn": { - "id": "FunctionArn", - "path": "integ-distribution-function/FunctionArn", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnOutput", - "version": "0.0.0" - } - }, - "FunctionStage": { - "id": "FunctionStage", - "path": "integ-distribution-function/FunctionStage", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnOutput", - "version": "0.0.0" - } - }, - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "integ-distribution-function/BootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "0.0.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "integ-distribution-function/CheckBootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnRule", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.Stack", - "version": "0.0.0" - } - }, - "DistributionFunction": { - "id": "DistributionFunction", - "path": "DistributionFunction", - "children": { - "DefaultTest": { - "id": "DefaultTest", - "path": "DistributionFunction/DefaultTest", - "children": { - "Default": { - "id": "Default", - "path": "DistributionFunction/DefaultTest/Default", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - }, - "DeployAssert": { - "id": "DeployAssert", - "path": "DistributionFunction/DefaultTest/DeployAssert", - "children": { - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "DistributionFunction/DefaultTest/DeployAssert/BootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "0.0.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "DistributionFunction/DefaultTest/DeployAssert/CheckBootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnRule", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.Stack", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", - "version": "0.0.0" - } - }, - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.App", - "version": "0.0.0" - } - } -} \ No newline at end of file +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"integ-distribution-function":{"id":"integ-distribution-function","path":"integ-distribution-function","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"Function":{"id":"Function","path":"integ-distribution-function/Function","constructInfo":{"fqn":"aws-cdk-lib.aws_cloudfront.Function","version":"0.0.0","metadata":[{"code":"*"}]},"children":{"Resource":{"id":"Resource","path":"integ-distribution-function/Function/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_cloudfront.CfnFunction","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::CloudFront::Function","aws:cdk:cloudformation:props":{"autoPublish":true,"functionCode":"function handler(event) { return event.request }","functionConfig":{"comment":"eu-west-1integdistributionfunctionFunctionDCD62A02","runtime":"cloudfront-js-1.0"},"name":"eu-west-1integdistributionfunctionFunctionDCD62A02"}}}}},"Dist":{"id":"Dist","path":"integ-distribution-function/Dist","constructInfo":{"fqn":"aws-cdk-lib.aws_cloudfront.Distribution","version":"0.0.0","metadata":[{"defaultBehavior":{"origin":"*","cachePolicy":{"cachePolicyId":"*"},"functionAssociations":[{"function":"*","eventType":"viewer-request"}]}}]},"children":{"Origin1":{"id":"Origin1","path":"integ-distribution-function/Dist/Origin1","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"Resource":{"id":"Resource","path":"integ-distribution-function/Dist/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_cloudfront.CfnDistribution","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::CloudFront::Distribution","aws:cdk:cloudformation:props":{"distributionConfig":{"enabled":true,"origins":[{"domainName":"www.example.com","id":"integdistributionfunctionDistOrigin1D1E9DF17","customOriginConfig":{"originProtocolPolicy":"https-only"}}],"defaultCacheBehavior":{"pathPattern":"*","targetOriginId":"integdistributionfunctionDistOrigin1D1E9DF17","cachePolicyId":"4135ea2d-6df8-44a3-9df3-4b5a84be39ad","compress":true,"viewerProtocolPolicy":"allow-all","functionAssociations":[{"functionArn":{"Ref":"Function76856677"},"eventType":"viewer-request"}]},"httpVersion":"http2","ipv6Enabled":true}}}}}},"FunctionArn":{"id":"FunctionArn","path":"integ-distribution-function/FunctionArn","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"FunctionStage":{"id":"FunctionStage","path":"integ-distribution-function/FunctionStage","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"BootstrapVersion":{"id":"BootstrapVersion","path":"integ-distribution-function/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"integ-distribution-function/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"DistributionFunction":{"id":"DistributionFunction","path":"DistributionFunction","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"DistributionFunction/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"DistributionFunction/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"DistributionFunction/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"DistributionFunction/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"DistributionFunction/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.assets.json index 2ecc1dbe4c465..04b7be0961941 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.assets.json @@ -1,15 +1,16 @@ { - "version": "38.0.1", + "version": "48.0.0", "files": { - "88280b03c5b1be25a757aec1dc08c8df2c722de34a69963dfde75905ceaae61e": { + "6ebf91e65fc00e28320feeed599537ee23102f8329f67fc837211d771738390f": { + "displayName": "aws-cdk-rds-integ-with-feature-flag Template", "source": { "path": "aws-cdk-rds-integ-with-feature-flag.template.json", "packaging": "file" }, "destinations": { - "current_account-current_region": { + "current_account-current_region-0167c2e4": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "88280b03c5b1be25a757aec1dc08c8df2c722de34a69963dfde75905ceaae61e.json", + "objectKey": "6ebf91e65fc00e28320feeed599537ee23102f8329f67fc837211d771738390f.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.template.json index 6aa2bda2f1bef..59d1e79641b13 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.template.json @@ -503,6 +503,7 @@ "DBSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, + "DeleteAutomatedBackups": false, "Engine": "aurora-mysql", "EngineVersion": "8.0.mysql_aurora.3.07.1", "KmsKeyId": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.assets.json index e4813a656fbd4..7fd08c6c424df 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.assets.json @@ -1,15 +1,16 @@ { - "version": "38.0.1", + "version": "48.0.0", "files": { - "c5c41991477732fc96052ff5ee9b37386fd014657c4e5c15836e6075551961b5": { + "4f0094c1c92187789079c6a4dc0359e266a9713b13e88b8936fa9637ef26b3e7": { + "displayName": "aws-cdk-rds-integ Template", "source": { "path": "aws-cdk-rds-integ.template.json", "packaging": "file" }, "destinations": { - "current_account-current_region": { + "current_account-current_region-48d241e9": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "c5c41991477732fc96052ff5ee9b37386fd014657c4e5c15836e6075551961b5.json", + "objectKey": "4f0094c1c92187789079c6a4dc0359e266a9713b13e88b8936fa9637ef26b3e7.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.template.json index 8e864fd4fc053..c93ed44ece8bd 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.template.json @@ -503,6 +503,7 @@ "DBSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, + "DeleteAutomatedBackups": false, "Engine": "aurora-mysql", "EngineVersion": "8.0.mysql_aurora.3.07.1", "KmsKeyId": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/cdk.out index c6e612584e352..523a9aac37cbf 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"38.0.1"} \ No newline at end of file +{"version":"48.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/integ.json index a4563c58af824..10d0ca6d586a4 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "38.0.1", + "version": "48.0.0", "testCases": { "test-rds-cluster-with-feature-flag/DefaultTest": { "stacks": [ @@ -8,5 +8,6 @@ "assertionStack": "test-rds-cluster-with-feature-flag/DefaultTest/DeployAssert", "assertionStackName": "testrdsclusterwithfeatureflagDefaultTestDeployAssert8E2E540B" } - } + }, + "minimumCliVersion": "2.1027.0" } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/manifest.json index 7a2508d7dbe9f..fd012997af498 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "38.0.1", + "version": "48.0.0", "artifacts": { "aws-cdk-rds-integ-with-feature-flag.assets": { "type": "cdk:asset-manifest", @@ -16,10 +16,9 @@ "templateFile": "aws-cdk-rds-integ-with-feature-flag.template.json", "terminationProtection": false, "validateOnSynth": false, - "notificationArns": [], "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}/88280b03c5b1be25a757aec1dc08c8df2c722de34a69963dfde75905ceaae61e.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/6ebf91e65fc00e28320feeed599537ee23102f8329f67fc837211d771738390f.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -35,12 +34,36 @@ "aws-cdk-rds-integ-with-feature-flag.assets" ], "metadata": { + "/aws-cdk-rds-integ-with-feature-flag/VPC": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], "/aws-cdk-rds-integ-with-feature-flag/VPC/Resource": [ { "type": "aws:cdk:logicalId", "data": "VPCB9E5F0B4" } ], + "/aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + } + ], "/aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/Subnet": [ { "type": "aws:cdk:logicalId", @@ -77,6 +100,24 @@ "data": "VPCPublicSubnet1NATGatewayE0556630" } ], + "/aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + } + ], "/aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/Subnet": [ { "type": "aws:cdk:logicalId", @@ -113,6 +154,20 @@ "data": "VPCPublicSubnet2NATGateway3C070193" } ], + "/aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + } + ], "/aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1/Subnet": [ { "type": "aws:cdk:logicalId", @@ -137,6 +192,20 @@ "data": "VPCPrivateSubnet1DefaultRouteAE1D6490" } ], + "/aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + } + ], "/aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2/Subnet": [ { "type": "aws:cdk:logicalId", @@ -173,24 +242,62 @@ "data": "VPCVPCGW99B986DC" } ], + "/aws-cdk-rds-integ-with-feature-flag/Params": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + } + ], "/aws-cdk-rds-integ-with-feature-flag/Params/Resource": [ { "type": "aws:cdk:logicalId", "data": "ParamsA8366201" } ], + "/aws-cdk-rds-integ-with-feature-flag/DbSecurity": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], "/aws-cdk-rds-integ-with-feature-flag/DbSecurity/Resource": [ { "type": "aws:cdk:logicalId", "data": "DbSecurity381C2C15" } ], + "/aws-cdk-rds-integ-with-feature-flag/Database": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], + "/aws-cdk-rds-integ-with-feature-flag/Database/Subnets": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], "/aws-cdk-rds-integ-with-feature-flag/Database/Subnets/Default": [ { "type": "aws:cdk:logicalId", "data": "DatabaseSubnets56F17B9A" } ], + "/aws-cdk-rds-integ-with-feature-flag/Database/SecurityGroup": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + } + ], "/aws-cdk-rds-integ-with-feature-flag/Database/SecurityGroup/Resource": [ { "type": "aws:cdk:logicalId", @@ -209,12 +316,34 @@ "data": "DatabaseB269D8BB" } ], + "/aws-cdk-rds-integ-with-feature-flag/Database/Instance1Wrapper": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], "/aws-cdk-rds-integ-with-feature-flag/Database/Instance1": [ { "type": "aws:cdk:logicalId", "data": "DatabaseInstance1844F58FD" } ], + "/aws-cdk-rds-integ-with-feature-flag/Database/Instance2Wrapper": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], + "/aws-cdk-rds-integ-with-feature-flag/Database/Instance2Wrapper/InstanceParameterGroup": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + } + ], "/aws-cdk-rds-integ-with-feature-flag/Database/Instance2Wrapper/InstanceParameterGroup/Resource": [ { "type": "aws:cdk:logicalId", @@ -227,6 +356,22 @@ "data": "DatabaseInstance2AA380DEE" } ], + "/aws-cdk-rds-integ-with-feature-flag/Database/Instance3Wrapper": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], + "/aws-cdk-rds-integ-with-feature-flag/Database/Instance3Wrapper/InstanceParameterGroup": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + } + ], "/aws-cdk-rds-integ-with-feature-flag/Database/Instance3Wrapper/InstanceParameterGroup/Resource": [ { "type": "aws:cdk:logicalId", @@ -239,12 +384,58 @@ "data": "DatabaseInstance32FCBA185" } ], + "/aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + } + ], + "/aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess/ImportClusterIamAccess": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], "/aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess/Resource": [ { "type": "aws:cdk:logicalId", "data": "ClusterIamAccess93AC3DF3" } ], + "/aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess/DefaultPolicy": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": "*" + } + ], "/aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess/DefaultPolicy/Resource": [ { "type": "aws:cdk:logicalId", @@ -281,7 +472,6 @@ "templateFile": "testrdsclusterwithfeatureflagDefaultTestDeployAssert8E2E540B.template.json", "terminationProtection": false, "validateOnSynth": false, - "notificationArns": [], "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}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", @@ -320,6 +510,485 @@ "properties": { "file": "tree.json" } + }, + "aws-cdk-lib/feature-flag-report": { + "type": "cdk:feature-flag-report", + "properties": { + "module": "aws-cdk-lib", + "flags": { + "@aws-cdk/aws-signer:signingProfileNamePassedToCfn": { + "recommendedValue": true, + "explanation": "Pass signingProfileName to CfnSigningProfile" + }, + "@aws-cdk/core:newStyleStackSynthesis": { + "recommendedValue": true, + "explanation": "Switch to new stack synthesis method which enables CI/CD", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:stackRelativeExports": { + "recommendedValue": true, + "explanation": "Name exports based on the construct paths relative to the stack, rather than the global construct path", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-ecs-patterns:secGroupsDisablesImplicitOpenListener": { + "recommendedValue": true, + "explanation": "Disable implicit openListener when custom security groups are provided" + }, + "@aws-cdk/aws-rds:lowercaseDbIdentifier": { + "recommendedValue": true, + "explanation": "Force lowercasing of RDS Cluster names in CDK", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": { + "recommendedValue": true, + "explanation": "Allow adding/removing multiple UsagePlanKeys independently", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeVersionProps": { + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeLayerVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`." + }, + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": { + "recommendedValue": true, + "explanation": "Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:checkSecretUsage": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this flag to make it impossible to accidentally use SecretValues in unsafe locations" + }, + "@aws-cdk/core:target-partitions": { + "recommendedValue": [ + "aws", + "aws-cn" + ], + "explanation": "What regions to include in lookup tables of environment agnostic stacks" + }, + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": { + "userValue": true, + "recommendedValue": true, + "explanation": "ECS extensions will automatically add an `awslogs` driver if no logging is specified" + }, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names." + }, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": { + "userValue": true, + "recommendedValue": true, + "explanation": "ARN format used by ECS. In the new ARN format, the cluster name is part of the resource ID." + }, + "@aws-cdk/aws-iam:minimizePolicies": { + "userValue": true, + "recommendedValue": true, + "explanation": "Minimize IAM policies by combining Statements" + }, + "@aws-cdk/core:validateSnapshotRemovalPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Error on snapshot removal policies on resources that do not support it." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate key aliases that include the stack name" + }, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to create an S3 bucket policy by default in cases where an AWS service would automatically create the Policy if one does not exist." + }, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict KMS key policy for encrypted Queues a bit more" + }, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make default CloudWatch Role behavior safe for multiple API Gateways in one environment" + }, + "@aws-cdk/core:enablePartitionLiterals": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make ARNs concrete if AWS partition is known" + }, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": { + "userValue": true, + "recommendedValue": true, + "explanation": "Event Rules may only push to encrypted SQS queues in the same account" + }, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": { + "userValue": true, + "recommendedValue": true, + "explanation": "Avoid setting the \"ECS\" deployment controller when adding a circuit breaker" + }, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature to by default create default policy names for imported roles that depend on the stack the role is in." + }, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use S3 Bucket Policy instead of ACLs for Server Access Logging" + }, + "@aws-cdk/aws-route53-patters:useCertificate": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use the official `Certificate` resource instead of `DnsValidatedCertificate`" + }, + "@aws-cdk/customresources:installLatestAwsSdkDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "Whether to install the latest SDK by default in AwsCustomResource" + }, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use unique resource name for Database Proxy" + }, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Remove CloudWatch alarms from deployment group" + }, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include authorizer configuration in the calculation of the API deployment logical ID." + }, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": { + "userValue": true, + "recommendedValue": true, + "explanation": "Define user data for a launch template by default when a machine image is provided." + }, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": { + "userValue": true, + "recommendedValue": true, + "explanation": "SecretTargetAttachments uses the ResourcePolicy of the attached Secret." + }, + "@aws-cdk/aws-redshift:columnId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Whether to use an ID to track Redshift column changes" + }, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable AmazonEMRServicePolicy_v2 managed policies" + }, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict access to the VPC default security group" + }, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a unique id for each RequestValidator added to a method" + }, + "@aws-cdk/aws-kms:aliasNameRef": { + "userValue": true, + "recommendedValue": true, + "explanation": "KMS Alias name and keyArn will have implicit reference to KMS Key" + }, + "@aws-cdk/aws-kms:applyImportedAliasPermissionsToPrincipal": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable grant methods on Aliases imported by name to use kms:ResourceAliases condition" + }, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a launch template when creating an AutoScalingGroup" + }, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include the stack prefix in the stack name generation process" + }, + "@aws-cdk/aws-efs:denyAnonymousAccess": { + "userValue": true, + "recommendedValue": true, + "explanation": "EFS denies anonymous clients accesses" + }, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables support for Multi-AZ with Standby deployment for opensearch domains" + }, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables aws-lambda-nodejs.Function to use the latest available NodeJs runtime as the default" + }, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, mount targets will have a stable logicalId that is linked to the associated subnet." + }, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a scope of InstanceParameterGroup for AuroraClusterInstance with each parameters will change." + }, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, will always use the arn for identifiers for CfnSourceApiAssociation in the GraphqlApi construct rather than id." + }, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, creating an RDS database cluster from a snapshot will only render credentials for snapshot credentials." + }, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the CodeCommit source action is using the default branch name 'main'." + }, + "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the logical ID of a Lambda permission for a Lambda action includes an alarm ID." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default value for crossAccountKeys to false." + }, + "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default pipeline type to V2." + }, + "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, IAM Policy created from KMS key grant will reduce the resource scope to this key only." + }, + "@aws-cdk/pipelines:reduceAssetRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from PipelineAssetsFileRole trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-eks:nodegroupNameAttribute": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, nodegroupName attribute of the provisioned EKS NodeGroup will not have the cluster name prefix." + }, + "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default volume type of the EBS volume will be GP3" + }, + "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, remove default deployment alarm settings" + }, + "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, the custom resource used for `AwsCustomResource` will configure the `logApiResponseData` property as true by default" + }, + "@aws-cdk/aws-s3:keepNotificationInImportedBucket": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, Adding notifications to a bucket in the current stack will not remove notification from imported stack." + }, + "@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask": { + "recommendedValue": true, + "explanation": "When enabled, use new props for S3 URI field in task definition of state machine for bedrock invoke model.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:explicitStackTags": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, stack tags need to be assigned explicitly on a Stack." + }, + "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": { + "userValue": false, + "recommendedValue": false, + "explanation": "When set to true along with canContainersAccessInstanceRole=false in ECS cluster, new updated commands will be added to UserData to block container accessing IMDS. **Applicable to Linux only. IMPORTANT: See [details.](#aws-cdkaws-ecsenableImdsBlockingDeprecatedFeature)**" + }, + "@aws-cdk/aws-ecs:disableEcsImdsBlocking": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, CDK synth will throw exception if canContainersAccessInstanceRole is false. **IMPORTANT: See [details.](#aws-cdkaws-ecsdisableEcsImdsBlocking)**" + }, + "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, we will only grant the necessary permissions when users specify cloudwatch log group through logConfiguration" + }, + "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled will allow you to specify a resource policy per replica, and not copy the source table policy to all replicas" + }, + "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, initOptions.timeout and resourceSignalTimeout values will be summed together." + }, + "@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a Lambda authorizer Permission created when using GraphqlApi will be properly scoped with a SourceArn." + }, + "@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the value of property `instanceResourceId` in construct `DatabaseInstanceReadReplica` will be set to the correct value which is `DbiResourceId` instead of currently `DbInstanceArn`" + }, + "@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CFN templates added with `cfn-include` will error if the template contains Resource Update or Create policies with CFN Intrinsics that include non-primitive values." + }, + "@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, both `@aws-sdk` and `@smithy` packages will be excluded from the Lambda Node.js 18.x runtime to prevent version mismatches in bundled applications." + }, + "@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resource of IAM Run Ecs policy generated by SFN EcsRunTask will reference the definition, instead of constructing ARN." + }, + "@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the BastionHost construct will use the latest Amazon Linux 2023 AMI, instead of Amazon Linux 2." + }, + "@aws-cdk/core:aspectStabilization": { + "recommendedValue": true, + "explanation": "When enabled, a stabilization loop will be run when invoking Aspects during synthesis.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, use a new method for DNS Name of user pool domain target without creating a custom resource." + }, + "@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default security group ingress rules will allow IPv6 ingress from anywhere" + }, + "@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default behaviour of OIDC provider will reject unauthorized connections" + }, + "@aws-cdk/core:enableAdditionalMetadataCollection": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will expand the scope of usage data collected to better inform CDK development and improve communication for security concerns and emerging issues." + }, + "@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": { + "userValue": false, + "recommendedValue": false, + "explanation": "[Deprecated] When enabled, Lambda will create new inline policies with AddToRolePolicy instead of adding to the Default Policy Statement" + }, + "@aws-cdk/aws-s3:setUniqueReplicationRoleName": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will automatically generate a unique role name that is used for s3 object replication." + }, + "@aws-cdk/pipelines:reduceStageRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from Stage addActions trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-events:requireEventBusPolicySid": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, grantPutEventsTo() will use resource policies with Statement IDs for service principals." + }, + "@aws-cdk/core:aspectPrioritiesMutating": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, Aspects added by the construct library on your behalf will be given a priority of MUTATING." + }, + "@aws-cdk/aws-dynamodb:retainTableReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, table replica will be default to the removal policy of source table unless specified otherwise." + }, + "@aws-cdk/cognito:logUserPoolClientSecretValue": { + "recommendedValue": false, + "explanation": "When disabled, the value of the user pool client secret will not be logged in the custom resource lambda function logs." + }, + "@aws-cdk/pipelines:reduceCrossAccountActionRoleTrustScope": { + "recommendedValue": true, + "explanation": "When enabled, scopes down the trust policy for the cross-account action role", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resultWriterV2 property of DistributedMap will be used insted of resultWriter" + }, + "@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions": { + "userValue": true, + "recommendedValue": true, + "explanation": "Add an S3 trust policy to a KMS key resource policy for SNS subscriptions." + }, + "@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the EgressOnlyGateway resource is only created if private subnets are defined in the dual-stack VPC." + }, + "@aws-cdk/aws-ec2-alpha:useResourceIdForVpcV2Migration": { + "recommendedValue": false, + "explanation": "When enabled, use resource IDs for VPC V2 migration" + }, + "@aws-cdk/aws-s3:publicAccessBlockedByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, setting any combination of options for BlockPublicAccess will automatically set true for any options not defined." + }, + "@aws-cdk/aws-lambda:useCdkManagedLogGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK creates and manages loggroup for the lambda function" + } + } + } } - } + }, + "minimumCliVersion": "2.1027.0" } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterDefaultTestDeployAssert23E53F17.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterDefaultTestDeployAssert23E53F17.assets.json index 4418321ac7c58..9cfc5d2aec649 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterDefaultTestDeployAssert23E53F17.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterDefaultTestDeployAssert23E53F17.assets.json @@ -1,13 +1,14 @@ { - "version": "38.0.1", + "version": "48.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "testrdsclusterDefaultTestDeployAssert23E53F17 Template", "source": { "path": "testrdsclusterDefaultTestDeployAssert23E53F17.template.json", "packaging": "file" }, "destinations": { - "current_account-current_region": { + "current_account-current_region-d8d86b35": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterwithfeatureflagDefaultTestDeployAssert8E2E540B.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterwithfeatureflagDefaultTestDeployAssert8E2E540B.assets.json index 0509595126662..21233608c3612 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterwithfeatureflagDefaultTestDeployAssert8E2E540B.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterwithfeatureflagDefaultTestDeployAssert8E2E540B.assets.json @@ -1,13 +1,14 @@ { - "version": "38.0.1", + "version": "48.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "testrdsclusterwithfeatureflagDefaultTestDeployAssert8E2E540B Template", "source": { "path": "testrdsclusterwithfeatureflagDefaultTestDeployAssert8E2E540B.template.json", "packaging": "file" }, "destinations": { - "current_account-current_region": { + "current_account-current_region-d8d86b35": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/tree.json index fabfe7323f23b..d4e895d16c613 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/tree.json @@ -1,1236 +1 @@ -{ - "version": "tree-0.1", - "tree": { - "id": "App", - "path": "", - "children": { - "aws-cdk-rds-integ-with-feature-flag": { - "id": "aws-cdk-rds-integ-with-feature-flag", - "path": "aws-cdk-rds-integ-with-feature-flag", - "children": { - "VPC": { - "id": "VPC", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::VPC", - "aws:cdk:cloudformation:props": { - "cidrBlock": "10.0.0.0/16", - "enableDnsHostnames": true, - "enableDnsSupport": true, - "instanceTenancy": "default", - "tags": [ - { - "key": "Name", - "value": "aws-cdk-rds-integ-with-feature-flag/VPC" - } - ] - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "PublicSubnet1": { - "id": "PublicSubnet1", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1", - "children": { - "Subnet": { - "id": "Subnet", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/Subnet", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", - "aws:cdk:cloudformation:props": { - "availabilityZone": { - "Fn::Select": [ - 0, - { - "Fn::GetAZs": "" - } - ] - }, - "cidrBlock": "10.0.0.0/18", - "mapPublicIpOnLaunch": true, - "tags": [ - { - "key": "aws-cdk:subnet-name", - "value": "Public" - }, - { - "key": "aws-cdk:subnet-type", - "value": "Public" - }, - { - "key": "Name", - "value": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1" - } - ], - "vpcId": { - "Ref": "VPCB9E5F0B4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "Acl": { - "id": "Acl", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/Acl", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "RouteTable": { - "id": "RouteTable", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/RouteTable", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", - "aws:cdk:cloudformation:props": { - "tags": [ - { - "key": "Name", - "value": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1" - } - ], - "vpcId": { - "Ref": "VPCB9E5F0B4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "RouteTableAssociation": { - "id": "RouteTableAssociation", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/RouteTableAssociation", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", - "aws:cdk:cloudformation:props": { - "routeTableId": { - "Ref": "VPCPublicSubnet1RouteTableFEE4B781" - }, - "subnetId": { - "Ref": "VPCPublicSubnet1SubnetB4246D30" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "DefaultRoute": { - "id": "DefaultRoute", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/DefaultRoute", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::Route", - "aws:cdk:cloudformation:props": { - "destinationCidrBlock": "0.0.0.0/0", - "gatewayId": { - "Ref": "VPCIGWB7E252D3" - }, - "routeTableId": { - "Ref": "VPCPublicSubnet1RouteTableFEE4B781" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "EIP": { - "id": "EIP", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/EIP", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::EIP", - "aws:cdk:cloudformation:props": { - "domain": "vpc", - "tags": [ - { - "key": "Name", - "value": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1" - } - ] - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "NATGateway": { - "id": "NATGateway", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/NATGateway", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", - "aws:cdk:cloudformation:props": { - "allocationId": { - "Fn::GetAtt": [ - "VPCPublicSubnet1EIP6AD938E8", - "AllocationId" - ] - }, - "subnetId": { - "Ref": "VPCPublicSubnet1SubnetB4246D30" - }, - "tags": [ - { - "key": "Name", - "value": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1" - } - ] - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "PublicSubnet2": { - "id": "PublicSubnet2", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2", - "children": { - "Subnet": { - "id": "Subnet", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/Subnet", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", - "aws:cdk:cloudformation:props": { - "availabilityZone": { - "Fn::Select": [ - 1, - { - "Fn::GetAZs": "" - } - ] - }, - "cidrBlock": "10.0.64.0/18", - "mapPublicIpOnLaunch": true, - "tags": [ - { - "key": "aws-cdk:subnet-name", - "value": "Public" - }, - { - "key": "aws-cdk:subnet-type", - "value": "Public" - }, - { - "key": "Name", - "value": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2" - } - ], - "vpcId": { - "Ref": "VPCB9E5F0B4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "Acl": { - "id": "Acl", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/Acl", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "RouteTable": { - "id": "RouteTable", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/RouteTable", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", - "aws:cdk:cloudformation:props": { - "tags": [ - { - "key": "Name", - "value": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2" - } - ], - "vpcId": { - "Ref": "VPCB9E5F0B4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "RouteTableAssociation": { - "id": "RouteTableAssociation", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/RouteTableAssociation", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", - "aws:cdk:cloudformation:props": { - "routeTableId": { - "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" - }, - "subnetId": { - "Ref": "VPCPublicSubnet2Subnet74179F39" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "DefaultRoute": { - "id": "DefaultRoute", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/DefaultRoute", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::Route", - "aws:cdk:cloudformation:props": { - "destinationCidrBlock": "0.0.0.0/0", - "gatewayId": { - "Ref": "VPCIGWB7E252D3" - }, - "routeTableId": { - "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "EIP": { - "id": "EIP", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/EIP", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::EIP", - "aws:cdk:cloudformation:props": { - "domain": "vpc", - "tags": [ - { - "key": "Name", - "value": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2" - } - ] - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "NATGateway": { - "id": "NATGateway", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/NATGateway", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", - "aws:cdk:cloudformation:props": { - "allocationId": { - "Fn::GetAtt": [ - "VPCPublicSubnet2EIP4947BC00", - "AllocationId" - ] - }, - "subnetId": { - "Ref": "VPCPublicSubnet2Subnet74179F39" - }, - "tags": [ - { - "key": "Name", - "value": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2" - } - ] - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "PrivateSubnet1": { - "id": "PrivateSubnet1", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1", - "children": { - "Subnet": { - "id": "Subnet", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1/Subnet", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", - "aws:cdk:cloudformation:props": { - "availabilityZone": { - "Fn::Select": [ - 0, - { - "Fn::GetAZs": "" - } - ] - }, - "cidrBlock": "10.0.128.0/18", - "mapPublicIpOnLaunch": false, - "tags": [ - { - "key": "aws-cdk:subnet-name", - "value": "Private" - }, - { - "key": "aws-cdk:subnet-type", - "value": "Private" - }, - { - "key": "Name", - "value": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1" - } - ], - "vpcId": { - "Ref": "VPCB9E5F0B4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "Acl": { - "id": "Acl", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1/Acl", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "RouteTable": { - "id": "RouteTable", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1/RouteTable", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", - "aws:cdk:cloudformation:props": { - "tags": [ - { - "key": "Name", - "value": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1" - } - ], - "vpcId": { - "Ref": "VPCB9E5F0B4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "RouteTableAssociation": { - "id": "RouteTableAssociation", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1/RouteTableAssociation", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", - "aws:cdk:cloudformation:props": { - "routeTableId": { - "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" - }, - "subnetId": { - "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "DefaultRoute": { - "id": "DefaultRoute", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1/DefaultRoute", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::Route", - "aws:cdk:cloudformation:props": { - "destinationCidrBlock": "0.0.0.0/0", - "natGatewayId": { - "Ref": "VPCPublicSubnet1NATGatewayE0556630" - }, - "routeTableId": { - "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "PrivateSubnet2": { - "id": "PrivateSubnet2", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2", - "children": { - "Subnet": { - "id": "Subnet", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2/Subnet", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", - "aws:cdk:cloudformation:props": { - "availabilityZone": { - "Fn::Select": [ - 1, - { - "Fn::GetAZs": "" - } - ] - }, - "cidrBlock": "10.0.192.0/18", - "mapPublicIpOnLaunch": false, - "tags": [ - { - "key": "aws-cdk:subnet-name", - "value": "Private" - }, - { - "key": "aws-cdk:subnet-type", - "value": "Private" - }, - { - "key": "Name", - "value": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2" - } - ], - "vpcId": { - "Ref": "VPCB9E5F0B4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "Acl": { - "id": "Acl", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2/Acl", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "RouteTable": { - "id": "RouteTable", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2/RouteTable", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", - "aws:cdk:cloudformation:props": { - "tags": [ - { - "key": "Name", - "value": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2" - } - ], - "vpcId": { - "Ref": "VPCB9E5F0B4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "RouteTableAssociation": { - "id": "RouteTableAssociation", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2/RouteTableAssociation", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", - "aws:cdk:cloudformation:props": { - "routeTableId": { - "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" - }, - "subnetId": { - "Ref": "VPCPrivateSubnet2SubnetCFCDAA7A" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "DefaultRoute": { - "id": "DefaultRoute", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2/DefaultRoute", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::Route", - "aws:cdk:cloudformation:props": { - "destinationCidrBlock": "0.0.0.0/0", - "natGatewayId": { - "Ref": "VPCPublicSubnet2NATGateway3C070193" - }, - "routeTableId": { - "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "IGW": { - "id": "IGW", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/IGW", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", - "aws:cdk:cloudformation:props": { - "tags": [ - { - "key": "Name", - "value": "aws-cdk-rds-integ-with-feature-flag/VPC" - } - ] - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "VPCGW": { - "id": "VPCGW", - "path": "aws-cdk-rds-integ-with-feature-flag/VPC/VPCGW", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", - "aws:cdk:cloudformation:props": { - "internetGatewayId": { - "Ref": "VPCIGWB7E252D3" - }, - "vpcId": { - "Ref": "VPCB9E5F0B4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "Params": { - "id": "Params", - "path": "aws-cdk-rds-integ-with-feature-flag/Params", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-rds-integ-with-feature-flag/Params/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::RDS::DBClusterParameterGroup", - "aws:cdk:cloudformation:props": { - "description": "A nice parameter group", - "family": "aurora-mysql8.0", - "parameters": { - "character_set_database": "utf8mb4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "DbSecurity": { - "id": "DbSecurity", - "path": "aws-cdk-rds-integ-with-feature-flag/DbSecurity", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-rds-integ-with-feature-flag/DbSecurity/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::KMS::Key", - "aws:cdk:cloudformation:props": { - "keyPolicy": { - "Statement": [ - { - "Action": "kms:*", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::", - { - "Ref": "AWS::AccountId" - }, - ":root" - ] - ] - } - }, - "Resource": "*" - } - ], - "Version": "2012-10-17" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "Database": { - "id": "Database", - "path": "aws-cdk-rds-integ-with-feature-flag/Database", - "children": { - "Subnets": { - "id": "Subnets", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/Subnets", - "children": { - "Default": { - "id": "Default", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/Subnets/Default", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::RDS::DBSubnetGroup", - "aws:cdk:cloudformation:props": { - "dbSubnetGroupDescription": "Subnets for Database database", - "subnetIds": [ - { - "Ref": "VPCPublicSubnet1SubnetB4246D30" - }, - { - "Ref": "VPCPublicSubnet2Subnet74179F39" - } - ] - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "SecurityGroup": { - "id": "SecurityGroup", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/SecurityGroup", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/SecurityGroup/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", - "aws:cdk:cloudformation:props": { - "groupDescription": "RDS security group", - "securityGroupEgress": [ - { - "cidrIp": "0.0.0.0/0", - "description": "Allow all outbound traffic by default", - "ipProtocol": "-1" - } - ], - "vpcId": { - "Ref": "VPCB9E5F0B4" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "from 0.0.0.0_0:{IndirectPort}": { - "id": "from 0.0.0.0_0:{IndirectPort}", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/SecurityGroup/from 0.0.0.0_0:{IndirectPort}", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroupIngress", - "aws:cdk:cloudformation:props": { - "cidrIp": "0.0.0.0/0", - "description": "Open to the world", - "fromPort": { - "Fn::GetAtt": [ - "DatabaseB269D8BB", - "Endpoint.Port" - ] - }, - "groupId": { - "Fn::GetAtt": [ - "DatabaseSecurityGroup5C91FDCB", - "GroupId" - ] - }, - "ipProtocol": "tcp", - "toPort": { - "Fn::GetAtt": [ - "DatabaseB269D8BB", - "Endpoint.Port" - ] - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "Resource": { - "id": "Resource", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::RDS::DBCluster", - "aws:cdk:cloudformation:props": { - "autoMinorVersionUpgrade": false, - "copyTagsToSnapshot": true, - "dbClusterParameterGroupName": { - "Ref": "ParamsA8366201" - }, - "dbSubnetGroupName": { - "Ref": "DatabaseSubnets56F17B9A" - }, - "engine": "aurora-mysql", - "engineVersion": "8.0.mysql_aurora.3.07.1", - "kmsKeyId": { - "Fn::GetAtt": [ - "DbSecurity381C2C15", - "Arn" - ] - }, - "masterUsername": "admin", - "masterUserPassword": "7959866cacc02c2d243ecfe177464fe6", - "storageEncrypted": true, - "vpcSecurityGroupIds": [ - { - "Fn::GetAtt": [ - "DatabaseSecurityGroup5C91FDCB", - "GroupId" - ] - } - ] - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "Instance1Wrapper": { - "id": "Instance1Wrapper", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/Instance1Wrapper", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "Instance1": { - "id": "Instance1", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/Instance1", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::RDS::DBInstance", - "aws:cdk:cloudformation:props": { - "dbClusterIdentifier": { - "Ref": "DatabaseB269D8BB" - }, - "dbInstanceClass": "db.t3.medium", - "dbSubnetGroupName": { - "Ref": "DatabaseSubnets56F17B9A" - }, - "engine": "aurora-mysql", - "preferredMaintenanceWindow": "Sat:22:15-Sat:22:45", - "publiclyAccessible": true - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "Instance2Wrapper": { - "id": "Instance2Wrapper", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/Instance2Wrapper", - "children": { - "InstanceParameterGroup": { - "id": "InstanceParameterGroup", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/Instance2Wrapper/InstanceParameterGroup", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/Instance2Wrapper/InstanceParameterGroup/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::RDS::DBParameterGroup", - "aws:cdk:cloudformation:props": { - "description": "Parameter group for aurora-mysql8.0", - "family": "aurora-mysql8.0", - "parameters": {} - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "Instance2": { - "id": "Instance2", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/Instance2", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::RDS::DBInstance", - "aws:cdk:cloudformation:props": { - "dbClusterIdentifier": { - "Ref": "DatabaseB269D8BB" - }, - "dbInstanceClass": "db.t3.medium", - "dbParameterGroupName": { - "Ref": "DatabaseInstance2WrapperInstanceParameterGroup61FBD67B" - }, - "dbSubnetGroupName": { - "Ref": "DatabaseSubnets56F17B9A" - }, - "engine": "aurora-mysql", - "preferredMaintenanceWindow": "Sat:22:15-Sat:22:45", - "publiclyAccessible": true - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "Instance3Wrapper": { - "id": "Instance3Wrapper", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/Instance3Wrapper", - "children": { - "InstanceParameterGroup": { - "id": "InstanceParameterGroup", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/Instance3Wrapper/InstanceParameterGroup", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/Instance3Wrapper/InstanceParameterGroup/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::RDS::DBParameterGroup", - "aws:cdk:cloudformation:props": { - "description": "Parameter group for aurora-mysql8.0", - "family": "aurora-mysql8.0", - "parameters": {} - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "Instance3": { - "id": "Instance3", - "path": "aws-cdk-rds-integ-with-feature-flag/Database/Instance3", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::RDS::DBInstance", - "aws:cdk:cloudformation:props": { - "dbClusterIdentifier": { - "Ref": "DatabaseB269D8BB" - }, - "dbInstanceClass": "db.t3.medium", - "dbParameterGroupName": { - "Ref": "DatabaseInstance3WrapperInstanceParameterGroup00CB9DB5" - }, - "dbSubnetGroupName": { - "Ref": "DatabaseSubnets56F17B9A" - }, - "engine": "aurora-mysql", - "preferredMaintenanceWindow": "Sat:22:15-Sat:22:45", - "publiclyAccessible": true - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "ClusterIamAccess": { - "id": "ClusterIamAccess", - "path": "aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess", - "children": { - "ImportClusterIamAccess": { - "id": "ImportClusterIamAccess", - "path": "aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess/ImportClusterIamAccess", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "Resource": { - "id": "Resource", - "path": "aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Role", - "aws:cdk:cloudformation:props": { - "assumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "ecs-tasks.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "DefaultPolicy": { - "id": "DefaultPolicy", - "path": "aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess/DefaultPolicy", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess/DefaultPolicy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Policy", - "aws:cdk:cloudformation:props": { - "policyDocument": { - "Statement": [ - { - "Action": "rds-db:connect", - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":rds-db:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":dbuser:", - { - "Fn::GetAtt": [ - "DatabaseB269D8BB", - "DBClusterResourceId" - ] - }, - "/db_user" - ] - ] - } - } - ], - "Version": "2012-10-17" - }, - "policyName": "ClusterIamAccessDefaultPolicyA088E4DA", - "roles": [ - { - "Ref": "ClusterIamAccess93AC3DF3" - } - ] - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "aws-cdk-rds-integ-with-feature-flag/BootstrapVersion", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "aws-cdk-rds-integ-with-feature-flag/CheckBootstrapVersion", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "test-rds-cluster-with-feature-flag": { - "id": "test-rds-cluster-with-feature-flag", - "path": "test-rds-cluster-with-feature-flag", - "children": { - "DefaultTest": { - "id": "DefaultTest", - "path": "test-rds-cluster-with-feature-flag/DefaultTest", - "children": { - "Default": { - "id": "Default", - "path": "test-rds-cluster-with-feature-flag/DefaultTest/Default", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "DeployAssert": { - "id": "DeployAssert", - "path": "test-rds-cluster-with-feature-flag/DefaultTest/DeployAssert", - "children": { - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "test-rds-cluster-with-feature-flag/DefaultTest/DeployAssert/BootstrapVersion", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "test-rds-cluster-with-feature-flag/DefaultTest/DeployAssert/CheckBootstrapVersion", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", - "version": "0.0.0" - } - }, - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.4.2" - } - } -} \ No newline at end of file +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"children":{"aws-cdk-rds-integ-with-feature-flag":{"id":"aws-cdk-rds-integ-with-feature-flag","path":"aws-cdk-rds-integ-with-feature-flag","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"children":{"VPC":{"id":"VPC","path":"aws-cdk-rds-integ-with-feature-flag/VPC","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*"]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-rds-integ-with-feature-flag/VPC/Resource","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::VPC","aws:cdk:cloudformation:props":{"cidrBlock":"10.0.0.0/16","enableDnsHostnames":true,"enableDnsSupport":true,"instanceTenancy":"default","tags":[{"key":"Name","value":"aws-cdk-rds-integ-with-feature-flag/VPC"}]}}},"PublicSubnet1":{"id":"PublicSubnet1","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*","*","*","*"]},"children":{"Subnet":{"id":"Subnet","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/Subnet","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Subnet","aws:cdk:cloudformation:props":{"availabilityZone":{"Fn::Select":[0,{"Fn::GetAZs":""}]},"cidrBlock":"10.0.0.0/18","mapPublicIpOnLaunch":true,"tags":[{"key":"aws-cdk:subnet-name","value":"Public"},{"key":"aws-cdk:subnet-type","value":"Public"},{"key":"Name","value":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"Acl":{"id":"Acl","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/Acl","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":[]}},"RouteTable":{"id":"RouteTable","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/RouteTable","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::RouteTable","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"RouteTableAssociation":{"id":"RouteTableAssociation","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/RouteTableAssociation","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SubnetRouteTableAssociation","aws:cdk:cloudformation:props":{"routeTableId":{"Ref":"VPCPublicSubnet1RouteTableFEE4B781"},"subnetId":{"Ref":"VPCPublicSubnet1SubnetB4246D30"}}}},"DefaultRoute":{"id":"DefaultRoute","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/DefaultRoute","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Route","aws:cdk:cloudformation:props":{"destinationCidrBlock":"0.0.0.0/0","gatewayId":{"Ref":"VPCIGWB7E252D3"},"routeTableId":{"Ref":"VPCPublicSubnet1RouteTableFEE4B781"}}}},"EIP":{"id":"EIP","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/EIP","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::EIP","aws:cdk:cloudformation:props":{"domain":"vpc","tags":[{"key":"Name","value":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1"}]}}},"NATGateway":{"id":"NATGateway","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/NATGateway","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::NatGateway","aws:cdk:cloudformation:props":{"allocationId":{"Fn::GetAtt":["VPCPublicSubnet1EIP6AD938E8","AllocationId"]},"subnetId":{"Ref":"VPCPublicSubnet1SubnetB4246D30"},"tags":[{"key":"Name","value":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1"}]}}}}},"PublicSubnet2":{"id":"PublicSubnet2","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*","*","*","*"]},"children":{"Subnet":{"id":"Subnet","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/Subnet","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Subnet","aws:cdk:cloudformation:props":{"availabilityZone":{"Fn::Select":[1,{"Fn::GetAZs":""}]},"cidrBlock":"10.0.64.0/18","mapPublicIpOnLaunch":true,"tags":[{"key":"aws-cdk:subnet-name","value":"Public"},{"key":"aws-cdk:subnet-type","value":"Public"},{"key":"Name","value":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"Acl":{"id":"Acl","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/Acl","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":[]}},"RouteTable":{"id":"RouteTable","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/RouteTable","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::RouteTable","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"RouteTableAssociation":{"id":"RouteTableAssociation","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/RouteTableAssociation","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SubnetRouteTableAssociation","aws:cdk:cloudformation:props":{"routeTableId":{"Ref":"VPCPublicSubnet2RouteTable6F1A15F1"},"subnetId":{"Ref":"VPCPublicSubnet2Subnet74179F39"}}}},"DefaultRoute":{"id":"DefaultRoute","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/DefaultRoute","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Route","aws:cdk:cloudformation:props":{"destinationCidrBlock":"0.0.0.0/0","gatewayId":{"Ref":"VPCIGWB7E252D3"},"routeTableId":{"Ref":"VPCPublicSubnet2RouteTable6F1A15F1"}}}},"EIP":{"id":"EIP","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/EIP","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::EIP","aws:cdk:cloudformation:props":{"domain":"vpc","tags":[{"key":"Name","value":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2"}]}}},"NATGateway":{"id":"NATGateway","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/NATGateway","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::NatGateway","aws:cdk:cloudformation:props":{"allocationId":{"Fn::GetAtt":["VPCPublicSubnet2EIP4947BC00","AllocationId"]},"subnetId":{"Ref":"VPCPublicSubnet2Subnet74179F39"},"tags":[{"key":"Name","value":"aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2"}]}}}}},"PrivateSubnet1":{"id":"PrivateSubnet1","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*","*","*"]},"children":{"Subnet":{"id":"Subnet","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1/Subnet","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Subnet","aws:cdk:cloudformation:props":{"availabilityZone":{"Fn::Select":[0,{"Fn::GetAZs":""}]},"cidrBlock":"10.0.128.0/18","mapPublicIpOnLaunch":false,"tags":[{"key":"aws-cdk:subnet-name","value":"Private"},{"key":"aws-cdk:subnet-type","value":"Private"},{"key":"Name","value":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"Acl":{"id":"Acl","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1/Acl","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":[]}},"RouteTable":{"id":"RouteTable","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1/RouteTable","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::RouteTable","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"RouteTableAssociation":{"id":"RouteTableAssociation","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1/RouteTableAssociation","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SubnetRouteTableAssociation","aws:cdk:cloudformation:props":{"routeTableId":{"Ref":"VPCPrivateSubnet1RouteTableBE8A6027"},"subnetId":{"Ref":"VPCPrivateSubnet1Subnet8BCA10E0"}}}},"DefaultRoute":{"id":"DefaultRoute","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1/DefaultRoute","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Route","aws:cdk:cloudformation:props":{"destinationCidrBlock":"0.0.0.0/0","natGatewayId":{"Ref":"VPCPublicSubnet1NATGatewayE0556630"},"routeTableId":{"Ref":"VPCPrivateSubnet1RouteTableBE8A6027"}}}}}},"PrivateSubnet2":{"id":"PrivateSubnet2","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*","*","*"]},"children":{"Subnet":{"id":"Subnet","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2/Subnet","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Subnet","aws:cdk:cloudformation:props":{"availabilityZone":{"Fn::Select":[1,{"Fn::GetAZs":""}]},"cidrBlock":"10.0.192.0/18","mapPublicIpOnLaunch":false,"tags":[{"key":"aws-cdk:subnet-name","value":"Private"},{"key":"aws-cdk:subnet-type","value":"Private"},{"key":"Name","value":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"Acl":{"id":"Acl","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2/Acl","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":[]}},"RouteTable":{"id":"RouteTable","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2/RouteTable","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::RouteTable","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"RouteTableAssociation":{"id":"RouteTableAssociation","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2/RouteTableAssociation","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SubnetRouteTableAssociation","aws:cdk:cloudformation:props":{"routeTableId":{"Ref":"VPCPrivateSubnet2RouteTable0A19E10E"},"subnetId":{"Ref":"VPCPrivateSubnet2SubnetCFCDAA7A"}}}},"DefaultRoute":{"id":"DefaultRoute","path":"aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2/DefaultRoute","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Route","aws:cdk:cloudformation:props":{"destinationCidrBlock":"0.0.0.0/0","natGatewayId":{"Ref":"VPCPublicSubnet2NATGateway3C070193"},"routeTableId":{"Ref":"VPCPrivateSubnet2RouteTable0A19E10E"}}}}}},"IGW":{"id":"IGW","path":"aws-cdk-rds-integ-with-feature-flag/VPC/IGW","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::InternetGateway","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"aws-cdk-rds-integ-with-feature-flag/VPC"}]}}},"VPCGW":{"id":"VPCGW","path":"aws-cdk-rds-integ-with-feature-flag/VPC/VPCGW","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::VPCGatewayAttachment","aws:cdk:cloudformation:props":{"internetGatewayId":{"Ref":"VPCIGWB7E252D3"},"vpcId":{"Ref":"VPCB9E5F0B4"}}}}}},"Params":{"id":"Params","path":"aws-cdk-rds-integ-with-feature-flag/Params","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*","*"]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-rds-integ-with-feature-flag/Params/Resource","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::RDS::DBClusterParameterGroup","aws:cdk:cloudformation:props":{"description":"A nice parameter group","family":"aurora-mysql8.0","parameters":{"character_set_database":"utf8mb4"}}}}}},"DbSecurity":{"id":"DbSecurity","path":"aws-cdk-rds-integ-with-feature-flag/DbSecurity","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*"]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-rds-integ-with-feature-flag/DbSecurity/Resource","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::KMS::Key","aws:cdk:cloudformation:props":{"keyPolicy":{"Statement":[{"Action":"kms:*","Effect":"Allow","Principal":{"AWS":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":iam::",{"Ref":"AWS::AccountId"},":root"]]}},"Resource":"*"}],"Version":"2012-10-17"}}}}}},"Database":{"id":"Database","path":"aws-cdk-rds-integ-with-feature-flag/Database","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*"]},"children":{"Subnets":{"id":"Subnets","path":"aws-cdk-rds-integ-with-feature-flag/Database/Subnets","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*"]},"children":{"Default":{"id":"Default","path":"aws-cdk-rds-integ-with-feature-flag/Database/Subnets/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::RDS::DBSubnetGroup","aws:cdk:cloudformation:props":{"dbSubnetGroupDescription":"Subnets for Database database","subnetIds":[{"Ref":"VPCPublicSubnet1SubnetB4246D30"},{"Ref":"VPCPublicSubnet2Subnet74179F39"}]}}}}},"SecurityGroup":{"id":"SecurityGroup","path":"aws-cdk-rds-integ-with-feature-flag/Database/SecurityGroup","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*","*"]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-rds-integ-with-feature-flag/Database/SecurityGroup/Resource","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SecurityGroup","aws:cdk:cloudformation:props":{"groupDescription":"RDS security group","securityGroupEgress":[{"cidrIp":"0.0.0.0/0","description":"Allow all outbound traffic by default","ipProtocol":"-1"}],"vpcId":{"Ref":"VPCB9E5F0B4"}}}},"from 0.0.0.0_0:{IndirectPort}":{"id":"from 0.0.0.0_0:{IndirectPort}","path":"aws-cdk-rds-integ-with-feature-flag/Database/SecurityGroup/from 0.0.0.0_0:{IndirectPort}","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SecurityGroupIngress","aws:cdk:cloudformation:props":{"cidrIp":"0.0.0.0/0","description":"Open to the world","fromPort":{"Fn::GetAtt":["DatabaseB269D8BB","Endpoint.Port"]},"groupId":{"Fn::GetAtt":["DatabaseSecurityGroup5C91FDCB","GroupId"]},"ipProtocol":"tcp","toPort":{"Fn::GetAtt":["DatabaseB269D8BB","Endpoint.Port"]}}}}}},"Resource":{"id":"Resource","path":"aws-cdk-rds-integ-with-feature-flag/Database/Resource","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::RDS::DBCluster","aws:cdk:cloudformation:props":{"autoMinorVersionUpgrade":false,"copyTagsToSnapshot":true,"dbClusterParameterGroupName":{"Ref":"ParamsA8366201"},"dbSubnetGroupName":{"Ref":"DatabaseSubnets56F17B9A"},"deleteAutomatedBackups":false,"engine":"aurora-mysql","engineVersion":"8.0.mysql_aurora.3.07.1","kmsKeyId":{"Fn::GetAtt":["DbSecurity381C2C15","Arn"]},"masterUsername":"admin","masterUserPassword":"7959866cacc02c2d243ecfe177464fe6","storageEncrypted":true,"vpcSecurityGroupIds":[{"Fn::GetAtt":["DatabaseSecurityGroup5C91FDCB","GroupId"]}]}}},"Instance1Wrapper":{"id":"Instance1Wrapper","path":"aws-cdk-rds-integ-with-feature-flag/Database/Instance1Wrapper","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*"]}},"Instance1":{"id":"Instance1","path":"aws-cdk-rds-integ-with-feature-flag/Database/Instance1","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::RDS::DBInstance","aws:cdk:cloudformation:props":{"dbClusterIdentifier":{"Ref":"DatabaseB269D8BB"},"dbInstanceClass":"db.t3.medium","dbSubnetGroupName":{"Ref":"DatabaseSubnets56F17B9A"},"engine":"aurora-mysql","preferredMaintenanceWindow":"Sat:22:15-Sat:22:45","publiclyAccessible":true}}},"Instance2Wrapper":{"id":"Instance2Wrapper","path":"aws-cdk-rds-integ-with-feature-flag/Database/Instance2Wrapper","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*"]},"children":{"InstanceParameterGroup":{"id":"InstanceParameterGroup","path":"aws-cdk-rds-integ-with-feature-flag/Database/Instance2Wrapper/InstanceParameterGroup","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*","*"]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-rds-integ-with-feature-flag/Database/Instance2Wrapper/InstanceParameterGroup/Resource","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::RDS::DBParameterGroup","aws:cdk:cloudformation:props":{"description":"Parameter group for aurora-mysql8.0","family":"aurora-mysql8.0","parameters":{}}}}}}}},"Instance2":{"id":"Instance2","path":"aws-cdk-rds-integ-with-feature-flag/Database/Instance2","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::RDS::DBInstance","aws:cdk:cloudformation:props":{"dbClusterIdentifier":{"Ref":"DatabaseB269D8BB"},"dbInstanceClass":"db.t3.medium","dbParameterGroupName":{"Ref":"DatabaseInstance2WrapperInstanceParameterGroup61FBD67B"},"dbSubnetGroupName":{"Ref":"DatabaseSubnets56F17B9A"},"engine":"aurora-mysql","preferredMaintenanceWindow":"Sat:22:15-Sat:22:45","publiclyAccessible":true}}},"Instance3Wrapper":{"id":"Instance3Wrapper","path":"aws-cdk-rds-integ-with-feature-flag/Database/Instance3Wrapper","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*"]},"children":{"InstanceParameterGroup":{"id":"InstanceParameterGroup","path":"aws-cdk-rds-integ-with-feature-flag/Database/Instance3Wrapper/InstanceParameterGroup","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*","*"]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-rds-integ-with-feature-flag/Database/Instance3Wrapper/InstanceParameterGroup/Resource","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::RDS::DBParameterGroup","aws:cdk:cloudformation:props":{"description":"Parameter group for aurora-mysql8.0","family":"aurora-mysql8.0","parameters":{}}}}}}}},"Instance3":{"id":"Instance3","path":"aws-cdk-rds-integ-with-feature-flag/Database/Instance3","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::RDS::DBInstance","aws:cdk:cloudformation:props":{"dbClusterIdentifier":{"Ref":"DatabaseB269D8BB"},"dbInstanceClass":"db.t3.medium","dbParameterGroupName":{"Ref":"DatabaseInstance3WrapperInstanceParameterGroup00CB9DB5"},"dbSubnetGroupName":{"Ref":"DatabaseSubnets56F17B9A"},"engine":"aurora-mysql","preferredMaintenanceWindow":"Sat:22:15-Sat:22:45","publiclyAccessible":true}}}}},"ClusterIamAccess":{"id":"ClusterIamAccess","path":"aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*","*","*","*","*"]},"children":{"ImportClusterIamAccess":{"id":"ImportClusterIamAccess","path":"aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess/ImportClusterIamAccess","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*"]}},"Resource":{"id":"Resource","path":"aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess/Resource","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Role","aws:cdk:cloudformation:props":{"assumeRolePolicyDocument":{"Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"Service":"ecs-tasks.amazonaws.com"}}],"Version":"2012-10-17"}}}},"DefaultPolicy":{"id":"DefaultPolicy","path":"aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess/DefaultPolicy","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2","metadata":["*","*","*","*"]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess/DefaultPolicy/Resource","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Policy","aws:cdk:cloudformation:props":{"policyDocument":{"Statement":[{"Action":"rds-db:connect","Effect":"Allow","Resource":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":rds-db:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":dbuser:",{"Fn::GetAtt":["DatabaseB269D8BB","DBClusterResourceId"]},"/db_user"]]}}],"Version":"2012-10-17"},"policyName":"ClusterIamAccessDefaultPolicyA088E4DA","roles":[{"Ref":"ClusterIamAccess93AC3DF3"}]}}}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-rds-integ-with-feature-flag/BootstrapVersion","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-rds-integ-with-feature-flag/CheckBootstrapVersion","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}},"test-rds-cluster-with-feature-flag":{"id":"test-rds-cluster-with-feature-flag","path":"test-rds-cluster-with-feature-flag","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"test-rds-cluster-with-feature-flag/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"test-rds-cluster-with-feature-flag/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"test-rds-cluster-with-feature-flag/DefaultTest/DeployAssert","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"test-rds-cluster-with-feature-flag/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"test-rds-cluster-with-feature-flag/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.ts index 66caa47941fa0..5d200984d055b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.ts @@ -63,6 +63,7 @@ class TestStack extends cdk.Stack { parameterGroup: params, storageEncryptionKey: kmsKey, autoMinorVersionUpgrade: false, + deleteAutomatedBackups: false, }); cluster.connections.allowDefaultPortFromAnyIpv4('Open to the world'); @@ -100,4 +101,3 @@ const stackWithFeatureFlag = new TestStack(appWithFeatureFlag, 'aws-cdk-rds-inte new IntegTest(appWithFeatureFlag, 'test-rds-cluster-with-feature-flag', { testCases: [stackWithFeatureFlag], }); -appWithFeatureFlag.synth(); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.bundling.docker-opts.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.bundling.docker-opts.ts index c356ac29bdb1d..71c729d722c15 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.bundling.docker-opts.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.bundling.docker-opts.ts @@ -9,7 +9,10 @@ const stack = new Stack(app, 'cdk-integ-assets-bundling-docker-opts'); new assets.Asset(stack, 'BundledAsset', { path: path.join(__dirname, 'markdown-asset'), // /asset-input and working directory in the container bundling: { - image: DockerImage.fromBuild(path.join(__dirname, 'alpine-markdown')), // Build an image + // Build an image + image: DockerImage.fromBuild(path.join(__dirname, 'alpine-markdown'), { + platform: 'linux/amd64', + }), command: [ 'sh', '-c', ` markdown index.md > /asset-output/index.html diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6.assets.json new file mode 100644 index 0000000000000..31087d713734d --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6 Template", + "source": { + "path": "EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-d8d86b35": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/asset.b8cec122f25692e8b194663d25a2ee5e0b65e55df966120791d6a3ddc08fc136/index.js b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/asset.b8cec122f25692e8b194663d25a2ee5e0b65e55df966120791d6a3ddc08fc136/index.js new file mode 100644 index 0000000000000..d3d578f964997 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/asset.b8cec122f25692e8b194663d25a2ee5e0b65e55df966120791d6a3ddc08fc136/index.js @@ -0,0 +1 @@ +"use strict";var o=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var c=(e,n)=>{for(var s in n)o(e,s,{get:n[s],enumerable:!0})},l=(e,n,s,t)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of a(n))!p.call(e,r)&&r!==s&&o(e,r,{get:()=>n[r],enumerable:!(t=i(n,r))||t.enumerable});return e};var g=e=>l(o({},"__esModule",{value:!0}),e);var y={};c(y,{handler:()=>u});module.exports=g(y);function x(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}async function u(e){console.log("Event: %j",{...e,ResponseURL:"..."});let n=Object.entries(e.expressionAttributeValues).reduce((s,[t,r])=>s.replace(new RegExp(x(t),"g"),JSON.stringify(r)),e.expression);return console.log(`Expression: ${n}`),[eval][0](n)}0&&(module.exports={handler}); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/cdk.out new file mode 100644 index 0000000000000..523a9aac37cbf --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"48.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/evaluate-expression-nodejs22.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/evaluate-expression-nodejs22.assets.json new file mode 100644 index 0000000000000..e54887e2b1e3c --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/evaluate-expression-nodejs22.assets.json @@ -0,0 +1,34 @@ +{ + "version": "48.0.0", + "files": { + "b8cec122f25692e8b194663d25a2ee5e0b65e55df966120791d6a3ddc08fc136": { + "displayName": "Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/Code", + "source": { + "path": "asset.b8cec122f25692e8b194663d25a2ee5e0b65e55df966120791d6a3ddc08fc136", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region-59391115": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "b8cec122f25692e8b194663d25a2ee5e0b65e55df966120791d6a3ddc08fc136.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "c5164ccfa069cfa49003acfb6fe3d40ba28c968ba56b2a0de4a8da687be8f41a": { + "displayName": "evaluate-expression-nodejs22 Template", + "source": { + "path": "evaluate-expression-nodejs22.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-02ca34e9": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "c5164ccfa069cfa49003acfb6fe3d40ba28c968ba56b2a0de4a8da687be8f41a.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/evaluate-expression-nodejs22.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/evaluate-expression-nodejs22.template.json new file mode 100644 index 0000000000000..67b657ee75f5d --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/evaluate-expression-nodejs22.template.json @@ -0,0 +1,201 @@ +{ + "Resources": { + "Evalb64e1fb89c894f7d8a342e2a1c5f6d7eServiceRole544E6136": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "Evalb64e1fb89c894f7d8a342e2a1c5f6d7e3682A325": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "b8cec122f25692e8b194663d25a2ee5e0b65e55df966120791d6a3ddc08fc136.zip" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "Evalb64e1fb89c894f7d8a342e2a1c5f6d7eServiceRole544E6136", + "Arn" + ] + }, + "Runtime": "nodejs22.x" + }, + "DependsOn": [ + "Evalb64e1fb89c894f7d8a342e2a1c5f6d7eServiceRole544E6136" + ] + }, + "Evalb64e1fb89c894f7d8a342e2a1c5f6d7eLogGroup529D8984": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "Evalb64e1fb89c894f7d8a342e2a1c5f6d7e3682A325" + } + ] + ] + }, + "RetentionInDays": 731 + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "StateMachineRoleB840431D": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "states.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "StateMachineRoleDefaultPolicyDF1E6607": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "Evalb64e1fb89c894f7d8a342e2a1c5f6d7e3682A325", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "Evalb64e1fb89c894f7d8a342e2a1c5f6d7e3682A325", + "Arn" + ] + }, + ":*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "StateMachineRoleDefaultPolicyDF1E6607", + "Roles": [ + { + "Ref": "StateMachineRoleB840431D" + } + ] + } + }, + "StateMachine2E01A3A5": { + "Type": "AWS::StepFunctions::StateMachine", + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "", + [ + "{\"StartAt\":\"Task\",\"States\":{\"Task\":{\"End\":true,\"Type\":\"Task\",\"Resource\":\"", + { + "Fn::GetAtt": [ + "Evalb64e1fb89c894f7d8a342e2a1c5f6d7e3682A325", + "Arn" + ] + }, + "\",\"Parameters\":{\"expression\":\"$.a + $.b\",\"expressionAttributeValues\":{\"$.a.$\":\"$.a\",\"$.b.$\":\"$.b\"}}}}}" + ] + ] + }, + "RoleArn": { + "Fn::GetAtt": [ + "StateMachineRoleB840431D", + "Arn" + ] + } + }, + "DependsOn": [ + "StateMachineRoleDefaultPolicyDF1E6607", + "StateMachineRoleB840431D" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/integ.json new file mode 100644 index 0000000000000..2811751b93c71 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "48.0.0", + "testCases": { + "EvaluateExpressionNodejs22/DefaultTest": { + "stacks": [ + "evaluate-expression-nodejs22" + ], + "assertionStack": "EvaluateExpressionNodejs22/DefaultTest/DeployAssert", + "assertionStackName": "EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6" + } + }, + "minimumCliVersion": "2.1027.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/manifest.json new file mode 100644 index 0000000000000..6f037890e0e9e --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/manifest.json @@ -0,0 +1,787 @@ +{ + "version": "48.0.0", + "artifacts": { + "evaluate-expression-nodejs22.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "evaluate-expression-nodejs22.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "evaluate-expression-nodejs22": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "evaluate-expression-nodejs22.template.json", + "terminationProtection": false, + "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}/c5164ccfa069cfa49003acfb6fe3d40ba28c968ba56b2a0de4a8da687be8f41a.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "evaluate-expression-nodejs22.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "evaluate-expression-nodejs22.assets" + ], + "metadata": { + "/evaluate-expression-nodejs22/Task/EvalFunction": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "uuid": "*", + "lambdaPurpose": "*", + "runtime": "*", + "code": "*", + "handler": "*" + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addMetadata": [ + "*", + true + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addMetadata": [ + "*", + "*" + ] + } + } + ], + "/evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "runtime": "*", + "code": "*", + "handler": "*" + } + }, + { + "type": "aws:cdk:is-custom-resource-handler-singleton", + "data": true + }, + { + "type": "aws:cdk:is-custom-resource-handler-runtime-family", + "data": 0 + } + ], + "/evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/ServiceRole": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "assumedBy": { + "principalAccount": "*", + "assumeRoleAction": "*" + }, + "managedPolicies": [ + { + "managedPolicyArn": "*" + } + ] + } + } + ], + "/evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/ServiceRole/ImportServiceRole": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], + "/evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Evalb64e1fb89c894f7d8a342e2a1c5f6d7eServiceRole544E6136" + } + ], + "/evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Evalb64e1fb89c894f7d8a342e2a1c5f6d7e3682A325" + } + ], + "/evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/LogGroup": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "logGroupName": "*" + } + } + ], + "/evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/LogGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Evalb64e1fb89c894f7d8a342e2a1c5f6d7eLogGroup529D8984" + } + ], + "/evaluate-expression-nodejs22/StateMachine": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "definition": "*" + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addToRolePolicy": [ + {} + ] + } + } + ], + "/evaluate-expression-nodejs22/StateMachine/Role": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "assumedBy": { + "principalAccount": "*", + "assumeRoleAction": "*" + } + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addToPrincipalPolicy": [ + {} + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachInlinePolicy": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachInlinePolicy": [ + "*" + ] + } + } + ], + "/evaluate-expression-nodejs22/StateMachine/Role/ImportRole": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], + "/evaluate-expression-nodejs22/StateMachine/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "StateMachineRoleB840431D" + } + ], + "/evaluate-expression-nodejs22/StateMachine/Role/DefaultPolicy": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachToRole": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachToRole": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addStatements": [ + {} + ] + } + } + ], + "/evaluate-expression-nodejs22/StateMachine/Role/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "StateMachineRoleDefaultPolicyDF1E6607" + } + ], + "/evaluate-expression-nodejs22/StateMachine/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "StateMachine2E01A3A5" + } + ], + "/evaluate-expression-nodejs22/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/evaluate-expression-nodejs22/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "evaluate-expression-nodejs22" + }, + "EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6.template.json", + "terminationProtection": false, + "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}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "EvaluateExpressionNodejs22DefaultTestDeployAssert27FE8CA6.assets" + ], + "metadata": { + "/EvaluateExpressionNodejs22/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/EvaluateExpressionNodejs22/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "EvaluateExpressionNodejs22/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "aws-cdk-lib/feature-flag-report": { + "type": "cdk:feature-flag-report", + "properties": { + "module": "aws-cdk-lib", + "flags": { + "@aws-cdk/aws-signer:signingProfileNamePassedToCfn": { + "recommendedValue": true, + "explanation": "Pass signingProfileName to CfnSigningProfile" + }, + "@aws-cdk/core:newStyleStackSynthesis": { + "recommendedValue": true, + "explanation": "Switch to new stack synthesis method which enables CI/CD", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:stackRelativeExports": { + "recommendedValue": true, + "explanation": "Name exports based on the construct paths relative to the stack, rather than the global construct path", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-ecs-patterns:secGroupsDisablesImplicitOpenListener": { + "recommendedValue": true, + "explanation": "Disable implicit openListener when custom security groups are provided" + }, + "@aws-cdk/aws-rds:lowercaseDbIdentifier": { + "recommendedValue": true, + "explanation": "Force lowercasing of RDS Cluster names in CDK", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": { + "recommendedValue": true, + "explanation": "Allow adding/removing multiple UsagePlanKeys independently", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeVersionProps": { + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeLayerVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`." + }, + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": { + "recommendedValue": true, + "explanation": "Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:checkSecretUsage": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this flag to make it impossible to accidentally use SecretValues in unsafe locations" + }, + "@aws-cdk/core:target-partitions": { + "recommendedValue": [ + "aws", + "aws-cn" + ], + "explanation": "What regions to include in lookup tables of environment agnostic stacks" + }, + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": { + "userValue": true, + "recommendedValue": true, + "explanation": "ECS extensions will automatically add an `awslogs` driver if no logging is specified" + }, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names." + }, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": { + "userValue": true, + "recommendedValue": true, + "explanation": "ARN format used by ECS. In the new ARN format, the cluster name is part of the resource ID." + }, + "@aws-cdk/aws-iam:minimizePolicies": { + "userValue": true, + "recommendedValue": true, + "explanation": "Minimize IAM policies by combining Statements" + }, + "@aws-cdk/core:validateSnapshotRemovalPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Error on snapshot removal policies on resources that do not support it." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate key aliases that include the stack name" + }, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to create an S3 bucket policy by default in cases where an AWS service would automatically create the Policy if one does not exist." + }, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict KMS key policy for encrypted Queues a bit more" + }, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make default CloudWatch Role behavior safe for multiple API Gateways in one environment" + }, + "@aws-cdk/core:enablePartitionLiterals": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make ARNs concrete if AWS partition is known" + }, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": { + "userValue": true, + "recommendedValue": true, + "explanation": "Event Rules may only push to encrypted SQS queues in the same account" + }, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": { + "userValue": true, + "recommendedValue": true, + "explanation": "Avoid setting the \"ECS\" deployment controller when adding a circuit breaker" + }, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature to by default create default policy names for imported roles that depend on the stack the role is in." + }, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use S3 Bucket Policy instead of ACLs for Server Access Logging" + }, + "@aws-cdk/aws-route53-patters:useCertificate": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use the official `Certificate` resource instead of `DnsValidatedCertificate`" + }, + "@aws-cdk/customresources:installLatestAwsSdkDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "Whether to install the latest SDK by default in AwsCustomResource" + }, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use unique resource name for Database Proxy" + }, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Remove CloudWatch alarms from deployment group" + }, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include authorizer configuration in the calculation of the API deployment logical ID." + }, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": { + "userValue": true, + "recommendedValue": true, + "explanation": "Define user data for a launch template by default when a machine image is provided." + }, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": { + "userValue": true, + "recommendedValue": true, + "explanation": "SecretTargetAttachments uses the ResourcePolicy of the attached Secret." + }, + "@aws-cdk/aws-redshift:columnId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Whether to use an ID to track Redshift column changes" + }, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable AmazonEMRServicePolicy_v2 managed policies" + }, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict access to the VPC default security group" + }, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a unique id for each RequestValidator added to a method" + }, + "@aws-cdk/aws-kms:aliasNameRef": { + "userValue": true, + "recommendedValue": true, + "explanation": "KMS Alias name and keyArn will have implicit reference to KMS Key" + }, + "@aws-cdk/aws-kms:applyImportedAliasPermissionsToPrincipal": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable grant methods on Aliases imported by name to use kms:ResourceAliases condition" + }, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a launch template when creating an AutoScalingGroup" + }, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include the stack prefix in the stack name generation process" + }, + "@aws-cdk/aws-efs:denyAnonymousAccess": { + "userValue": true, + "recommendedValue": true, + "explanation": "EFS denies anonymous clients accesses" + }, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables support for Multi-AZ with Standby deployment for opensearch domains" + }, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables aws-lambda-nodejs.Function to use the latest available NodeJs runtime as the default" + }, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, mount targets will have a stable logicalId that is linked to the associated subnet." + }, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a scope of InstanceParameterGroup for AuroraClusterInstance with each parameters will change." + }, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, will always use the arn for identifiers for CfnSourceApiAssociation in the GraphqlApi construct rather than id." + }, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, creating an RDS database cluster from a snapshot will only render credentials for snapshot credentials." + }, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the CodeCommit source action is using the default branch name 'main'." + }, + "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the logical ID of a Lambda permission for a Lambda action includes an alarm ID." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default value for crossAccountKeys to false." + }, + "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default pipeline type to V2." + }, + "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, IAM Policy created from KMS key grant will reduce the resource scope to this key only." + }, + "@aws-cdk/pipelines:reduceAssetRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from PipelineAssetsFileRole trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-eks:nodegroupNameAttribute": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, nodegroupName attribute of the provisioned EKS NodeGroup will not have the cluster name prefix." + }, + "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default volume type of the EBS volume will be GP3" + }, + "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, remove default deployment alarm settings" + }, + "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, the custom resource used for `AwsCustomResource` will configure the `logApiResponseData` property as true by default" + }, + "@aws-cdk/aws-s3:keepNotificationInImportedBucket": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, Adding notifications to a bucket in the current stack will not remove notification from imported stack." + }, + "@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask": { + "recommendedValue": true, + "explanation": "When enabled, use new props for S3 URI field in task definition of state machine for bedrock invoke model.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:explicitStackTags": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, stack tags need to be assigned explicitly on a Stack." + }, + "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": { + "userValue": false, + "recommendedValue": false, + "explanation": "When set to true along with canContainersAccessInstanceRole=false in ECS cluster, new updated commands will be added to UserData to block container accessing IMDS. **Applicable to Linux only. IMPORTANT: See [details.](#aws-cdkaws-ecsenableImdsBlockingDeprecatedFeature)**" + }, + "@aws-cdk/aws-ecs:disableEcsImdsBlocking": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, CDK synth will throw exception if canContainersAccessInstanceRole is false. **IMPORTANT: See [details.](#aws-cdkaws-ecsdisableEcsImdsBlocking)**" + }, + "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, we will only grant the necessary permissions when users specify cloudwatch log group through logConfiguration" + }, + "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled will allow you to specify a resource policy per replica, and not copy the source table policy to all replicas" + }, + "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, initOptions.timeout and resourceSignalTimeout values will be summed together." + }, + "@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a Lambda authorizer Permission created when using GraphqlApi will be properly scoped with a SourceArn." + }, + "@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the value of property `instanceResourceId` in construct `DatabaseInstanceReadReplica` will be set to the correct value which is `DbiResourceId` instead of currently `DbInstanceArn`" + }, + "@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CFN templates added with `cfn-include` will error if the template contains Resource Update or Create policies with CFN Intrinsics that include non-primitive values." + }, + "@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, both `@aws-sdk` and `@smithy` packages will be excluded from the Lambda Node.js 18.x runtime to prevent version mismatches in bundled applications." + }, + "@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resource of IAM Run Ecs policy generated by SFN EcsRunTask will reference the definition, instead of constructing ARN." + }, + "@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the BastionHost construct will use the latest Amazon Linux 2023 AMI, instead of Amazon Linux 2." + }, + "@aws-cdk/core:aspectStabilization": { + "recommendedValue": true, + "explanation": "When enabled, a stabilization loop will be run when invoking Aspects during synthesis.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, use a new method for DNS Name of user pool domain target without creating a custom resource." + }, + "@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default security group ingress rules will allow IPv6 ingress from anywhere" + }, + "@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default behaviour of OIDC provider will reject unauthorized connections" + }, + "@aws-cdk/core:enableAdditionalMetadataCollection": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will expand the scope of usage data collected to better inform CDK development and improve communication for security concerns and emerging issues." + }, + "@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": { + "userValue": false, + "recommendedValue": false, + "explanation": "[Deprecated] When enabled, Lambda will create new inline policies with AddToRolePolicy instead of adding to the Default Policy Statement" + }, + "@aws-cdk/aws-s3:setUniqueReplicationRoleName": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will automatically generate a unique role name that is used for s3 object replication." + }, + "@aws-cdk/pipelines:reduceStageRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from Stage addActions trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-events:requireEventBusPolicySid": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, grantPutEventsTo() will use resource policies with Statement IDs for service principals." + }, + "@aws-cdk/core:aspectPrioritiesMutating": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, Aspects added by the construct library on your behalf will be given a priority of MUTATING." + }, + "@aws-cdk/aws-dynamodb:retainTableReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, table replica will be default to the removal policy of source table unless specified otherwise." + }, + "@aws-cdk/cognito:logUserPoolClientSecretValue": { + "recommendedValue": false, + "explanation": "When disabled, the value of the user pool client secret will not be logged in the custom resource lambda function logs." + }, + "@aws-cdk/pipelines:reduceCrossAccountActionRoleTrustScope": { + "recommendedValue": true, + "explanation": "When enabled, scopes down the trust policy for the cross-account action role", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resultWriterV2 property of DistributedMap will be used insted of resultWriter" + }, + "@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions": { + "userValue": true, + "recommendedValue": true, + "explanation": "Add an S3 trust policy to a KMS key resource policy for SNS subscriptions." + }, + "@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the EgressOnlyGateway resource is only created if private subnets are defined in the dual-stack VPC." + }, + "@aws-cdk/aws-ec2-alpha:useResourceIdForVpcV2Migration": { + "recommendedValue": false, + "explanation": "When enabled, use resource IDs for VPC V2 migration" + }, + "@aws-cdk/aws-s3:publicAccessBlockedByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, setting any combination of options for BlockPublicAccess will automatically set true for any options not defined." + }, + "@aws-cdk/aws-lambda:useCdkManagedLogGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK creates and manages loggroup for the lambda function" + } + } + } + } + }, + "minimumCliVersion": "2.1027.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/tree.json new file mode 100644 index 0000000000000..9216d511aefed --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.js.snapshot/tree.json @@ -0,0 +1 @@ +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"evaluate-expression-nodejs22":{"id":"evaluate-expression-nodejs22","path":"evaluate-expression-nodejs22","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"Task":{"id":"Task","path":"evaluate-expression-nodejs22/Task","constructInfo":{"fqn":"aws-cdk-lib.aws_stepfunctions_tasks.EvaluateExpression","version":"0.0.0"},"children":{"EvalFunction":{"id":"EvalFunction","path":"evaluate-expression-nodejs22/Task/EvalFunction","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.SingletonFunction","version":"0.0.0","metadata":[{"uuid":"*","lambdaPurpose":"*","runtime":"*","code":"*","handler":"*"},{"addMetadata":["*",true]},{"addMetadata":["*","*"]}]}}}},"Evalb64e1fb89c894f7d8a342e2a1c5f6d7e":{"id":"Evalb64e1fb89c894f7d8a342e2a1c5f6d7e","path":"evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.Function","version":"0.0.0","metadata":[{"runtime":"*","code":"*","handler":"*"}]},"children":{"ServiceRole":{"id":"ServiceRole","path":"evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/ServiceRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"},"managedPolicies":[{"managedPolicyArn":"*"}]}]},"children":{"ImportServiceRole":{"id":"ImportServiceRole","path":"evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/ServiceRole/ImportServiceRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/ServiceRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Role","aws:cdk:cloudformation:props":{"assumeRolePolicyDocument":{"Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"}}],"Version":"2012-10-17"},"managedPolicyArns":[{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]]}]}}}}},"Code":{"id":"Code","path":"evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/Code","constructInfo":{"fqn":"aws-cdk-lib.aws_s3_assets.Asset","version":"0.0.0"},"children":{"Stage":{"id":"Stage","path":"evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/Code/Stage","constructInfo":{"fqn":"aws-cdk-lib.AssetStaging","version":"0.0.0"}},"AssetBucket":{"id":"AssetBucket","path":"evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/Code/AssetBucket","constructInfo":{"fqn":"aws-cdk-lib.aws_s3.BucketBase","version":"0.0.0","metadata":[]}}}},"Resource":{"id":"Resource","path":"evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.CfnFunction","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::Lambda::Function","aws:cdk:cloudformation:props":{"code":{"s3Bucket":{"Fn::Sub":"cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"},"s3Key":"b8cec122f25692e8b194663d25a2ee5e0b65e55df966120791d6a3ddc08fc136.zip"},"handler":"index.handler","role":{"Fn::GetAtt":["Evalb64e1fb89c894f7d8a342e2a1c5f6d7eServiceRole544E6136","Arn"]},"runtime":"nodejs22.x"}}},"LogGroup":{"id":"LogGroup","path":"evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/LogGroup","constructInfo":{"fqn":"aws-cdk-lib.aws_logs.LogGroup","version":"0.0.0","metadata":[{"logGroupName":"*"}]},"children":{"Resource":{"id":"Resource","path":"evaluate-expression-nodejs22/Evalb64e1fb89c894f7d8a342e2a1c5f6d7e/LogGroup/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_logs.CfnLogGroup","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::Logs::LogGroup","aws:cdk:cloudformation:props":{"logGroupName":{"Fn::Join":["",["/aws/lambda/",{"Ref":"Evalb64e1fb89c894f7d8a342e2a1c5f6d7e3682A325"}]]},"retentionInDays":731}}}}}}},"StateMachine":{"id":"StateMachine","path":"evaluate-expression-nodejs22/StateMachine","constructInfo":{"fqn":"aws-cdk-lib.aws_stepfunctions.StateMachine","version":"0.0.0","metadata":[{"definition":"*"},{"addToRolePolicy":[{}]}]},"children":{"Role":{"id":"Role","path":"evaluate-expression-nodejs22/StateMachine/Role","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"}},{"addToPrincipalPolicy":[{}]},{"attachInlinePolicy":["*"]},{"attachInlinePolicy":["*"]}]},"children":{"ImportRole":{"id":"ImportRole","path":"evaluate-expression-nodejs22/StateMachine/Role/ImportRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"evaluate-expression-nodejs22/StateMachine/Role/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Role","aws:cdk:cloudformation:props":{"assumeRolePolicyDocument":{"Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"Service":"states.amazonaws.com"}}],"Version":"2012-10-17"}}}},"DefaultPolicy":{"id":"DefaultPolicy","path":"evaluate-expression-nodejs22/StateMachine/Role/DefaultPolicy","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Policy","version":"0.0.0","metadata":["*",{"attachToRole":["*"]},{"attachToRole":["*"]},{"addStatements":[{}]}]},"children":{"Resource":{"id":"Resource","path":"evaluate-expression-nodejs22/StateMachine/Role/DefaultPolicy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnPolicy","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Policy","aws:cdk:cloudformation:props":{"policyDocument":{"Statement":[{"Action":"lambda:InvokeFunction","Effect":"Allow","Resource":[{"Fn::GetAtt":["Evalb64e1fb89c894f7d8a342e2a1c5f6d7e3682A325","Arn"]},{"Fn::Join":["",[{"Fn::GetAtt":["Evalb64e1fb89c894f7d8a342e2a1c5f6d7e3682A325","Arn"]},":*"]]}]}],"Version":"2012-10-17"},"policyName":"StateMachineRoleDefaultPolicyDF1E6607","roles":[{"Ref":"StateMachineRoleB840431D"}]}}}}}}},"Resource":{"id":"Resource","path":"evaluate-expression-nodejs22/StateMachine/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_stepfunctions.CfnStateMachine","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::StepFunctions::StateMachine","aws:cdk:cloudformation:props":{"definitionString":{"Fn::Join":["",["{\"StartAt\":\"Task\",\"States\":{\"Task\":{\"End\":true,\"Type\":\"Task\",\"Resource\":\"",{"Fn::GetAtt":["Evalb64e1fb89c894f7d8a342e2a1c5f6d7e3682A325","Arn"]},"\",\"Parameters\":{\"expression\":\"$.a + $.b\",\"expressionAttributeValues\":{\"$.a.$\":\"$.a\",\"$.b.$\":\"$.b\"}}}}}"]]},"roleArn":{"Fn::GetAtt":["StateMachineRoleB840431D","Arn"]}}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"evaluate-expression-nodejs22/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"evaluate-expression-nodejs22/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"EvaluateExpressionNodejs22":{"id":"EvaluateExpressionNodejs22","path":"EvaluateExpressionNodejs22","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"EvaluateExpressionNodejs22/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"EvaluateExpressionNodejs22/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"EvaluateExpressionNodejs22/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"EvaluateExpressionNodejs22/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"EvaluateExpressionNodejs22/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.ts new file mode 100644 index 0000000000000..901eb3acc53f8 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/integ.evaluate-expression-nodejs22.ts @@ -0,0 +1,27 @@ +import { App, Stack, StackProps } from 'aws-cdk-lib'; +import * as integ from '@aws-cdk/integ-tests-alpha'; +import { Construct } from 'constructs'; +import * as sfn from 'aws-cdk-lib/aws-stepfunctions'; +import * as lambda from 'aws-cdk-lib/aws-lambda'; +import * as tasks from 'aws-cdk-lib/aws-stepfunctions-tasks'; + +class TestStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + const task = new tasks.EvaluateExpression(this, 'Task', { + expression: '$.a + $.b', + runtime: lambda.Runtime.NODEJS_22_X, + }); + + new sfn.StateMachine(this, 'StateMachine', { + definition: task, + }); + } +} + +const app = new App(); + +new integ.IntegTest(app, 'EvaluateExpressionNodejs22', { + testCases: [new TestStack(app, 'evaluate-expression-nodejs22')], +}); diff --git a/packages/@aws-cdk/aws-apprunner-alpha/lib/service.ts b/packages/@aws-cdk/aws-apprunner-alpha/lib/service.ts index 9fcdf6c146a9c..7c43fffa25ee6 100644 --- a/packages/@aws-cdk/aws-apprunner-alpha/lib/service.ts +++ b/packages/@aws-cdk/aws-apprunner-alpha/lib/service.ts @@ -761,7 +761,7 @@ export interface ServiceProps { * * @default - Use an AWS managed key */ - readonly kmsKey?: kms.IKey; + readonly kmsKey?: kms.IKeyRef; /** * The IP address type for your incoming public network configuration. @@ -1338,7 +1338,7 @@ export class Service extends cdk.Resource implements IService, iam.IGrantable { undefined, }, encryptionConfiguration: this.props.kmsKey ? { - kmsKey: this.props.kmsKey.keyArn, + kmsKey: this.props.kmsKey.keyRef.keyArn, } : undefined, autoScalingConfigurationArn: this.props.autoScalingConfiguration?.autoScalingConfigurationArn, networkConfiguration: { diff --git a/packages/@aws-cdk/aws-bedrock-alpha/bedrock/agents/api-schema.ts b/packages/@aws-cdk/aws-bedrock-alpha/bedrock/agents/api-schema.ts index b64d139327142..1ff418c0123c9 100644 --- a/packages/@aws-cdk/aws-bedrock-alpha/bedrock/agents/api-schema.ts +++ b/packages/@aws-cdk/aws-bedrock-alpha/bedrock/agents/api-schema.ts @@ -1,7 +1,7 @@ import { Construct } from 'constructs'; import * as s3_assets from 'aws-cdk-lib/aws-s3-assets'; import { CfnAgent } from 'aws-cdk-lib/aws-bedrock'; -import { IBucket, Location } from 'aws-cdk-lib/aws-s3'; +import { IBucketRef, Location } from 'aws-cdk-lib/aws-s3'; import { ActionGroupSchema } from './schema-base'; /** @@ -42,9 +42,9 @@ export abstract class ApiSchema extends ActionGroupSchema { * @param bucket - the bucket containing the local file containing the OpenAPI schema for the action group * @param objectKey - object key in the bucket */ - public static fromS3File(bucket: IBucket, objectKey: string): S3ApiSchema { + public static fromS3File(bucket: IBucketRef, objectKey: string): S3ApiSchema { return new S3ApiSchema({ - bucketName: bucket.bucketName, + bucketName: bucket.bucketRef.bucketName, objectKey: objectKey, }); } diff --git a/packages/@aws-cdk/aws-codestar-alpha/lib/github-repository.ts b/packages/@aws-cdk/aws-codestar-alpha/lib/github-repository.ts index 73d54342034a2..c9cdd7c5db22f 100644 --- a/packages/@aws-cdk/aws-codestar-alpha/lib/github-repository.ts +++ b/packages/@aws-cdk/aws-codestar-alpha/lib/github-repository.ts @@ -43,7 +43,7 @@ export interface GitHubRepositoryProps { /** * The name of the Amazon S3 bucket that contains the ZIP file with the content to be committed to the new repository */ - readonly contentsBucket: s3.IBucket; + readonly contentsBucket: s3.IBucketRef; /** * The S3 object key or file name for the ZIP file @@ -103,7 +103,7 @@ export class GitHubRepository extends cdk.Resource implements IGitHubRepository repositoryAccessToken: props.accessToken.unsafeUnwrap(), // Safe usage code: { s3: { - bucket: props.contentsBucket.bucketName, + bucket: props.contentsBucket.bucketRef.bucketName, key: props.contentsKey, objectVersion: props.contentsS3Version, }, diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts index 214a42ca84394..71869ba13649e 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts @@ -1,6 +1,6 @@ /* eslint no-bitwise: ["error", { "allow": ["~", "|", "<<", "&"] }] */ -import { ISubnet, SubnetType } from 'aws-cdk-lib/aws-ec2'; +import { ISubnet, ISubnetRef, SubnetType } from 'aws-cdk-lib/aws-ec2'; /** * The default names for every subnet type @@ -22,7 +22,7 @@ export function defaultSubnetName(type: SubnetType) { * * All subnet names look like NAME <> "Subnet" <> INDEX */ -export function subnetGroupNameFromConstructId(subnet: ISubnet) { +export function subnetGroupNameFromConstructId(subnet: ISubnetRef) { return subnet.node.id.replace(/Subnet\d+$/, ''); } diff --git a/packages/@aws-cdk/aws-eks-v2-alpha/lib/cluster.ts b/packages/@aws-cdk/aws-eks-v2-alpha/lib/cluster.ts index 58cc0331db0bf..7239953b77a08 100644 --- a/packages/@aws-cdk/aws-eks-v2-alpha/lib/cluster.ts +++ b/packages/@aws-cdk/aws-eks-v2-alpha/lib/cluster.ts @@ -371,7 +371,7 @@ export interface ClusterCommonOptions { * all etcd volumes used by Amazon EKS are encrypted at the disk-level * using AWS-Managed encryption keys. */ - readonly secretsEncryptionKey?: kms.IKey; + readonly secretsEncryptionKey?: kms.IKeyRef; /** * Specify which IP family is used to assign Kubernetes pod and service IP addresses. @@ -1214,7 +1214,7 @@ export class Cluster extends ClusterBase { ...(props.secretsEncryptionKey ? { encryptionConfig: [{ provider: { - keyArn: props.secretsEncryptionKey.keyArn, + keyArn: props.secretsEncryptionKey.keyRef.keyArn, }, resources: ['secrets'], }], diff --git a/packages/@aws-cdk/aws-glue-alpha/lib/security-configuration.ts b/packages/@aws-cdk/aws-glue-alpha/lib/security-configuration.ts index 392a3011ea801..c93e832b80744 100644 --- a/packages/@aws-cdk/aws-glue-alpha/lib/security-configuration.ts +++ b/packages/@aws-cdk/aws-glue-alpha/lib/security-configuration.ts @@ -76,7 +76,7 @@ export interface S3Encryption { * The KMS key to be used to encrypt the data. * @default no kms key if mode = S3_MANAGED. A key will be created if one is not provided and mode = KMS. */ - readonly kmsKey?: kms.IKey; + readonly kmsKey?: kms.IKeyRef; } /** @@ -92,7 +92,7 @@ export interface CloudWatchEncryption { * The KMS key to be used to encrypt the data. * @default A key will be created if one is not provided. */ - readonly kmsKey?: kms.IKey; + readonly kmsKey?: kms.IKeyRef; } /** @@ -108,7 +108,7 @@ export interface JobBookmarksEncryption { * The KMS key to be used to encrypt the data. * @default A key will be created if one is not provided. */ - readonly kmsKey?: kms.IKey; + readonly kmsKey?: kms.IKeyRef; } /** @@ -179,17 +179,17 @@ export class SecurityConfiguration extends cdk.Resource implements ISecurityConf /** * The KMS key used in CloudWatch encryption if it requires a kms key. */ - public readonly cloudWatchEncryptionKey?: kms.IKey; + public readonly cloudWatchEncryptionKey?: kms.IKeyRef; /** * The KMS key used in job bookmarks encryption if it requires a kms key. */ - public readonly jobBookmarksEncryptionKey?: kms.IKey; + public readonly jobBookmarksEncryptionKey?: kms.IKeyRef; /** * The KMS key used in S3 encryption if it requires a kms key. */ - public readonly s3EncryptionKey?: kms.IKey; + public readonly s3EncryptionKey?: kms.IKeyRef; constructor(scope: constructs.Construct, id: string, props: SecurityConfigurationProps = {}) { super(scope, id, { @@ -216,7 +216,7 @@ export class SecurityConfiguration extends cdk.Resource implements ISecurityConf this.cloudWatchEncryptionKey = props.cloudWatchEncryption.kmsKey || autoCreatedKmsKey; cloudWatchEncryption = { cloudWatchEncryptionMode: props.cloudWatchEncryption.mode, - kmsKeyArn: this.cloudWatchEncryptionKey?.keyArn, + kmsKeyArn: this.cloudWatchEncryptionKey?.keyRef.keyArn, }; } @@ -225,7 +225,7 @@ export class SecurityConfiguration extends cdk.Resource implements ISecurityConf this.jobBookmarksEncryptionKey = props.jobBookmarksEncryption.kmsKey || autoCreatedKmsKey; jobBookmarksEncryption = { jobBookmarksEncryptionMode: props.jobBookmarksEncryption.mode, - kmsKeyArn: this.jobBookmarksEncryptionKey?.keyArn, + kmsKeyArn: this.jobBookmarksEncryptionKey?.keyRef.keyArn, }; } @@ -237,7 +237,7 @@ export class SecurityConfiguration extends cdk.Resource implements ISecurityConf // NOTE: CloudFormations errors out if array is of length > 1. That's why the props don't expose an array s3Encryptions = [{ s3EncryptionMode: props.s3Encryption.mode, - kmsKeyArn: this.s3EncryptionKey?.keyArn, + kmsKeyArn: this.s3EncryptionKey?.keyRef.keyArn, }]; } diff --git a/packages/@aws-cdk/aws-glue-alpha/test/security-configuration.test.ts b/packages/@aws-cdk/aws-glue-alpha/test/security-configuration.test.ts index 8793c3e1a9404..15fc41b0bcc6d 100644 --- a/packages/@aws-cdk/aws-glue-alpha/test/security-configuration.test.ts +++ b/packages/@aws-cdk/aws-glue-alpha/test/security-configuration.test.ts @@ -22,7 +22,7 @@ test('a security configuration with encryption configuration requiring kms key a }, }); - expect(securityConfiguration.cloudWatchEncryptionKey?.keyArn).toEqual(keyArn); + expect(securityConfiguration.cloudWatchEncryptionKey?.keyRef.keyArn).toEqual(keyArn); expect(securityConfiguration.jobBookmarksEncryptionKey).toBeUndefined(); expect(securityConfiguration.s3EncryptionKey).toBeUndefined(); @@ -57,7 +57,7 @@ test('a security configuration with an encryption configuration requiring kms ke EncryptionConfiguration: { CloudWatchEncryption: { CloudWatchEncryptionMode: 'SSE-KMS', - KmsKeyArn: stack.resolve(securityConfiguration.cloudWatchEncryptionKey?.keyArn), + KmsKeyArn: stack.resolve(securityConfiguration.cloudWatchEncryptionKey?.keyRef.keyArn), }, }, }); @@ -82,7 +82,7 @@ test('a security configuration with all encryption configs and mixed kms key inp }); expect(securityConfiguration.cloudWatchEncryptionKey).toBeDefined(); - expect(securityConfiguration.jobBookmarksEncryptionKey?.keyArn).toEqual(keyArn); + expect(securityConfiguration.jobBookmarksEncryptionKey?.keyRef.keyArn).toEqual(keyArn); expect(securityConfiguration.s3EncryptionKey).toBeUndefined(); Template.fromStack(stack).resourceCountIs('AWS::KMS::Key', 1); @@ -93,7 +93,7 @@ test('a security configuration with all encryption configs and mixed kms key inp CloudWatchEncryption: { CloudWatchEncryptionMode: 'SSE-KMS', // auto-created kms key - KmsKeyArn: stack.resolve(securityConfiguration.cloudWatchEncryptionKey?.keyArn), + KmsKeyArn: stack.resolve(securityConfiguration.cloudWatchEncryptionKey?.keyRef.keyArn), }, JobBookmarksEncryption: { JobBookmarksEncryptionMode: 'CSE-KMS', diff --git a/packages/@aws-cdk/aws-ivs-alpha/lib/recording-configuration.ts b/packages/@aws-cdk/aws-ivs-alpha/lib/recording-configuration.ts index 2363f5f70e3e5..2ca929aa6edfd 100644 --- a/packages/@aws-cdk/aws-ivs-alpha/lib/recording-configuration.ts +++ b/packages/@aws-cdk/aws-ivs-alpha/lib/recording-configuration.ts @@ -1,5 +1,5 @@ import { CfnRecordingConfiguration } from 'aws-cdk-lib/aws-ivs'; -import { IBucket } from 'aws-cdk-lib/aws-s3'; +import { IBucketRef } from 'aws-cdk-lib/aws-s3'; import { Duration, Fn, IResource, Resource, Stack, Token } from 'aws-cdk-lib/core'; import { Construct } from 'constructs'; import { RenditionConfiguration } from './rendition-configuration'; @@ -14,7 +14,7 @@ export interface RecordingConfigurationProps { /** * S3 bucket where recorded videos will be stored. */ - readonly bucket: IBucket; + readonly bucket: IBucketRef; /** * The name of the Recording configuration. @@ -146,7 +146,7 @@ export class RecordingConfiguration extends Resource implements IRecordingConfig const resource = new CfnRecordingConfiguration(this, 'Resource', { destinationConfiguration: { s3: { - bucketName: this.props.bucket.bucketName, + bucketName: this.props.bucket.bucketRef.bucketName, }, }, name: this.props.recordingConfigurationName, diff --git a/packages/@aws-cdk/aws-location-alpha/lib/geofence-collection.ts b/packages/@aws-cdk/aws-location-alpha/lib/geofence-collection.ts index 022c8fc10d527..da3382694ce9b 100644 --- a/packages/@aws-cdk/aws-location-alpha/lib/geofence-collection.ts +++ b/packages/@aws-cdk/aws-location-alpha/lib/geofence-collection.ts @@ -53,7 +53,7 @@ export interface GeofenceCollectionProps { * @default - Use an AWS managed key * @see https://docs.aws.amazon.com/location/latest/developerguide/encryption-at-rest.html */ - readonly kmsKey?: kms.IKey; + readonly kmsKey?: kms.IKeyRef; } /** @@ -141,7 +141,7 @@ export class GeofenceCollection extends Resource implements IGeofenceCollection const geofenceCollection = new CfnGeofenceCollection(this, 'Resource', { collectionName: this.physicalName, description: props.description, - kmsKeyId: props.kmsKey?.keyArn, + kmsKeyId: props.kmsKey?.keyRef.keyArn, }); this.geofenceCollectionName = geofenceCollection.ref; diff --git a/packages/@aws-cdk/aws-location-alpha/lib/tracker.ts b/packages/@aws-cdk/aws-location-alpha/lib/tracker.ts index 9219dd678eec5..494da529f92ff 100644 --- a/packages/@aws-cdk/aws-location-alpha/lib/tracker.ts +++ b/packages/@aws-cdk/aws-location-alpha/lib/tracker.ts @@ -62,7 +62,7 @@ export interface TrackerProps { * * @default - Use an AWS managed key */ - readonly kmsKey?: kms.IKey; + readonly kmsKey?: kms.IKeyRef; /** * Whether to opt-in to the Bounding Polygon Queries feature with customer managed key @@ -210,7 +210,7 @@ export class Tracker extends Resource implements ITracker { description: props.description, eventBridgeEnabled: props.eventBridgeEnabled, kmsKeyEnableGeospatialQueries: props.kmsKeyEnableGeospatialQueries, - kmsKeyId: props.kmsKey?.keyArn, + kmsKeyId: props.kmsKey?.keyRef.keyArn, positionFiltering: props.positionFiltering, }); diff --git a/packages/@aws-cdk/aws-msk-alpha/lib/cluster.ts b/packages/@aws-cdk/aws-msk-alpha/lib/cluster.ts index 113acacc32010..bdfd7d2693dc7 100644 --- a/packages/@aws-cdk/aws-msk-alpha/lib/cluster.ts +++ b/packages/@aws-cdk/aws-msk-alpha/lib/cluster.ts @@ -181,7 +181,7 @@ export interface EbsStorageInfo { * * @default Uses AWS managed CMK (aws/kafka) */ - readonly encryptionKey?: kms.IKey; + readonly encryptionKey?: kms.IKeyRef; } /** @@ -381,7 +381,7 @@ export interface SaslAuthProps { * * @default - CMK will be created with alias msk/{clusterName}/sasl/scram */ - readonly key?: kms.IKey; + readonly key?: kms.IKeyRef; } /** @@ -522,7 +522,7 @@ export class Cluster extends ClusterBase { const encryptionAtRest = props.ebsStorageInfo?.encryptionKey ? { dataVolumeKmsKeyId: - props.ebsStorageInfo.encryptionKey.keyId, + props.ebsStorageInfo.encryptionKey.keyRef.keyId, } : undefined; // MSK will create the managed key diff --git a/packages/@aws-cdk/aws-neptune-alpha/lib/cluster.ts b/packages/@aws-cdk/aws-neptune-alpha/lib/cluster.ts index c66b9c8bc2dd1..b6886af2dda54 100644 --- a/packages/@aws-cdk/aws-neptune-alpha/lib/cluster.ts +++ b/packages/@aws-cdk/aws-neptune-alpha/lib/cluster.ts @@ -134,6 +134,10 @@ export class EngineVersion { * Neptune engine version 1.4.5.0 */ public static readonly V1_4_5_0 = new EngineVersion('1.4.5.0'); + /** + * Neptune engine version 1.4.5.1 + */ + public static readonly V1_4_5_1 = new EngineVersion('1.4.5.1'); /** * Constructor for specifying a custom engine version @@ -209,7 +213,7 @@ export interface DatabaseClusterProps { * * @default - default master key. */ - readonly kmsKey?: kms.IKey; + readonly kmsKey?: kms.IKeyRef; /** * Whether to enable storage encryption @@ -683,7 +687,7 @@ export class DatabaseCluster extends DatabaseClusterBase implements IDatabaseClu preferredBackupWindow: props.preferredBackupWindow, preferredMaintenanceWindow: props.preferredMaintenanceWindow, // Encryption - kmsKeyId: props.kmsKey?.keyArn, + kmsKeyId: props.kmsKey?.keyRef.keyArn, // CloudWatch Logs exports enableCloudwatchLogsExports: props.cloudwatchLogsExports?.map(logType => logType.value), storageEncrypted, diff --git a/packages/@aws-cdk/aws-redshift-alpha/lib/cluster.ts b/packages/@aws-cdk/aws-redshift-alpha/lib/cluster.ts index 6933c51ceabcd..7f3c389273f61 100644 --- a/packages/@aws-cdk/aws-redshift-alpha/lib/cluster.ts +++ b/packages/@aws-cdk/aws-redshift-alpha/lib/cluster.ts @@ -313,7 +313,7 @@ export interface ClusterProps { * * @default - AWS-managed key, if encryption at rest is enabled */ - readonly encryptionKey?: kms.IKey; + readonly encryptionKey?: kms.IKeyRef; /** * A preferred maintenance window day/time range. Should be specified as a range ddd:hh24:mi-ddd:hh24:mi (24H Clock UTC). @@ -692,7 +692,7 @@ export class Cluster extends ClusterBase { dbName: props.defaultDatabaseName || 'default_db', publiclyAccessible: props.publiclyAccessible || false, // Encryption - kmsKeyId: props.encryptionKey?.keyId, + kmsKeyId: props.encryptionKey?.keyRef.keyId, encrypted: props.encrypted ?? true, classic: props.classicResizing, elasticIp: props.elasticIp, diff --git a/packages/@aws-cdk/aws-s3objectlambda-alpha/lib/access-point.ts b/packages/@aws-cdk/aws-s3objectlambda-alpha/lib/access-point.ts index 314cdfc29cfeb..a257406238c8c 100644 --- a/packages/@aws-cdk/aws-s3objectlambda-alpha/lib/access-point.ts +++ b/packages/@aws-cdk/aws-s3objectlambda-alpha/lib/access-point.ts @@ -51,7 +51,7 @@ export interface AccessPointProps { /** * The bucket to which this access point belongs. */ - readonly bucket: s3.IBucket; + readonly bucket: s3.IBucketRef; /** * The Lambda function used to transform objects. @@ -224,7 +224,7 @@ export class AccessPoint extends AccessPointBase { } const supporting = new s3.CfnAccessPoint(this, 'SupportingAccessPoint', { - bucket: props.bucket.bucketName, + bucket: props.bucket.bucketRef.bucketName, }); const allowedFeatures = []; diff --git a/packages/@aws-cdk/aws-sagemaker-alpha/lib/endpoint-config.ts b/packages/@aws-cdk/aws-sagemaker-alpha/lib/endpoint-config.ts index b4c9e02521324..cd7c0c1bcfba1 100644 --- a/packages/@aws-cdk/aws-sagemaker-alpha/lib/endpoint-config.ts +++ b/packages/@aws-cdk/aws-sagemaker-alpha/lib/endpoint-config.ts @@ -136,7 +136,7 @@ export interface EndpointConfigProps { * * @default - none */ - readonly encryptionKey?: kms.IKey; + readonly encryptionKey?: kms.IKeyRef; /** * A list of instance production variants. You can always add more variants later by calling @@ -219,7 +219,7 @@ export class EndpointConfig extends cdk.Resource implements IEndpointConfig { // create the endpoint configuration resource const endpointConfig = new CfnEndpointConfig(this, 'EndpointConfig', { - kmsKeyId: (props.encryptionKey) ? props.encryptionKey.keyArn : undefined, + kmsKeyId: (props.encryptionKey) ? props.encryptionKey.keyRef.keyArn : undefined, endpointConfigName: this.physicalName, productionVariants: cdk.Lazy.any({ produce: () => this.renderInstanceProductionVariants() }), }); diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/access-log.ts b/packages/aws-cdk-lib/aws-apigateway/lib/access-log.ts index ee704ec56d18a..70fd1ad609a62 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/access-log.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/access-log.ts @@ -1,4 +1,4 @@ -import { IStage } from './stage'; +import { IStageRef } from './apigateway.generated'; import * as firehose from '../../aws-kinesisfirehose'; import { ILogGroup } from '../../aws-logs'; import { ValidationError } from '../../core/lib/errors'; @@ -10,7 +10,7 @@ export interface IAccessLogDestination { /** * Binds this destination to the RestApi Stage. */ - bind(stage: IStage): AccessLogDestinationConfig; + bind(stage: IStageRef): AccessLogDestinationConfig; } /** @@ -33,7 +33,7 @@ export class LogGroupLogDestination implements IAccessLogDestination { /** * Binds this destination to the CloudWatch Logs. */ - public bind(_stage: IStage): AccessLogDestinationConfig { + public bind(_stage: IStageRef): AccessLogDestinationConfig { return { destinationArn: this.logGroup.logGroupArn, }; @@ -50,7 +50,7 @@ export class FirehoseLogDestination implements IAccessLogDestination { /** * Binds this destination to the Firehose delivery stream. */ - public bind(stage: IStage): AccessLogDestinationConfig { + public bind(stage: IStageRef): AccessLogDestinationConfig { if (!this.stream.deliveryStreamName?.startsWith('amazon-apigateway-')) { throw new ValidationError(`Firehose delivery stream name for access log destination must begin with 'amazon-apigateway-', got '${this.stream.deliveryStreamName}'`, stage); } diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/api-definition.ts b/packages/aws-cdk-lib/aws-apigateway/lib/api-definition.ts index 291e4864fc5a4..d00ffd9101302 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/api-definition.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/api-definition.ts @@ -1,6 +1,5 @@ import { Construct, Node } from 'constructs'; -import { CfnRestApi } from './apigateway.generated'; -import { IRestApi } from './restapi'; +import { CfnRestApi, IRestApiRef } from './apigateway.generated'; import * as s3 from '../../aws-s3'; import * as s3_assets from '../../aws-s3-assets'; import { UnscopedValidationError, ValidationError } from '../../core/lib/errors'; @@ -89,7 +88,7 @@ export abstract class ApiDefinition { * Definition to bind to it. Specifically it's required to allow assets to add * metadata for tooling like SAM CLI to be able to find their origins. */ - public bindAfterCreate(_scope: Construct, _restApi: IRestApi) { + public bindAfterCreate(_scope: Construct, _restApi: IRestApiRef) { return; } } @@ -134,14 +133,14 @@ export interface ApiDefinitionConfig { export class S3ApiDefinition extends ApiDefinition { private bucketName: string; - constructor(bucket: s3.IBucket, private key: string, private objectVersion?: string) { + constructor(bucket: s3.IBucketRef, private key: string, private objectVersion?: string) { super(); - if (!bucket.bucketName) { + if (!bucket.bucketRef.bucketName) { throw new ValidationError('bucketName is undefined for the provided bucket', bucket); } - this.bucketName = bucket.bucketName; + this.bucketName = bucket.bucketRef.bucketName; } public bind(_scope: Construct): ApiDefinitionConfig { @@ -209,7 +208,7 @@ export class AssetApiDefinition extends ApiDefinition { }; } - public bindAfterCreate(scope: Construct, restApi: IRestApi) { + public bindAfterCreate(scope: Construct, restApi: IRestApiRef) { if (!scope.node.tryGetContext(cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT)) { return; // not enabled } diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/api-key.ts b/packages/aws-cdk-lib/aws-apigateway/lib/api-key.ts index 476fbfc88e3ec..06155af14da80 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/api-key.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/api-key.ts @@ -1,5 +1,5 @@ import { Construct } from 'constructs'; -import { ApiKeyReference, CfnApiKey, IApiKeyRef } from './apigateway.generated'; +import { ApiKeyReference, CfnApiKey, IApiKeyRef, IStageRef } from './apigateway.generated'; import { ResourceOptions } from './resource'; import { IRestApi } from './restapi'; import { IStage } from './stage'; @@ -207,7 +207,7 @@ export class ApiKey extends ApiKeyBase { }); } - private renderStageKeys(resources?: IRestApi[], stages?: IStage[]): CfnApiKey.StageKeyProperty[] | undefined { + private renderStageKeys(resources?: IRestApi[], stages?: IStageRef[]): CfnApiKey.StageKeyProperty[] | undefined { if (!resources && !stages) { return undefined; } @@ -228,7 +228,7 @@ export class ApiKey extends ApiKeyBase { return { restApiId, stageName }; }) : stages ? stages.map((stage => { - return { restApiId: stage.restApi.restApiId, stageName: stage.stageName }; + return { restApiId: stage.stageRef.restApiId, stageName: stage.stageRef.stageName }; })) : undefined; } } diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/base-path-mapping.ts b/packages/aws-cdk-lib/aws-apigateway/lib/base-path-mapping.ts index ce7b047b2f7a9..f1138d6cfef55 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/base-path-mapping.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/base-path-mapping.ts @@ -1,7 +1,6 @@ import { Construct } from 'constructs'; -import { CfnBasePathMapping } from './apigateway.generated'; -import { IDomainName } from './domain-name'; -import { IRestApi, RestApiBase } from './restapi'; +import { CfnBasePathMapping, IDomainNameRef, IRestApiRef } from './apigateway.generated'; +import { RestApiBase } from './restapi'; import { Stage } from './stage'; import { Resource, Token } from '../../core'; import { ValidationError } from '../../core/lib/errors'; @@ -39,12 +38,12 @@ export interface BasePathMappingProps extends BasePathMappingOptions { /** * The DomainName to associate with this base path mapping. */ - readonly domainName: IDomainName; + readonly domainName: IDomainNameRef; /** * The RestApi resource to target. */ - readonly restApi: IRestApi; + readonly restApi: IRestApiRef; } /** @@ -87,8 +86,8 @@ export class BasePathMapping extends Resource { new CfnBasePathMapping(this, 'Resource', { basePath: props.basePath, - domainName: props.domainName.domainName, - restApiId: props.restApi.restApiId, + domainName: props.domainName.domainNameRef.domainName, + restApiId: props.restApi.restApiRef.restApiId, stage: stage?.stageName, }); } diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/deployment.ts b/packages/aws-cdk-lib/aws-apigateway/lib/deployment.ts index e00ab6675b896..2b7402a5b9a42 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/deployment.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/deployment.ts @@ -1,6 +1,6 @@ import { ArtifactMetadataEntryType } from '@aws-cdk/cloud-assembly-schema'; import { Construct } from 'constructs'; -import { CfnDeployment } from './apigateway.generated'; +import { CfnDeployment, IRestApiRef } from './apigateway.generated'; import { Method } from './method'; import { IRestApi, RestApi, SpecRestApi, RestApiBase } from './restapi'; import { Lazy, RemovalPolicy, Resource, CfnResource } from '../../core'; @@ -153,19 +153,19 @@ export class Deployment extends Resource { interface LatestDeploymentResourceProps { readonly description?: string; - readonly restApi: IRestApi; + readonly restApi: IRestApiRef; readonly stageName?: string; } class LatestDeploymentResource extends CfnDeployment { private readonly hashComponents = new Array(); private readonly originalLogicalId: string; - private readonly api: IRestApi; + private readonly api: IRestApiRef; constructor(scope: Construct, id: string, props: LatestDeploymentResourceProps) { super(scope, id, { description: props.description, - restApiId: props.restApi.restApiId, + restApiId: props.restApi.restApiRef.restApiId, stageName: props.stageName, }); diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/domain-name.ts b/packages/aws-cdk-lib/aws-apigateway/lib/domain-name.ts index 947aa702669ee..5e09dcd25f76e 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/domain-name.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/domain-name.ts @@ -1,8 +1,7 @@ import { Construct } from 'constructs'; -import { CfnDomainName, DomainNameReference, IDomainNameRef } from './apigateway.generated'; +import { CfnDomainName, DomainNameReference, IDomainNameRef, IRestApiRef, IStageRef } from './apigateway.generated'; import { BasePathMapping, BasePathMappingOptions } from './base-path-mapping'; import { EndpointType, IRestApi } from './restapi'; -import { IStage } from './stage'; import * as apigwv2 from '../../aws-apigatewayv2'; import * as acm from '../../aws-certificatemanager'; import { IBucket } from '../../aws-s3'; @@ -228,7 +227,7 @@ export class DomainName extends Resource implements IDomainName { * @param options Options for mapping to base path with or without a stage */ @MethodMetadata() - public addBasePathMapping(targetApi: IRestApi, options: BasePathMappingOptions = {}): BasePathMapping { + public addBasePathMapping(targetApi: IRestApiRef, options: BasePathMappingOptions = {}): BasePathMapping { if (this.basePaths.has(options.basePath)) { throw new ValidationError(`DomainName ${this.node.id} already has a mapping for path ${options.basePath}`, this); } @@ -258,7 +257,7 @@ export class DomainName extends Resource implements IDomainName { * @param options Options for mapping to a stage */ @MethodMetadata() - public addApiMapping(targetStage: IStage, options: ApiMappingOptions = {}): void { + public addApiMapping(targetStage: IStageRef, options: ApiMappingOptions = {}): void { if (this.basePaths.has(options.basePath)) { throw new ValidationError(`DomainName ${this.node.id} already has a mapping for path ${options.basePath}`, this); } @@ -266,8 +265,8 @@ export class DomainName extends Resource implements IDomainName { this.basePaths.add(options.basePath); const id = `Map:${options.basePath ?? 'none'}=>${Names.nodeUniqueId(targetStage.node)}`; new apigwv2.CfnApiMapping(this, id, { - apiId: targetStage.restApi.restApiId, - stage: targetStage.stageName, + apiId: targetStage.stageRef.restApiId, + stage: targetStage.stageRef.stageName, domainName: this.domainName, apiMappingKey: options.basePath, }); diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/method.ts b/packages/aws-cdk-lib/aws-apigateway/lib/method.ts index 62ecedfac079e..16b8c227f6242 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/method.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/method.ts @@ -1,6 +1,6 @@ import { Construct } from 'constructs'; import { ApiGatewayMetrics } from './apigateway-canned-metrics.generated'; -import { CfnMethod, CfnMethodProps } from './apigateway.generated'; +import { CfnMethod, CfnMethodProps, IStageRef } from './apigateway.generated'; import { Authorizer, IAuthorizer } from './authorizer'; import { Integration, IntegrationConfig } from './integration'; import { MockIntegration } from './integrations/mock'; @@ -9,7 +9,6 @@ import { IModel } from './model'; import { IRequestValidator, RequestValidatorOptions } from './requestvalidator'; import { IResource } from './resource'; import { IRestApi, RestApi, RestApiBase } from './restapi'; -import { IStage } from './stage'; import { validateHttpMethod } from './util'; import * as cloudwatch from '../../aws-cloudwatch'; import * as iam from '../../aws-iam'; @@ -439,11 +438,11 @@ export class Method extends Resource { * Returns the given named metric for this API method */ @MethodMetadata() - public metric(metricName: string, stage: IStage, props?: cloudwatch.MetricOptions): cloudwatch.Metric { + public metric(metricName: string, stage: IStageRef, props?: cloudwatch.MetricOptions): cloudwatch.Metric { return new cloudwatch.Metric({ namespace: 'AWS/ApiGateway', metricName, - dimensionsMap: { ApiName: this.api.restApiName, Method: this.httpMethod, Resource: this.resource.path, Stage: stage.stageName }, + dimensionsMap: { ApiName: this.api.restApiName, Method: this.httpMethod, Resource: this.resource.path, Stage: stage.stageRef.stageName }, ...props, }).attachTo(this); } @@ -454,7 +453,7 @@ export class Method extends Resource { * @default - sum over 5 minutes */ @MethodMetadata() - public metricClientError(stage: IStage, props?: cloudwatch.MetricOptions): cloudwatch.Metric { + public metricClientError(stage: IStageRef, props?: cloudwatch.MetricOptions): cloudwatch.Metric { return this.cannedMetric(ApiGatewayMetrics._4XxErrorSum, stage, props); } @@ -464,7 +463,7 @@ export class Method extends Resource { * @default - sum over 5 minutes */ @MethodMetadata() - public metricServerError(stage: IStage, props?: cloudwatch.MetricOptions): cloudwatch.Metric { + public metricServerError(stage: IStageRef, props?: cloudwatch.MetricOptions): cloudwatch.Metric { return this.cannedMetric(ApiGatewayMetrics._5XxErrorSum, stage, props); } @@ -474,7 +473,7 @@ export class Method extends Resource { * @default - sum over 5 minutes */ @MethodMetadata() - public metricCacheHitCount(stage: IStage, props?: cloudwatch.MetricOptions): cloudwatch.Metric { + public metricCacheHitCount(stage: IStageRef, props?: cloudwatch.MetricOptions): cloudwatch.Metric { return this.cannedMetric(ApiGatewayMetrics.cacheHitCountSum, stage, props); } @@ -485,7 +484,7 @@ export class Method extends Resource { * @default - sum over 5 minutes */ @MethodMetadata() - public metricCacheMissCount(stage: IStage, props?: cloudwatch.MetricOptions): cloudwatch.Metric { + public metricCacheMissCount(stage: IStageRef, props?: cloudwatch.MetricOptions): cloudwatch.Metric { return this.cannedMetric(ApiGatewayMetrics.cacheMissCountSum, stage, props); } @@ -495,7 +494,7 @@ export class Method extends Resource { * @default - sample count over 5 minutes */ @MethodMetadata() - public metricCount(stage: IStage, props?: cloudwatch.MetricOptions): cloudwatch.Metric { + public metricCount(stage: IStageRef, props?: cloudwatch.MetricOptions): cloudwatch.Metric { return this.cannedMetric(ApiGatewayMetrics.countSum, stage, { statistic: 'SampleCount', ...props, @@ -509,7 +508,7 @@ export class Method extends Resource { * @default - average over 5 minutes. */ @MethodMetadata() - public metricIntegrationLatency(stage: IStage, props?: cloudwatch.MetricOptions): cloudwatch.Metric { + public metricIntegrationLatency(stage: IStageRef, props?: cloudwatch.MetricOptions): cloudwatch.Metric { return this.cannedMetric(ApiGatewayMetrics.integrationLatencyAverage, stage, props); } @@ -521,7 +520,7 @@ export class Method extends Resource { * @default - average over 5 minutes. */ @MethodMetadata() - public metricLatency(stage: IStage, props?: cloudwatch.MetricOptions): cloudwatch.Metric { + public metricLatency(stage: IStageRef, props?: cloudwatch.MetricOptions): cloudwatch.Metric { return this.cannedMetric(ApiGatewayMetrics.latencyAverage, stage, props); } @@ -544,9 +543,9 @@ export class Method extends Resource { Method: string; Resource: string; Stage: string; - }) => cloudwatch.MetricProps, stage: IStage, props?: cloudwatch.MetricOptions) { + }) => cloudwatch.MetricProps, stage: IStageRef, props?: cloudwatch.MetricOptions) { return new cloudwatch.Metric({ - ...fn({ ApiName: this.api.restApiName, Method: this.httpMethod, Resource: this.resource.path, Stage: stage.stageName }), + ...fn({ ApiName: this.api.restApiName, Method: this.httpMethod, Resource: this.resource.path, Stage: stage.stageRef.stageName }), ...props, }).attachTo(this); } diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/restapi.ts b/packages/aws-cdk-lib/aws-apigateway/lib/restapi.ts index 24e34c51dc85a..9d5d86fca66df 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/restapi.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/restapi.ts @@ -404,7 +404,7 @@ export abstract class RestApiBase extends Resource implements IRestApi, iam.IRes private _latestDeployment?: Deployment; private _domainName?: DomainName; - private _allowedVpcEndpoints: Set = new Set(); + private _allowedVpcEndpoints: Set = new Set(); protected resourcePolicy?: iam.PolicyDocument; protected cloudWatchAccount?: CfnAccount; @@ -506,7 +506,7 @@ export abstract class RestApiBase extends Resource implements IRestApi, iam.IRes const endpoints = Lazy.list({ produce: () => { - return Array.from(this._allowedVpcEndpoints).map(endpoint => endpoint.vpcEndpointId); + return Array.from(this._allowedVpcEndpoints).map(endpoint => endpoint.vpcEndpointRef.vpcEndpointId); }, }); diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/usage-plan.ts b/packages/aws-cdk-lib/aws-apigateway/lib/usage-plan.ts index 90ed23e22dee8..0405704063f44 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/usage-plan.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/usage-plan.ts @@ -1,6 +1,6 @@ import { Construct } from 'constructs'; import { IApiKey } from './api-key'; -import { CfnUsagePlan, CfnUsagePlanKey, IUsagePlanRef, UsagePlanReference } from './apigateway.generated'; +import { CfnUsagePlan, CfnUsagePlanKey, IApiKeyRef, IUsagePlanRef, UsagePlanReference } from './apigateway.generated'; import { Method } from './method'; import { IRestApi } from './restapi'; import { Stage } from './stage'; @@ -174,7 +174,7 @@ export interface IUsagePlan extends IResource, IUsagePlanRef { * @param apiKey the api key to associate with this usage plan * @param options options that control the behaviour of this method */ - addApiKey(apiKey: IApiKey, options?: AddApiKeyOptions): void; + addApiKey(apiKey: IApiKeyRef, options?: AddApiKeyOptions): void; } @@ -191,7 +191,7 @@ abstract class UsagePlanBase extends Resource implements IUsagePlan { * @param apiKey the api key to associate with this usage plan * @param options options that control the behaviour of this method */ - public addApiKey(apiKey: IApiKey, options?: AddApiKeyOptions): void { + public addApiKey(apiKey: IApiKeyRef, options?: AddApiKeyOptions): void { let id: string; const prefix = 'UsagePlanKeyResource'; @@ -203,7 +203,7 @@ abstract class UsagePlanBase extends Resource implements IUsagePlan { } const resource = new CfnUsagePlanKey(this, id, { - keyId: apiKey.keyId, + keyId: apiKey.apiKeyRef.apiKeyId, keyType: UsagePlanKeyType.API_KEY, usagePlanId: this.usagePlanId, }); diff --git a/packages/aws-cdk-lib/aws-apigatewayv2/lib/http/integration.ts b/packages/aws-cdk-lib/aws-apigatewayv2/lib/http/integration.ts index 7759e642a9250..6a635ee2ed6b4 100644 --- a/packages/aws-cdk-lib/aws-apigatewayv2/lib/http/integration.ts +++ b/packages/aws-cdk-lib/aws-apigatewayv2/lib/http/integration.ts @@ -2,7 +2,7 @@ import { Construct } from 'constructs'; import { IHttpApi } from './api'; import { HttpMethod, IHttpRoute } from './route'; import { CfnIntegration } from '.././index'; -import { IRole } from '../../../aws-iam'; +import { IRoleRef } from '../../../aws-iam'; import { Aws, Duration, Resource } from '../../../core'; import { ValidationError } from '../../../core/lib/errors'; import { addConstructMetadata } from '../../../core/lib/metadata-resource'; @@ -100,8 +100,8 @@ export abstract class IntegrationCredentials { /** * Use the specified role for integration requests */ - public static fromRole(role: IRole): IntegrationCredentials { - return { credentialsArn: role.roleArn }; + public static fromRole(role: IRoleRef): IntegrationCredentials { + return { credentialsArn: role.roleRef.roleArn }; } /** Use the calling user's identity to call the integration */ diff --git a/packages/aws-cdk-lib/aws-apigatewayv2/lib/http/vpc-link.ts b/packages/aws-cdk-lib/aws-apigatewayv2/lib/http/vpc-link.ts index 40c5db6e13779..5ab6ea0018aa6 100644 --- a/packages/aws-cdk-lib/aws-apigatewayv2/lib/http/vpc-link.ts +++ b/packages/aws-cdk-lib/aws-apigatewayv2/lib/http/vpc-link.ts @@ -48,7 +48,7 @@ export interface VpcLinkProps { * * @default - no security groups. Use `addSecurityGroups` to add security groups */ - readonly securityGroups?: ec2.ISecurityGroup[]; + readonly securityGroups?: ec2.ISecurityGroupRef[]; } /** @@ -89,8 +89,8 @@ export class VpcLink extends Resource implements IVpcLink { public readonly vpcLinkId: string; public readonly vpc: ec2.IVpc; - private readonly subnets = new Array(); - private readonly securityGroups = new Array(); + private readonly subnets = new Array(); + private readonly securityGroups = new Array(); constructor(scope: Construct, id: string, props: VpcLinkProps) { super(scope, id); @@ -118,7 +118,7 @@ export class VpcLink extends Resource implements IVpcLink { * Adds the provided subnets to the vpc link */ @MethodMetadata() - public addSubnets(...subnets: ec2.ISubnet[]) { + public addSubnets(...subnets: ec2.ISubnetRef[]) { this.subnets.push(...subnets); } @@ -126,15 +126,15 @@ export class VpcLink extends Resource implements IVpcLink { * Adds the provided security groups to the vpc link */ @MethodMetadata() - public addSecurityGroups(...groups: ec2.ISecurityGroup[]) { + public addSecurityGroups(...groups: ec2.ISecurityGroupRef[]) { this.securityGroups.push(...groups); } private renderSubnets() { - return this.subnets.map(subnet => subnet.subnetId); + return this.subnets.map(subnet => subnet.subnetRef.subnetId); } private renderSecurityGroups() { - return this.securityGroups.map(sg => sg.securityGroupId); + return this.securityGroups.map(sg => sg.securityGroupRef.securityGroupId); } } diff --git a/packages/aws-cdk-lib/aws-appconfig/lib/configuration.ts b/packages/aws-cdk-lib/aws-appconfig/lib/configuration.ts index aad418863b13e..38ff271162d9a 100644 --- a/packages/aws-cdk-lib/aws-appconfig/lib/configuration.ts +++ b/packages/aws-cdk-lib/aws-appconfig/lib/configuration.ts @@ -14,7 +14,7 @@ import * as lambda from '../../aws-lambda'; import * as s3 from '../../aws-s3'; import * as sm from '../../aws-secretsmanager'; import * as ssm from '../../aws-ssm'; -import { PhysicalName, Stack, ArnFormat, Names, RemovalPolicy } from '../../core'; +import { PhysicalName, Stack, ArnFormat, Names, RemovalPolicy, ValidationError } from '../../core'; import * as mimeTypes from 'mime-types'; import { DeletionProtectionCheck } from './util'; @@ -403,7 +403,7 @@ export interface HostedConfigurationProps extends ConfigurationProps { * * @default None */ - readonly kmsKey?: kms.IKey; + readonly kmsKey?: kms.IKeyRef; } /** @@ -416,7 +416,15 @@ export class HostedConfiguration extends ConfigurationBase { public readonly content: string; /** - * The content type of the hosted configuration. + * The configuration content type, specified as a standard MIME type. + * Supported examples include: + * - `text/plain` + * - `application/json` + * - `application/octet-stream` + * - `application/x-yaml` + * + * For an up-to-date list of valid MIME types, see: + * https://www.iana.org/assignments/media-types/media-types.xhtml */ public readonly contentType?: string; @@ -464,7 +472,7 @@ export class HostedConfiguration extends ConfigurationBase { type: this.type, validators: this.validators, deletionProtectionCheck: this.deletionProtectionCheck, - kmsKeyIdentifier: props.kmsKey?.keyArn, + kmsKeyIdentifier: props.kmsKey?.keyRef.keyArn, }); this.configurationProfileId = this._cfnConfigurationProfile.ref; this.configurationProfileArn = Stack.of(this).formatArn({ @@ -523,7 +531,7 @@ export interface SourcedConfigurationOptions extends ConfigurationOptions { * * @default - A role is generated. */ - readonly retrievalRole?: iam.IRole; + readonly retrievalRole?: iam.IRoleRef; } /** @@ -548,7 +556,7 @@ export interface SourcedConfigurationProps extends ConfigurationProps { * * @default - Auto generated if location type is not ConfigurationSourceType.CODE_PIPELINE otherwise no role specified. */ - readonly retrievalRole?: iam.IRole; + readonly retrievalRole?: iam.IRoleRef; } /** @@ -566,11 +574,6 @@ export class SourcedConfiguration extends ConfigurationBase { */ public readonly versionNumber?: string; - /** - * The IAM role to retrieve the configuration. - */ - public readonly retrievalRole?: iam.IRole; - /** * The key to decrypt the configuration if applicable. This key * can be used when storing configuration in AWS Secrets Manager, Systems Manager Parameter Store, @@ -590,15 +593,16 @@ export class SourcedConfiguration extends ConfigurationBase { private readonly locationUri: string; private readonly _cfnConfigurationProfile: CfnConfigurationProfile; + private readonly _retrievalRole?: iam.IRoleRef; - constructor (scope: Construct, id: string, props: SourcedConfigurationProps) { + constructor(scope: Construct, id: string, props: SourcedConfigurationProps) { super(scope, id, props); this.location = props.location; this.locationUri = this.location.locationUri; this.versionNumber = props.versionNumber; this.sourceKey = this.location.key; - this.retrievalRole = props.retrievalRole ?? this.getRetrievalRole(); + this._retrievalRole = props.retrievalRole ?? this.getRetrievalRole(); this._cfnConfigurationProfile = new CfnConfigurationProfile(this, 'Resource', { applicationId: this.applicationId, locationUri: this.locationUri, @@ -622,6 +626,19 @@ export class SourcedConfiguration extends ConfigurationBase { this.deployConfigToEnvironments(); } + /** + * The IAM role to retrieve the configuration. + */ + public get retrievalRole(): iam.IRole | undefined { + if (!this._retrievalRole) { + return undefined; + } + if ('grant' in this._retrievalRole) { + return this._retrievalRole as iam.IRole; + } + throw new ValidationError(`Retrieval role does not implement IRole: ${this._retrievalRole.constructor.name}`, this); + } + private getRetrievalRole(): iam.Role | undefined { // Check if the configuration source is not from CodePipeline if (this.location.type != ConfigurationSourceType.CODE_PIPELINE) { @@ -839,7 +856,15 @@ export abstract class ConfigurationContent { * Defines the hosted configuration content from a file. * * @param inputPath The path to the file that defines configuration content - * @param contentType The content type of the configuration + * @param contentType The configuration content type, specified as a standard MIME type. + * Supported examples include: + * - `text/plain` + * - `application/json` + * - `application/octet-stream` + * - `application/x-yaml` + * + * For an up-to-date list of valid MIME types, see: + * https://www.iana.org/assignments/media-types/media-types.xhtml */ public static fromFile(inputPath: string, contentType?: string): ConfigurationContent { return { @@ -852,7 +877,15 @@ export abstract class ConfigurationContent { * Defines the hosted configuration content from inline code. * * @param content The inline code that defines the configuration content - * @param contentType The content type of the configuration + * @param contentType The configuration content type, specified as a standard MIME type. + * Supported examples include: + * - `text/plain` + * - `application/json` + * - `application/octet-stream` + * - `application/x-yaml` + * + * For an up-to-date list of valid MIME types, see: + * https://www.iana.org/assignments/media-types/media-types.xhtml */ public static fromInline(content: string, contentType?: string): ConfigurationContent { return { @@ -865,7 +898,15 @@ export abstract class ConfigurationContent { * Defines the hosted configuration content as JSON from inline code. * * @param content The inline code that defines the configuration content - * @param contentType The content type of the configuration + * @param contentType The configuration content type, specified as a standard MIME type. + * Supported examples include: + * - `text/plain` + * - `application/json` + * - `application/octet-stream` + * - `application/x-yaml` + * + * For an up-to-date list of valid MIME types, see: + * https://www.iana.org/assignments/media-types/media-types.xhtml */ public static fromInlineJson(content: string, contentType?: string): ConfigurationContent { return { @@ -904,7 +945,15 @@ export abstract class ConfigurationContent { public abstract readonly content: string; /** - * The configuration content type. + * The configuration content type, specified as a standard MIME type. + * Supported examples include: + * - `text/plain` + * - `application/json` + * - `application/octet-stream` + * - `application/x-yaml` + * + * For an up-to-date list of valid MIME types, see: + * https://www.iana.org/assignments/media-types/media-types.xhtml */ public abstract readonly contentType: string; } diff --git a/packages/aws-cdk-lib/aws-appconfig/lib/environment.ts b/packages/aws-cdk-lib/aws-appconfig/lib/environment.ts index aff8848679565..24d726578f07c 100644 --- a/packages/aws-cdk-lib/aws-appconfig/lib/environment.ts +++ b/packages/aws-cdk-lib/aws-appconfig/lib/environment.ts @@ -403,10 +403,10 @@ export abstract class Monitor { * @param alarm The Amazon CloudWatch alarm. * @param alarmRole The IAM role for AWS AppConfig to view the alarm state. */ - public static fromCloudWatchAlarm(alarm: cloudwatch.IAlarm, alarmRole?: iam.IRole): Monitor { + public static fromCloudWatchAlarm(alarm: cloudwatch.IAlarm, alarmRole?: iam.IRoleRef): Monitor { return { alarmArn: alarm.alarmArn, - alarmRoleArn: alarmRole?.roleArn, + alarmRoleArn: alarmRole?.roleRef.roleArn, monitorType: MonitorType.CLOUDWATCH, }; } diff --git a/packages/aws-cdk-lib/aws-appconfig/lib/extension.ts b/packages/aws-cdk-lib/aws-appconfig/lib/extension.ts index 81ce7ebcbc49f..ac0247accabab 100644 --- a/packages/aws-cdk-lib/aws-appconfig/lib/extension.ts +++ b/packages/aws-cdk-lib/aws-appconfig/lib/extension.ts @@ -496,7 +496,7 @@ export class Extension extends Resource implements IExtension { public readonly extensionVersionNumber: number; private readonly _cfnExtension: CfnExtension; - private executionRole?: iam.IRole; + private executionRole?: iam.IRoleRef; constructor(scope: Construct, id: string, props: ExtensionProps) { super(scope, id, { @@ -527,7 +527,7 @@ export class Extension extends Resource implements IExtension { Uri: extensionUri, ...(sourceType === SourceType.EVENTS || cur.invokeWithoutExecutionRole ? {} - : { RoleArn: this.executionRole?.roleArn || this.getExecutionRole(cur.eventDestination, name).roleArn }), + : { RoleArn: this.executionRole?.roleRef.roleArn || this.getExecutionRole(cur.eventDestination, name).roleRef.roleArn }), ...(cur.description ? { Description: cur.description } : {}), }, ]; @@ -556,7 +556,7 @@ export class Extension extends Resource implements IExtension { }); } - private getExecutionRole(eventDestination: IEventDestination, actionName: string): iam.IRole { + private getExecutionRole(eventDestination: IEventDestination, actionName: string): iam.IRoleRef { const versionNumber = this.latestVersionNumber ? this.latestVersionNumber + 1 : 1; const combinedObjects = stringifyObjects(this.name, versionNumber, actionName); this.executionRole = new iam.Role(this, `Role${getHash(combinedObjects)}`, { diff --git a/packages/aws-cdk-lib/aws-appsync/lib/appsync-common.ts b/packages/aws-cdk-lib/aws-appsync/lib/appsync-common.ts index 33df34a0cc295..a22e80d4324d0 100644 --- a/packages/aws-cdk-lib/aws-appsync/lib/appsync-common.ts +++ b/packages/aws-cdk-lib/aws-appsync/lib/appsync-common.ts @@ -1,6 +1,6 @@ import { EventApiBase } from './eventapi'; import { ICertificate } from '../../aws-certificatemanager'; -import { IRole } from '../../aws-iam'; +import { IRoleRef } from '../../aws-iam'; import { RetentionDays } from '../../aws-logs'; import { Stack, ArnFormat } from '../../core'; @@ -121,7 +121,7 @@ export interface AppSyncLogConfig { * * @default - None */ - readonly role?: IRole; + readonly role?: IRoleRef; /** * The number of days log events are kept in CloudWatch Logs. diff --git a/packages/aws-cdk-lib/aws-appsync/lib/eventapi.ts b/packages/aws-cdk-lib/aws-appsync/lib/eventapi.ts index acb40be824a1b..e1b973734ec38 100644 --- a/packages/aws-cdk-lib/aws-appsync/lib/eventapi.ts +++ b/packages/aws-cdk-lib/aws-appsync/lib/eventapi.ts @@ -756,11 +756,11 @@ export class EventApi extends EventApiBase { private setupLogConfig(config?: AppSyncLogConfig) { if (!config) return; const logsRoleArn: string = - config.role?.roleArn ?? + config.role?.roleRef.roleArn ?? new Role(this, 'ApiLogsRole', { assumedBy: new ServicePrincipal('appsync.amazonaws.com'), managedPolicies: [ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSAppSyncPushToCloudWatchLogs')], - }).roleArn; + }).roleRef.roleArn; const fieldLogLevel: AppSyncFieldLogLevel = config.fieldLogLevel ?? AppSyncFieldLogLevel.NONE; return { cloudWatchLogsRoleArn: logsRoleArn, diff --git a/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi.ts b/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi.ts index ef7cb3526d6ae..4f51df490fbd3 100644 --- a/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi.ts +++ b/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi.ts @@ -5,7 +5,7 @@ import { ISchema, SchemaFile } from './schema'; import { MergeType, addSourceApiAutoMergePermission, addSourceGraphQLPermission } from './source-api-association'; import { ICertificate } from '../../aws-certificatemanager'; import { IUserPool } from '../../aws-cognito'; -import { ManagedPolicy, Role, IRole, ServicePrincipal } from '../../aws-iam'; +import { ManagedPolicy, Role, IRole, ServicePrincipal, IRoleRef } from '../../aws-iam'; import { IFunction } from '../../aws-lambda'; import { ILogGroup, LogGroup, LogRetention, RetentionDays } from '../../aws-logs'; import { CfnResource, Duration, Expiration, FeatureFlags, IResolvable, Lazy, Stack, Token, ValidationError } from '../../core'; @@ -231,7 +231,7 @@ export interface LogConfig { * * @default - None */ - readonly role?: IRole; + readonly role?: IRoleRef; /** * The number of days log events are kept in CloudWatch Logs. @@ -865,7 +865,7 @@ export class GraphqlApi extends GraphqlApiBase { private setupLogConfig(config?: LogConfig) { if (!config) return undefined; - const logsRoleArn: string = config.role?.roleArn ?? new Role(this, 'ApiLogsRole', { + const logsRoleArn: string = config.role?.roleRef.roleArn ?? new Role(this, 'ApiLogsRole', { assumedBy: new ServicePrincipal('appsync.amazonaws.com'), managedPolicies: [ ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSAppSyncPushToCloudWatchLogs'), diff --git a/packages/aws-cdk-lib/aws-backup/lib/resource.ts b/packages/aws-cdk-lib/aws-backup/lib/resource.ts index 3deadc8086a6a..fcf6a8645ae7d 100644 --- a/packages/aws-cdk-lib/aws-backup/lib/resource.ts +++ b/packages/aws-cdk-lib/aws-backup/lib/resource.ts @@ -72,11 +72,11 @@ export class BackupResource { /** * An EC2 instance */ - public static fromEc2Instance(instance: ec2.IInstance) { + public static fromEc2Instance(instance: ec2.IInstanceRef) { return BackupResource.fromArn(Stack.of(instance).formatArn({ service: 'ec2', resource: 'instance', - resourceName: instance.instanceId, + resourceName: instance.instanceRef.instanceId, })); } diff --git a/packages/aws-cdk-lib/aws-backup/lib/vault.ts b/packages/aws-cdk-lib/aws-backup/lib/vault.ts index f73a3b4a7880c..2ac120ceee686 100644 --- a/packages/aws-cdk-lib/aws-backup/lib/vault.ts +++ b/packages/aws-cdk-lib/aws-backup/lib/vault.ts @@ -58,7 +58,7 @@ export interface BackupVaultProps { * * @default - an Amazon managed KMS key */ - readonly encryptionKey?: kms.IKey; + readonly encryptionKey?: kms.IKeyRef; /** * A SNS topic to send vault events to. @@ -301,7 +301,7 @@ export class BackupVault extends BackupVaultBase { const vault = new CfnBackupVault(this, 'Resource', { backupVaultName: props.backupVaultName || this.uniqueVaultName(), accessPolicy: Lazy.any({ produce: () => this.accessPolicy.toJSON() }), - encryptionKeyArn: props.encryptionKey && props.encryptionKey.keyArn, + encryptionKeyArn: props.encryptionKey && props.encryptionKey.keyRef.keyArn, notifications, lockConfiguration: renderLockConfiguration(this, props.lockConfiguration), }); diff --git a/packages/aws-cdk-lib/aws-batch/lib/managed-compute-environment.ts b/packages/aws-cdk-lib/aws-batch/lib/managed-compute-environment.ts index e6a5ec999a2cc..4da2c55a2ea1f 100644 --- a/packages/aws-cdk-lib/aws-batch/lib/managed-compute-environment.ts +++ b/packages/aws-cdk-lib/aws-batch/lib/managed-compute-environment.ts @@ -1,4 +1,4 @@ -import { Construct } from 'constructs'; +import { Construct, IConstruct } from 'constructs'; import { CfnComputeEnvironment } from './batch.generated'; import { IComputeEnvironment, ComputeEnvironmentBase, ComputeEnvironmentProps } from './compute-environment-base'; import * as ec2 from '../../aws-ec2'; @@ -595,7 +595,7 @@ export interface ManagedEc2EcsComputeEnvironmentProps extends ManagedComputeEnvi * * @default - no placement group */ - readonly placementGroup?: ec2.IPlacementGroup; + readonly placementGroup?: ec2.IPlacementGroupRef; } /** @@ -650,8 +650,8 @@ export class ManagedEc2EcsComputeEnvironment extends ManagedComputeEnvironmentBa public readonly instanceRole?: iam.IRole; public readonly launchTemplate?: ec2.ILaunchTemplate; public readonly minvCpus?: number; - public readonly placementGroup?: ec2.IPlacementGroup; + private readonly _placementGroup?: ec2.IPlacementGroupRef; private readonly instanceProfile: iam.CfnInstanceProfile; constructor(scope: Construct, id: string, props: ManagedEc2EcsComputeEnvironmentProps) { @@ -684,7 +684,7 @@ export class ManagedEc2EcsComputeEnvironment extends ManagedComputeEnvironmentBa this.launchTemplate = props.launchTemplate; this.minvCpus = props.minvCpus ?? DEFAULT_MIN_VCPUS; - this.placementGroup = props.placementGroup; + this._placementGroup = props.placementGroup; validateVCpus(this, this.minvCpus, this.maxvCpus); validateSpotConfig(this, this.spot, this.spotBidPercentage, this.spotFleetRole); @@ -713,7 +713,7 @@ export class ManagedEc2EcsComputeEnvironment extends ManagedComputeEnvironmentBa imageType: image.imageType ?? EcsMachineImageType.ECS_AL2, }; }), - placementGroup: this.placementGroup?.placementGroupName, + placementGroup: props.placementGroup?.placementGroupRef.groupName, tags: this.tags.renderedTags as any, }, }); @@ -728,6 +728,10 @@ export class ManagedEc2EcsComputeEnvironment extends ManagedComputeEnvironmentBa this.node.addValidation({ validate: () => validateInstances(this.instanceTypes, this.instanceClasses, props.useOptimalInstanceClasses) }); } + public get placementGroup(): ec2.IPlacementGroup | undefined { + return this._placementGroup ? asPlacementGroup(this._placementGroup, this) : undefined; + } + @MethodMetadata() public addInstanceType(instanceType: ec2.InstanceType): void { this.instanceTypes.push(instanceType); @@ -984,7 +988,7 @@ export interface ManagedEc2EksComputeEnvironmentProps extends ManagedComputeEnvi * * @default - no placement group */ - readonly placementGroup?: ec2.IPlacementGroup; + readonly placementGroup?: ec2.IPlacementGroupRef; } /** @@ -1010,8 +1014,8 @@ export class ManagedEc2EksComputeEnvironment extends ManagedComputeEnvironmentBa public readonly instanceRole?: iam.IRole; public readonly launchTemplate?: ec2.ILaunchTemplate; public readonly minvCpus?: number; - public readonly placementGroup?: ec2.IPlacementGroup; + private readonly _placementGroup?: ec2.IPlacementGroupRef; private readonly instanceProfile: iam.CfnInstanceProfile; constructor(scope: Construct, id: string, props: ManagedEc2EksComputeEnvironmentProps) { @@ -1037,7 +1041,7 @@ export class ManagedEc2EksComputeEnvironment extends ManagedComputeEnvironmentBa this.launchTemplate = props.launchTemplate; this.minvCpus = props.minvCpus ?? DEFAULT_MIN_VCPUS; - this.placementGroup = props.placementGroup; + this._placementGroup = props.placementGroup; validateVCpus(this, this.minvCpus, this.maxvCpus); validateSpotConfig(this, this.spot, this.spotBidPercentage); @@ -1067,7 +1071,7 @@ export class ManagedEc2EksComputeEnvironment extends ManagedComputeEnvironmentBa imageType: image.imageType ?? EksMachineImageType.EKS_AL2, }; }), - placementGroup: this.placementGroup?.placementGroupName, + placementGroup: props.placementGroup?.placementGroupRef.groupName, tags: this.tags.renderedTags as any, }, }); @@ -1082,6 +1086,10 @@ export class ManagedEc2EksComputeEnvironment extends ManagedComputeEnvironmentBa this.node.addValidation({ validate: () => validateInstances(this.instanceTypes, this.instanceClasses, props.useOptimalInstanceClasses) }); } + public get placementGroup(): ec2.IPlacementGroup | undefined { + return this._placementGroup ? asPlacementGroup(this._placementGroup, this) : undefined; + } + @MethodMetadata() public addInstanceType(instanceType: ec2.InstanceType): void { this.instanceTypes.push(instanceType); @@ -1270,3 +1278,10 @@ function baseManagedResourceProperties(baseComputeEnvironment: ManagedComputeEnv const DEFAULT_MIN_VCPUS = 0; const DEFAULT_MAX_VCPUS = 256; + +function asPlacementGroup(x: ec2.IPlacementGroupRef, scope: IConstruct): ec2.IPlacementGroup { + if ('placementGroupName' in x) { + return x as ec2.IPlacementGroup; + } + throw new ValidationError(`Provided placement group is not an instance of IPlacementGroup: ${x.constructor.name}`, scope); +} diff --git a/packages/aws-cdk-lib/aws-certificatemanager/README.md b/packages/aws-cdk-lib/aws-certificatemanager/README.md index 8aa9a9467fc66..514d14fdf8a77 100644 --- a/packages/aws-cdk-lib/aws-certificatemanager/README.md +++ b/packages/aws-cdk-lib/aws-certificatemanager/README.md @@ -146,6 +146,17 @@ new acm.PrivateCertificate(this, 'PrivateCertificate', { }); ``` +## Requesting public SSL/TLS certificates exportable to use anywhere + +AWS Certificate Manager can issue an exportable public certificate. There is a charge at certificate issuance and again when the certificate renews. See [opting out of certificate transparency logging](https://docs.aws.amazon.com/acm/latest/userguide/acm-exportable-certificates.html) for details. + +```ts +new acm.Certificate(this, 'Certificate', { + domainName: 'test.example.com', + allowExport: true, +}); +``` + ## Requesting certificates without transparency logging Transparency logging can be opted out of for AWS Certificate Manager certificates. See [opting out of certificate transparency logging](https://docs.aws.amazon.com/acm/latest/userguide/acm-bestpractices.html#best-practices-transparency) for limits. diff --git a/packages/aws-cdk-lib/aws-certificatemanager/lib/certificate.ts b/packages/aws-cdk-lib/aws-certificatemanager/lib/certificate.ts index b2719c5163e9f..090a113995694 100644 --- a/packages/aws-cdk-lib/aws-certificatemanager/lib/certificate.ts +++ b/packages/aws-cdk-lib/aws-certificatemanager/lib/certificate.ts @@ -80,6 +80,16 @@ export interface CertificateProps { */ readonly validation?: CertificateValidation; + /** + * Enable or disable export of this certificate. + * + * If you issue an exportable public certificate, there is a charge at certificate issuance and again when the certificate renews. + * Ref: https://aws.amazon.com/certificate-manager/pricing + * + * @default false + */ + readonly allowExport?: boolean; + /** * Enable or disable transparency logging for this certificate * @@ -319,6 +329,8 @@ export class Certificate extends CertificateBase implements ICertificate { const allDomainNames = [props.domainName].concat(props.subjectAlternativeNames || []); + const certificateExport = (props.allowExport === true) ? 'ENABLED' : undefined; + let certificateTransparencyLoggingPreference: string | undefined; if (props.transparencyLoggingEnabled !== undefined) { certificateTransparencyLoggingPreference = props.transparencyLoggingEnabled ? 'ENABLED' : 'DISABLED'; @@ -329,6 +341,7 @@ export class Certificate extends CertificateBase implements ICertificate { subjectAlternativeNames: props.subjectAlternativeNames, domainValidationOptions: renderDomainValidation(this, validation, allDomainNames), validationMethod: validation.method, + certificateExport, certificateTransparencyLoggingPreference, keyAlgorithm: props.keyAlgorithm?.name, }); diff --git a/packages/aws-cdk-lib/aws-certificatemanager/lib/private-certificate.ts b/packages/aws-cdk-lib/aws-certificatemanager/lib/private-certificate.ts index b21b968781905..6505b04a1f369 100644 --- a/packages/aws-cdk-lib/aws-certificatemanager/lib/private-certificate.ts +++ b/packages/aws-cdk-lib/aws-certificatemanager/lib/private-certificate.ts @@ -42,6 +42,16 @@ export interface PrivateCertificateProps { * @default KeyAlgorithm.RSA_2048 */ readonly keyAlgorithm?: KeyAlgorithm; + + /** + * Enable or disable export of this certificate. + * + * If you issue an exportable public certificate, there is a charge at certificate issuance and again when the certificate renews. + * Ref: https://aws.amazon.com/certificate-manager/pricing + * + * @default false + */ + readonly allowExport?: boolean; } /** @@ -75,11 +85,14 @@ export class PrivateCertificate extends CertificateBase implements ICertificate // Enhanced CDK Analytics Telemetry addConstructMetadata(this, props); + const certificateExport = (props.allowExport === true) ? 'ENABLED' : undefined; + const cert = new CfnCertificate(this, 'Resource', { domainName: props.domainName, subjectAlternativeNames: props.subjectAlternativeNames, certificateAuthorityArn: props.certificateAuthority.certificateAuthorityArn, keyAlgorithm: props.keyAlgorithm?.name, + certificateExport, }); this.certificateArn = cert.ref; diff --git a/packages/aws-cdk-lib/aws-certificatemanager/test/certificate.test.ts b/packages/aws-cdk-lib/aws-certificatemanager/test/certificate.test.ts index 1335df418a773..acfcd4301bdba 100644 --- a/packages/aws-cdk-lib/aws-certificatemanager/test/certificate.test.ts +++ b/packages/aws-cdk-lib/aws-certificatemanager/test/certificate.test.ts @@ -363,6 +363,48 @@ test('CertificateValidation.fromDnsMultiZone', () => { }); }); +describe('Certificate export setting', () => { + test('leaves certificate export setting untouched by default', () => { + const stack = new Stack(); + + new Certificate(stack, 'Certificate', { + domainName: 'test.example.com', + }); + + const certificateNodes = Template.fromStack(stack).findResources('AWS::CertificateManager::Certificate'); + expect(certificateNodes.Certificate4E7ABB08).toBeDefined(); + expect(certificateNodes.Certificate4E7ABB08.CertificateTransparencyLoggingPreference).toBeUndefined(); + }); + + test('can enable certificate export', () => { + const stack = new Stack(); + + new Certificate(stack, 'Certificate', { + domainName: 'test.example.com', + allowExport: true, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CertificateManager::Certificate', { + DomainName: 'test.example.com', + CertificateExport: 'ENABLED', + }); + }); + + test('can disable certificate export', () => { + const stack = new Stack(); + + new Certificate(stack, 'Certificate', { + domainName: 'test.example.com', + allowExport: false, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CertificateManager::Certificate', { + DomainName: 'test.example.com', + CertificateExport: Match.absent(), + }); + }); +}); + describe('Transparency logging settings', () => { test('leaves transparency logging untouched by default', () => { const stack = new Stack(); diff --git a/packages/aws-cdk-lib/aws-certificatemanager/test/dns-validated-certificate.test.ts b/packages/aws-cdk-lib/aws-certificatemanager/test/dns-validated-certificate.test.ts index 214debb4a2161..2a042ebc188bb 100644 --- a/packages/aws-cdk-lib/aws-certificatemanager/test/dns-validated-certificate.test.ts +++ b/packages/aws-cdk-lib/aws-certificatemanager/test/dns-validated-certificate.test.ts @@ -41,7 +41,6 @@ testDeprecated('creates CloudFormation Custom Resource @aws-cdk/aws-lambda:creat }); Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'index.certificateRequestHandler', - Runtime: 'nodejs22.x', Timeout: 900, }); Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { @@ -136,7 +135,6 @@ testDeprecated('creates CloudFormation Custom Resource @aws-cdk/aws-lambda:creat }); Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'index.certificateRequestHandler', - Runtime: 'nodejs22.x', Timeout: 900, }); Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { diff --git a/packages/aws-cdk-lib/aws-certificatemanager/test/private-certificate.test.ts b/packages/aws-cdk-lib/aws-certificatemanager/test/private-certificate.test.ts index 75df50ea7b078..c8593ea8c5f2b 100644 --- a/packages/aws-cdk-lib/aws-certificatemanager/test/private-certificate.test.ts +++ b/packages/aws-cdk-lib/aws-certificatemanager/test/private-certificate.test.ts @@ -146,3 +146,51 @@ describe('Key Algorithm', () => { }); }); }); + +describe('Certificate export setting', () => { + test('leaves certificate export setting untouched by default', () => { + const stack = new Stack(); + + new PrivateCertificate(stack, 'Certificate', { + domainName: 'test.example.com', + certificateAuthority: acmpca.CertificateAuthority.fromCertificateAuthorityArn(stack, 'CA', + 'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/023077d8-2bfa-4eb0-8f22-05c96deade77'), + }); + + const certificateNodes = Template.fromStack(stack).findResources('AWS::CertificateManager::Certificate'); + expect(certificateNodes.Certificate4E7ABB08).toBeDefined(); + expect(certificateNodes.Certificate4E7ABB08.CertificateTransparencyLoggingPreference).toBeUndefined(); + }); + + test('can enable certificate export', () => { + const stack = new Stack(); + + new PrivateCertificate(stack, 'Certificate', { + domainName: 'test.example.com', + allowExport: true, + certificateAuthority: acmpca.CertificateAuthority.fromCertificateAuthorityArn(stack, 'CA', + 'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/023077d8-2bfa-4eb0-8f22-05c96deade77'), + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CertificateManager::Certificate', { + DomainName: 'test.example.com', + CertificateExport: 'ENABLED', + }); + }); + + test('can disable certificate export', () => { + const stack = new Stack(); + + new PrivateCertificate(stack, 'Certificate', { + domainName: 'test.example.com', + allowExport: false, + certificateAuthority: acmpca.CertificateAuthority.fromCertificateAuthorityArn(stack, 'CA', + 'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/023077d8-2bfa-4eb0-8f22-05c96deade77'), + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CertificateManager::Certificate', { + DomainName: 'test.example.com', + CertificateExport: Match.absent(), + }); + }); +}); diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts index 5dbf80d136fbd..19b0934064dea 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts @@ -1,20 +1,20 @@ import { Construct } from 'constructs'; -import { ICachePolicy } from './cache-policy'; import { CfnDistribution, CfnMonitoringSubscription, DistributionReference, + ICachePolicyRef, IDistributionRef, + IKeyGroupRef, + IOriginRequestPolicyRef, + IRealtimeLogConfigRef, + IResponseHeadersPolicyRef, } from './cloudfront.generated'; import { FunctionAssociation } from './function'; import { GeoRestriction } from './geo-restriction'; -import { IKeyGroup } from './key-group'; import { IOrigin, OriginBindConfig, OriginBindOptions, OriginSelectionCriteria } from './origin'; -import { IOriginRequestPolicy } from './origin-request-policy'; import { CacheBehavior } from './private/cache-behavior'; import { formatDistributionArn, grant } from './private/utils'; -import { IRealtimeLogConfig } from './realtime-log-config'; -import { IResponseHeadersPolicy } from './response-headers-policy'; import * as acm from '../../aws-certificatemanager'; import * as cloudwatch from '../../aws-cloudwatch'; import * as iam from '../../aws-iam'; @@ -1095,7 +1095,7 @@ export interface AddBehaviorOptions { * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-the-cache-key.html. * @default CachePolicy.CACHING_OPTIMIZED */ - readonly cachePolicy?: ICachePolicy; + readonly cachePolicy?: ICachePolicyRef; /** * Whether you want CloudFront to automatically compress certain files for this cache behavior. @@ -1112,21 +1112,21 @@ export interface AddBehaviorOptions { * * @default - none */ - readonly originRequestPolicy?: IOriginRequestPolicy; + readonly originRequestPolicy?: IOriginRequestPolicyRef; /** * The real-time log configuration to be attached to this cache behavior. * * @default - none */ - readonly realtimeLogConfig?: IRealtimeLogConfig; + readonly realtimeLogConfig?: IRealtimeLogConfigRef; /** * The response headers policy for this behavior. The response headers policy determines which headers are included in responses * * @default - none */ - readonly responseHeadersPolicy?: IResponseHeadersPolicy; + readonly responseHeadersPolicy?: IResponseHeadersPolicyRef; /** * Set this to true to indicate you want to distribute media files in the Microsoft Smooth Streaming format using this behavior. @@ -1163,7 +1163,7 @@ export interface AddBehaviorOptions { * @default - no KeyGroups are associated with cache behavior * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html */ - readonly trustedKeyGroups?: IKeyGroup[]; + readonly trustedKeyGroups?: IKeyGroupRef[]; /** * Enables your CloudFront distribution to receive gRPC requests and to proxy them directly to your origins. diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/function.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/function.ts index a9a660817e857..18bfcd5a186a1 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/lib/function.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/function.ts @@ -1,7 +1,6 @@ import * as fs from 'fs'; import { Construct } from 'constructs'; -import { CfnFunction, FunctionReference, IFunctionRef } from './cloudfront.generated'; -import { IKeyValueStore } from './key-value-store'; +import { CfnFunction, FunctionReference, IFunctionRef, IKeyValueStoreRef } from './cloudfront.generated'; import { IResource, Lazy, Names, Resource, Stack, ValidationError } from '../../core'; import { addConstructMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; @@ -144,7 +143,7 @@ export interface FunctionProps { * * @default - no key value store is associated */ - readonly keyValueStore?: IKeyValueStore; + readonly keyValueStore?: IKeyValueStoreRef; /** * A flag that determines whether to automatically publish the function to the LIVE stage when it’s created. @@ -219,7 +218,7 @@ export class Function extends Resource implements IFunction { functionConfig: { comment: props.comment ?? this.functionName, runtime: this.functionRuntime, - keyValueStoreAssociations: props.keyValueStore ? [{ keyValueStoreArn: props.keyValueStore.keyValueStoreArn }] : undefined, + keyValueStoreAssociations: props.keyValueStore ? [{ keyValueStoreArn: props.keyValueStore.keyValueStoreRef.keyValueStoreArn }] : undefined, }, name: this.functionName, }); @@ -268,7 +267,7 @@ export interface FunctionAssociation { /** * The CloudFront function that will be invoked. */ - readonly function: IFunction; + readonly function: IFunctionRef; /** The type of event which should invoke the function. */ readonly eventType: FunctionEventType; diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/key-group.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/key-group.ts index a37e590d9aeff..551fd3c4bd6bd 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/lib/key-group.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/key-group.ts @@ -1,6 +1,5 @@ import { Construct } from 'constructs'; -import { CfnKeyGroup, IKeyGroupRef, KeyGroupReference } from './cloudfront.generated'; -import { IPublicKey } from './public-key'; +import { CfnKeyGroup, IKeyGroupRef, IPublicKeyRef, KeyGroupReference } from './cloudfront.generated'; import { IResource, Names, Resource } from '../../core'; import { addConstructMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; @@ -35,7 +34,7 @@ export interface KeyGroupProps { /** * A list of public keys to add to the key group. */ - readonly items: IPublicKey[]; + readonly items: IPublicKeyRef[]; } /** @@ -70,7 +69,7 @@ export class KeyGroup extends Resource implements IKeyGroup { keyGroupConfig: { name: props.keyGroupName ?? this.generateName(), comment: props.comment, - items: props.items.map(key => key.publicKeyId), + items: props.items.map(key => key.publicKeyRef.publicKeyId), }, }); diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/private/cache-behavior.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/private/cache-behavior.ts index 8aaa82a0d39bb..7a8179b180616 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/lib/private/cache-behavior.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/private/cache-behavior.ts @@ -55,15 +55,15 @@ export class CacheBehavior { targetOriginId: this.originId, allowedMethods: this.props.allowedMethods?.methods, cachedMethods: this.props.cachedMethods?.methods, - cachePolicyId: (this.props.cachePolicy ?? CachePolicy.CACHING_OPTIMIZED).cachePolicyId, + cachePolicyId: (this.props.cachePolicy?.cachePolicyRef ?? CachePolicy.CACHING_OPTIMIZED).cachePolicyId, compress: this.props.compress ?? true, - originRequestPolicyId: this.props.originRequestPolicy?.originRequestPolicyId, - realtimeLogConfigArn: this.props?.realtimeLogConfig?.realtimeLogConfigArn, - responseHeadersPolicyId: this.props.responseHeadersPolicy?.responseHeadersPolicyId, + originRequestPolicyId: this.props.originRequestPolicy?.originRequestPolicyRef.originRequestPolicyId, + realtimeLogConfigArn: this.props?.realtimeLogConfig?.realtimeLogConfigRef.realtimeLogConfigArn, + responseHeadersPolicyId: this.props.responseHeadersPolicy?.responseHeadersPolicyRef.responseHeadersPolicyId, smoothStreaming: this.props.smoothStreaming, viewerProtocolPolicy: this.props.viewerProtocolPolicy ?? ViewerProtocolPolicy.ALLOW_ALL, functionAssociations: this.props.functionAssociations?.map(association => ({ - functionArn: association.function.functionArn, + functionArn: association.function.functionRef.functionArn, eventType: association.eventType.toString(), })), lambdaFunctionAssociations: this.props.edgeLambdas?.map(edgeLambda => ({ @@ -71,7 +71,7 @@ export class CacheBehavior { eventType: edgeLambda.eventType.toString(), includeBody: edgeLambda.includeBody, })), - trustedKeyGroups: this.props.trustedKeyGroups?.map(keyGroup => keyGroup.keyGroupId), + trustedKeyGroups: this.props.trustedKeyGroups?.map(keyGroup => keyGroup.keyGroupRef.keyGroupId), grpcConfig: this.props.enableGrpc !== undefined ? { enabled: this.props.enableGrpc, diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/response-headers-policy.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/response-headers-policy.ts index afef60089bff2..9617057d1c3ed 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/lib/response-headers-policy.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/response-headers-policy.ts @@ -160,6 +160,11 @@ export class ResponseHeadersPolicy extends Resource implements IResponseHeadersP throw new ValidationError(`accessControlAllowMethods contains unexpected method name; allowed values: ${allowedMethods.join(', ')}`, this); } }); + withResolved(behavior.accessControlAllowHeaders, (headers) => { + if (behavior.accessControlAllowCredentials && headers.some(header => !Token.isUnresolved(header) && header.includes('*'))) { + throw new ValidationError('accessControlAllowHeaders cannot contain "*" or headers with "*" when accessControlAllowCredentials is true', this); + } + }); return { accessControlAllowCredentials: behavior.accessControlAllowCredentials, diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/web-distribution.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/web-distribution.ts index 400bc87aef996..25d444b53cea6 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/lib/web-distribution.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/web-distribution.ts @@ -1067,7 +1067,7 @@ export class CloudFrontWebDistribution extends cdk.Resource implements IDistribu if (input.functionAssociations) { toReturn = Object.assign(toReturn, { functionAssociations: input.functionAssociations.map(association => ({ - functionArn: association.function.functionArn, + functionArn: association.function.functionRef.functionArn, eventType: association.eventType.toString(), })), }); diff --git a/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts b/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts index d921ed393e216..caae9579c0ea1 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts @@ -920,10 +920,7 @@ describe('with CloudFront functions', () => { { EventType: 'viewer-request', FunctionARN: { - 'Fn::GetAtt': [ - 'TestFunction22AD90FC', - 'FunctionARN', - ], + Ref: 'TestFunction22AD90FC', }, }, ], @@ -1303,7 +1300,7 @@ test('render distribution behavior with realtime log config', () => { DistributionConfig: { DefaultCacheBehavior: { RealtimeLogConfigArn: { - 'Fn::GetAtt': ['RealtimeConfigB6004E8E', 'Arn'], + Ref: 'RealtimeConfigB6004E8E', }, }, }, @@ -1349,14 +1346,14 @@ test('render distribution behavior with realtime log config - multiple behaviors DistributionConfig: { DefaultCacheBehavior: { RealtimeLogConfigArn: { - 'Fn::GetAtt': ['RealtimeConfigB6004E8E', 'Arn'], + Ref: 'RealtimeConfigB6004E8E', }, TargetOriginId: 'StackMyDistOrigin1D6D5E535', }, CacheBehaviors: [{ PathPattern: '/api/*', RealtimeLogConfigArn: { - 'Fn::GetAtt': ['RealtimeConfigB6004E8E', 'Arn'], + Ref: 'RealtimeConfigB6004E8E', }, TargetOriginId: 'StackMyDistOrigin20B96F3AD', }], diff --git a/packages/aws-cdk-lib/aws-cloudfront/test/response-headers-policy.test.ts b/packages/aws-cdk-lib/aws-cloudfront/test/response-headers-policy.test.ts index 10550d07d9500..1577f65ab6bba 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/test/response-headers-policy.test.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/test/response-headers-policy.test.ts @@ -205,5 +205,20 @@ describe('ResponseHeadersPolicy', () => { }, })).toThrow(/accessControlAllowMethods contains unexpected method name/); }); + + test.each([ + [['*']], + [['X-Custom-*', 'Authorization']], + ])('throws if accessControlAllowHeaders contains wildcard when accessControlAllowCredentials is true', (headers) => { + expect(() => new ResponseHeadersPolicy(stack, 'ResponseHeadersPolicy', { + corsBehavior: { + accessControlAllowCredentials: true, + accessControlAllowHeaders: headers, + accessControlAllowMethods: ['GET'], + accessControlAllowOrigins: ['https://example.com'], + originOverride: true, + }, + })).toThrow('accessControlAllowHeaders cannot contain "*" or headers with "*" when accessControlAllowCredentials is true'); + }); }); }); diff --git a/packages/aws-cdk-lib/aws-cloudfront/test/web-distribution.test.ts b/packages/aws-cdk-lib/aws-cloudfront/test/web-distribution.test.ts index 39a86dbfab129..8f6b642b7f850 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/test/web-distribution.test.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/test/web-distribution.test.ts @@ -810,10 +810,7 @@ added the ellipsis so a user would know there was more to r...`, { 'EventType': 'viewer-request', 'FunctionARN': { - 'Fn::GetAtt': [ - 'TestFunction22AD90FC', - 'FunctionARN', - ], + 'Ref': 'TestFunction22AD90FC', }, }, ], diff --git a/packages/aws-cdk-lib/aws-cloudtrail/lib/cloudtrail.ts b/packages/aws-cdk-lib/aws-cloudtrail/lib/cloudtrail.ts index 6acb4d0060b24..a50f4e11ac66c 100644 --- a/packages/aws-cdk-lib/aws-cloudtrail/lib/cloudtrail.ts +++ b/packages/aws-cdk-lib/aws-cloudtrail/lib/cloudtrail.ts @@ -85,7 +85,7 @@ export interface TrailProps { * @default - No encryption. * @deprecated - use encryptionKey instead. */ - readonly kmsKey?: kms.IKey; + readonly kmsKey?: kms.IKeyRef; /** The AWS Key Management Service (AWS KMS) key ID that you want to use to encrypt CloudTrail logs. * @@ -345,7 +345,7 @@ export class Trail extends Resource { isMultiRegionTrail: props.isMultiRegionTrail == null ? true : props.isMultiRegionTrail, includeGlobalServiceEvents: props.includeGlobalServiceEvents == null ? true : props.includeGlobalServiceEvents, trailName: this.physicalName, - kmsKeyId: props.encryptionKey?.keyArn ?? props.kmsKey?.keyArn, + kmsKeyId: props.encryptionKey?.keyArn ?? props.kmsKey?.keyRef.keyArn, s3BucketName: this.s3bucket.bucketName, s3KeyPrefix: props.s3KeyPrefix, cloudWatchLogsLogGroupArn: this.logGroup?.logGroupArn, @@ -458,7 +458,7 @@ export class Trail extends Resource { @MethodMetadata() public addS3EventSelector(s3Selector: S3EventSelector[], options: AddEventSelectorOptions = {}) { if (s3Selector.length === 0) { return; } - const dataResourceValues = s3Selector.map((sel) => `${sel.bucket.bucketArn}/${sel.objectPrefix ?? ''}`); + const dataResourceValues = s3Selector.map((sel) => `${sel.bucket.bucketRef.bucketArn}/${sel.objectPrefix ?? ''}`); return this.addEventSelector(DataResourceType.S3_OBJECT, dataResourceValues, options); } @@ -543,7 +543,7 @@ export enum ManagementEventSources { */ export interface S3EventSelector { /** S3 bucket */ - readonly bucket: s3.IBucket; + readonly bucket: s3.IBucketRef; /** * Data events for objects whose key matches this prefix will be logged. diff --git a/packages/aws-cdk-lib/aws-codecommit/lib/repository.ts b/packages/aws-cdk-lib/aws-codecommit/lib/repository.ts index f58e9523f84ec..d893f47de5132 100644 --- a/packages/aws-cdk-lib/aws-codecommit/lib/repository.ts +++ b/packages/aws-cdk-lib/aws-codecommit/lib/repository.ts @@ -505,7 +505,7 @@ export interface RepositoryProps { * * @default - Use an AWS managed key */ - readonly kmsKey?: kms.IKey; + readonly kmsKey?: kms.IKeyRef; } /** @@ -576,7 +576,7 @@ export class Repository extends RepositoryBase { repositoryDescription: props.description, triggers: Lazy.any({ produce: () => this.triggers }, { omitEmptyArray: true }), code: (props.code?.bind(this))?.code, - kmsKeyId: props.kmsKey?.keyArn, + kmsKeyId: props.kmsKey?.keyRef.keyArn, }); this.repositoryName = this.getResourceNameAttribute(repository.attrName); diff --git a/packages/aws-cdk-lib/aws-cognito-identitypool/lib/identitypool.ts b/packages/aws-cdk-lib/aws-cognito-identitypool/lib/identitypool.ts index 57109f086bbbe..6b63886f1d1f4 100644 --- a/packages/aws-cdk-lib/aws-cognito-identitypool/lib/identitypool.ts +++ b/packages/aws-cdk-lib/aws-cognito-identitypool/lib/identitypool.ts @@ -1,7 +1,7 @@ import { Construct } from 'constructs'; import { IUserPoolAuthenticationProvider } from './identitypool-user-pool-authentication-provider'; import { CfnIdentityPool, CfnIdentityPoolRoleAttachment, IUserPool, IUserPoolClient } from '../../aws-cognito'; -import { IOpenIdConnectProvider, ISamlProvider, Role, FederatedPrincipal, IRole } from '../../aws-iam'; +import { Role, FederatedPrincipal, IRole, IRoleRef, IOIDCProviderRef, ISAMLProviderRef } from '../../aws-iam'; import { Resource, IResource, Stack, ArnFormat, Lazy, Token, ValidationError, UnscopedValidationError } from '../../core'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; @@ -253,13 +253,13 @@ export interface IdentityPoolAuthenticationProviders { * The OpenIdConnect Provider associated with this Identity Pool * @default - no OpenIdConnectProvider */ - readonly openIdConnectProviders?: IOpenIdConnectProvider[]; + readonly openIdConnectProviders?: IOIDCProviderRef[]; /** * The Security Assertion Markup Language provider associated with this Identity Pool * @default - no SamlProvider */ - readonly samlProviders?: ISamlProvider[]; + readonly samlProviders?: ISAMLProviderRef[]; /** * The developer provider name to associate with this Identity Pool @@ -463,11 +463,11 @@ export class IdentityPool extends Resource implements IIdentityPool { if (providers && providers.length) this.cognitoIdentityProviders = providers; const openIdConnectProviderArns = authProviders.openIdConnectProviders ? authProviders.openIdConnectProviders.map(openIdProvider => - openIdProvider.openIdConnectProviderArn, + openIdProvider.oidcProviderRef.oidcProviderArn, ) : undefined; const samlProviderArns = authProviders.samlProviders ? authProviders.samlProviders.map(samlProvider => - samlProvider.samlProviderArn, + samlProvider.samlProviderRef.samlProviderArn, ) : undefined; let supportedLoginProviders:any = {}; @@ -568,13 +568,13 @@ interface IdentityPoolRoleAttachmentProps { * Default authenticated (User) Role * @default - No default authenticated Role will be added */ - readonly authenticatedRole?: IRole; + readonly authenticatedRole?: IRoleRef; /** * Default unauthenticated (Guest) Role * @default - No default unauthenticated Role will be added */ - readonly unauthenticatedRole?: IRole; + readonly unauthenticatedRole?: IRoleRef; /** * Rules for mapping roles to users @@ -611,8 +611,8 @@ class IdentityPoolRoleAttachment extends Resource implements IIdentityPoolRoleAt let roles: any = undefined, roleMappings: any = undefined; if (props.authenticatedRole || props.unauthenticatedRole) { roles = {}; - if (props.authenticatedRole) roles.authenticated = props.authenticatedRole.roleArn; - if (props.unauthenticatedRole) roles.unauthenticated = props.unauthenticatedRole.roleArn; + if (props.authenticatedRole) roles.authenticated = props.authenticatedRole.roleRef.roleArn; + if (props.unauthenticatedRole) roles.unauthenticated = props.unauthenticatedRole.roleRef.roleArn; } if (mappings) { roleMappings = this.configureRoleMappings(...mappings); diff --git a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-client.ts b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-client.ts index 3804e50ac2ab6..ec92565c2d3c4 100644 --- a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-client.ts +++ b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-client.ts @@ -3,7 +3,7 @@ import { CfnUserPoolClient } from './cognito.generated'; import { IUserPool } from './user-pool'; import { ClientAttributes } from './user-pool-attr'; import { IUserPoolResourceServer, ResourceServerScope } from './user-pool-resource-server'; -import { IRole } from '../../aws-iam'; +import { IRoleRef } from '../../aws-iam'; import { CfnApp } from '../../aws-pinpoint'; import { IResource, Resource, Duration, Stack, SecretValue, Token, FeatureFlags } from '../../core'; import { ValidationError } from '../../core/lib/errors'; @@ -407,7 +407,7 @@ export interface AnalyticsConfiguration { * The IAM role that has the permissions required for Amazon Cognito to publish events to Amazon Pinpoint analytics. * @default - no configuration, you need to specify either this property along with `applicationId` and `externalId` or `application`. */ - readonly role?: IRole; + readonly role?: IRoleRef; /** * If `true`, Amazon Cognito includes user data in the events that it publishes to Amazon Pinpoint analytics. @@ -722,7 +722,7 @@ export class UserPoolClient extends Resource implements IUserPoolClient { applicationArn: analytics.application?.attrArn, applicationId: analytics.applicationId, externalId: analytics.externalId, - roleArn: analytics.role?.roleArn, + roleArn: analytics.role?.roleRef.roleArn, userDataShared: analytics.shareUserData, }; } diff --git a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-group.ts b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-group.ts index b614ae6b6be54..623510becf132 100644 --- a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-group.ts +++ b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-group.ts @@ -1,7 +1,7 @@ import { Construct } from 'constructs'; import { CfnUserPoolGroup } from './cognito.generated'; import { IUserPool } from './user-pool'; -import { IRole } from '../../aws-iam'; +import { IRoleRef } from '../../aws-iam'; import { IResource, Resource, Token } from '../../core'; import { ValidationError } from '../../core/lib/errors'; import { addConstructMetadata } from '../../core/lib/metadata-resource'; @@ -58,7 +58,7 @@ export interface UserPoolGroupOptions { * * @default - no description */ - readonly role?: IRole; + readonly role?: IRoleRef; } /** @@ -121,7 +121,7 @@ export class UserPoolGroup extends Resource implements IUserPoolGroup { description: props.description, groupName: props.groupName, precedence: props.precedence, - roleArn: props.role?.roleArn, + roleArn: props.role?.roleRef.roleArn, }); this.groupName = resource.ref; diff --git a/packages/aws-cdk-lib/aws-cognito/lib/user-pool.ts b/packages/aws-cdk-lib/aws-cognito/lib/user-pool.ts index 8432ead5ff37b..20b7bfca96c93 100644 --- a/packages/aws-cdk-lib/aws-cognito/lib/user-pool.ts +++ b/packages/aws-cdk-lib/aws-cognito/lib/user-pool.ts @@ -9,8 +9,8 @@ import { UserPoolEmail, UserPoolEmailConfig } from './user-pool-email'; import { UserPoolGroup, UserPoolGroupOptions } from './user-pool-group'; import { IUserPoolIdentityProvider } from './user-pool-idp'; import { UserPoolResourceServer, UserPoolResourceServerOptions } from './user-pool-resource-server'; -import { Grant, IGrantable, IRole, PolicyDocument, PolicyStatement, Role, ServicePrincipal } from '../../aws-iam'; -import { IKey } from '../../aws-kms'; +import { Grant, IGrantable, IRoleRef, PolicyDocument, PolicyStatement, Role, ServicePrincipal } from '../../aws-iam'; +import { IKeyRef } from '../../aws-kms'; import * as lambda from '../../aws-lambda'; import { ArnFormat, Duration, IResource, Lazy, Names, RemovalPolicy, Resource, Stack, Token } from '../../core'; import { ValidationError } from '../../core/lib/errors'; @@ -707,7 +707,7 @@ export interface UserPoolProps { * * @default - a new IAM role is created. */ - readonly smsRole?: IRole; + readonly smsRole?: IRoleRef; /** * The 'ExternalId' that Cognito service must be using when assuming the `smsRole`, if the role is restricted with an 'sts:ExternalId' conditional. @@ -898,7 +898,7 @@ export interface UserPoolProps { * @see https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-custom-sender-triggers.html * @default - no key ID configured */ - readonly customSenderKmsKey?: IKey; + readonly customSenderKmsKey?: IKeyRef; /** * The user pool's Advanced Security Mode @@ -1141,7 +1141,7 @@ export class UserPool extends UserPoolBase { if (props.customSenderKmsKey) { const kmsKey = props.customSenderKmsKey; - (this.triggers as any).kmsKeyId = kmsKey.keyArn; + (this.triggers as any).kmsKeyId = kmsKey.keyRef.keyArn; } if (props.lambdaTriggers) { @@ -1436,7 +1436,7 @@ export class UserPool extends UserPoolBase { if (props.smsRole) { return { - snsCallerArn: props.smsRole.roleArn, + snsCallerArn: props.smsRole.roleRef.roleArn, externalId: props.smsRoleExternalId, snsRegion: props.snsRegion, }; @@ -1478,7 +1478,7 @@ export class UserPool extends UserPoolBase { }); return { externalId: smsRoleExternalId, - snsCallerArn: smsRole.roleArn, + snsCallerArn: smsRole.roleRef.roleArn, snsRegion: props.snsRegion, }; } diff --git a/packages/aws-cdk-lib/aws-config/lib/managed-rules.ts b/packages/aws-cdk-lib/aws-config/lib/managed-rules.ts index 65637dc642bc7..b70e979cc12c8 100644 --- a/packages/aws-cdk-lib/aws-config/lib/managed-rules.ts +++ b/packages/aws-cdk-lib/aws-config/lib/managed-rules.ts @@ -67,7 +67,7 @@ export interface CloudFormationStackDriftDetectionCheckProps extends RuleProps { * * @default - A role will be created */ - readonly role?: iam.IRole; + readonly role?: iam.IRoleRef; } /** @@ -82,14 +82,14 @@ export interface CloudFormationStackDriftDetectionCheckProps extends RuleProps { export class CloudFormationStackDriftDetectionCheck extends ManagedRule { /** Uniquely identifies this class. */ public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-config.CloudFormationStackDriftDetectionCheck'; - private readonly role: iam.IRole; + private readonly role: iam.IRoleRef; constructor(scope: Construct, id: string, props: CloudFormationStackDriftDetectionCheckProps = {}) { super(scope, id, { ...props, identifier: ManagedRuleIdentifiers.CLOUDFORMATION_STACK_DRIFT_DETECTION_CHECK, inputParameters: { - cloudformationRoleArn: Lazy.string({ produce: () => this.role.roleArn }), + cloudformationRoleArn: Lazy.string({ produce: () => this.role.roleRef.roleArn }), }, }); // Enhanced CDK Analytics Telemetry diff --git a/packages/aws-cdk-lib/aws-ec2/lib/cfn-init-elements.ts b/packages/aws-cdk-lib/aws-ec2/lib/cfn-init-elements.ts index e7c688434ae97..244f69caef1fa 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/cfn-init-elements.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/cfn-init-elements.ts @@ -1018,11 +1018,11 @@ export abstract class InitSource extends InitElement { * This block is the same every time (modulo bucket name), so it has the same * key every time so the blocks are merged into one in the final render. */ -function standardS3Auth(role: iam.IRole, bucketName: string) { +function standardS3Auth(role: iam.IRoleRef, bucketName: string) { return { S3AccessCreds: { type: 'S3', - roleName: role.roleName, + roleName: role.roleRef.roleName, buckets: [bucketName], }, }; diff --git a/packages/aws-cdk-lib/aws-ec2/lib/client-vpn-authorization-rule.ts b/packages/aws-cdk-lib/aws-ec2/lib/client-vpn-authorization-rule.ts index e619faf27d652..089679c767436 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/client-vpn-authorization-rule.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/client-vpn-authorization-rule.ts @@ -1,6 +1,5 @@ import { Construct } from 'constructs'; -import { IClientVpnEndpoint } from './client-vpn-endpoint-types'; -import { CfnClientVpnAuthorizationRule } from './ec2.generated'; +import { CfnClientVpnAuthorizationRule, IClientVpnEndpointRef } from './ec2.generated'; import { Resource, ValidationError } from '../../core'; import { addConstructMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; @@ -39,14 +38,14 @@ export interface ClientVpnAuthorizationRuleProps extends ClientVpnAuthorizationR * The client VPN endpoint to which to add the rule. * @default clientVpnEndpoint is required */ - readonly clientVpnEndpoint?: IClientVpnEndpoint; + readonly clientVpnEndpoint?: IClientVpnEndpointRef; /** * The client VPN endpoint to which to add the rule. * @deprecated Use `clientVpnEndpoint` instead * @default clientVpnEndpoint is required */ - readonly clientVpnEndoint?: IClientVpnEndpoint; + readonly clientVpnEndoint?: IClientVpnEndpointRef; } /** @@ -76,7 +75,7 @@ export class ClientVpnAuthorizationRule extends Resource { // Enhanced CDK Analytics Telemetry addConstructMetadata(this, props); new CfnClientVpnAuthorizationRule(this, 'Resource', { - clientVpnEndpointId: clientVpnEndpoint!.endpointId, + clientVpnEndpointId: clientVpnEndpoint!.clientVpnEndpointRef.clientVpnEndpointId, targetNetworkCidr: props.cidr, accessGroupId: props.groupId, authorizeAllGroups: !props.groupId, diff --git a/packages/aws-cdk-lib/aws-ec2/lib/client-vpn-endpoint.ts b/packages/aws-cdk-lib/aws-ec2/lib/client-vpn-endpoint.ts index b639fcc1414fe..412d91a7d2f03 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/client-vpn-endpoint.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/client-vpn-endpoint.ts @@ -16,7 +16,7 @@ import { import { CidrBlock } from './network-util'; import { ISecurityGroup, SecurityGroup } from './security-group'; import { IVpc, SubnetSelection } from './vpc'; -import { ISamlProvider } from '../../aws-iam'; +import { ISAMLProviderRef } from '../../aws-iam'; import * as logs from '../../aws-logs'; import { CfnOutput, Resource, Token, UnscopedValidationError, ValidationError } from '../../core'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; @@ -229,7 +229,7 @@ export abstract class ClientVpnUserBasedAuthentication { } /** Federated authentication */ - public static federated(samlProvider: ISamlProvider, selfServiceSamlProvider?: ISamlProvider): ClientVpnUserBasedAuthentication { + public static federated(samlProvider: ISAMLProviderRef, selfServiceSamlProvider?: ISAMLProviderRef): ClientVpnUserBasedAuthentication { return new FederatedAuthentication(samlProvider, selfServiceSamlProvider); } @@ -257,7 +257,7 @@ class ActiveDirectoryAuthentication extends ClientVpnUserBasedAuthentication { * Federated authentication */ class FederatedAuthentication extends ClientVpnUserBasedAuthentication { - constructor(private readonly samlProvider: ISamlProvider, private readonly selfServiceSamlProvider?: ISamlProvider) { + constructor(private readonly samlProvider: ISAMLProviderRef, private readonly selfServiceSamlProvider?: ISAMLProviderRef) { super(); } @@ -265,8 +265,8 @@ class FederatedAuthentication extends ClientVpnUserBasedAuthentication { return { type: 'federated-authentication', federatedAuthentication: { - samlProviderArn: this.samlProvider.samlProviderArn, - selfServiceSamlProviderArn: this.selfServiceSamlProvider?.samlProviderArn, + samlProviderArn: this.samlProvider.samlProviderRef.samlProviderArn, + selfServiceSamlProviderArn: this.selfServiceSamlProvider?.samlProviderRef.samlProviderArn, }, }; } diff --git a/packages/aws-cdk-lib/aws-ec2/lib/client-vpn-route.ts b/packages/aws-cdk-lib/aws-ec2/lib/client-vpn-route.ts index 004903d4542fe..f8e64034a42fe 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/client-vpn-route.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/client-vpn-route.ts @@ -1,7 +1,6 @@ import { Construct } from 'constructs'; import { IClientVpnEndpoint } from './client-vpn-endpoint-types'; -import { CfnClientVpnRoute } from './ec2.generated'; -import { ISubnet } from './vpc'; +import { CfnClientVpnRoute, ISubnetRef } from './ec2.generated'; import { Resource, ValidationError } from '../../core'; import { addConstructMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; @@ -45,8 +44,8 @@ export abstract class ClientVpnRouteTarget { * The specified subnet must be an existing target network of the client VPN * endpoint. */ - public static subnet(subnet: ISubnet): ClientVpnRouteTarget { - return { subnetId: subnet.subnetId }; + public static subnet(subnet: ISubnetRef): ClientVpnRouteTarget { + return { subnetId: subnet.subnetRef.subnetId }; } /** diff --git a/packages/aws-cdk-lib/aws-ec2/lib/instance-types.ts b/packages/aws-cdk-lib/aws-ec2/lib/instance-types.ts index a6077bfe7c7e3..41b0d6f1918d0 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/instance-types.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/instance-types.ts @@ -440,6 +440,28 @@ export enum InstanceClass { */ R7IZ = 'r7iz', + /** + * Memory optimized instances based on custom Intel Xeon Scalable 6 processors, available only on AWS + */ + MEMORY8_INTEL_BASE = 'memory8-intel-base', + + /** + * Memory optimized instances based on custom Intel Xeon Scalable 6 processors, available only on AWS + */ + R8I = 'r8i', + + /** + * Memory optimized flexible instances based on custom Intel Xeon Scalable 6 processors, available only on AWS + * Provide up to 20% higher performance, 2.5x more memory throughput, and can scale up to full CPU performance 95% of the time + */ + MEMORY8_INTEL_FLEX = 'memory8-intel-flex', + + /** + * Memory optimized flexible instances based on custom Intel Xeon Scalable 6 processors, available only on AWS + * Provide up to 20% higher performance, 2.5x more memory throughput, and can scale up to full CPU performance 95% of the time + */ + R8I_FLEX = 'r8i-flex', + /** * Memory optimized instances based on 4th generation AMD EPYC (codename Genoa), 7th generation */ @@ -1339,6 +1361,28 @@ export enum InstanceClass { */ M8GD = 'm8gd', + /** + * Standard instances based on custom Intel Xeon Scalable 6 processors, available only on AWS + */ + STANDARD8_INTEL = 'standard8-intel', + + /** + * Standard instances based on custom Intel Xeon Scalable 6 processors, available only on AWS + */ + M8I = 'm8i', + + /** + * Flexible instances based on custom Intel Xeon Scalable 6 processors, available only on AWS + * Provide up to 20% higher performance, 2.5x more memory throughput, and can scale up to full CPU performance 95% of the time + */ + STANDARD8_INTEL_FLEX = 'standard8-intel-flex', + + /** + * Flexible instances based on custom Intel Xeon Scalable 6 processors, available only on AWS + * Provide up to 20% higher performance, 2.5x more memory throughput, and can scale up to full CPU performance 95% of the time + */ + M8I_FLEX = 'm8i-flex', + /** * Standard instances with high memory and compute capacity based on Intel Xeon Scalable (Sapphire Rapids) processors, 7th generation */ @@ -1795,6 +1839,10 @@ export class InstanceType { [InstanceClass.R8G]: 'r8g', [InstanceClass.MEMORY8_GRAVITON4_NVME_DRIVE]: 'r8gd', [InstanceClass.R8GD]: 'r8gd', + [InstanceClass.MEMORY8_INTEL_BASE]: 'r8i', + [InstanceClass.R8I]: 'r8i', + [InstanceClass.MEMORY8_INTEL_FLEX]: 'r8i-flex', + [InstanceClass.R8I_FLEX]: 'r8i-flex', [InstanceClass.COMPUTE3]: 'c3', [InstanceClass.C3]: 'c3', [InstanceClass.COMPUTE4]: 'c4', @@ -1955,6 +2003,10 @@ export class InstanceType { [InstanceClass.M7I]: 'm7i', [InstanceClass.STANDARD7_INTEL_FLEX]: 'm7i-flex', [InstanceClass.M7I_FLEX]: 'm7i-flex', + [InstanceClass.STANDARD8_INTEL]: 'm8i', + [InstanceClass.M8I]: 'm8i', + [InstanceClass.STANDARD8_INTEL_FLEX]: 'm8i-flex', + [InstanceClass.M8I_FLEX]: 'm8i-flex', [InstanceClass.STANDARD7_AMD]: 'm7a', [InstanceClass.M7A]: 'm7a', [InstanceClass.HIGH_COMPUTE_MEMORY1]: 'z1d', diff --git a/packages/aws-cdk-lib/aws-ec2/lib/instance.ts b/packages/aws-cdk-lib/aws-ec2/lib/instance.ts index 707da0c255a18..e907179325323 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/instance.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/instance.ts @@ -2,12 +2,11 @@ import { Construct } from 'constructs'; import { InstanceRequireImdsv2Aspect } from './aspects'; import { CloudFormationInit } from './cfn-init'; import { Connections, IConnectable } from './connections'; -import { CfnInstance, IInstanceRef, InstanceReference } from './ec2.generated'; +import { CfnInstance, IInstanceRef, InstanceReference, IPlacementGroupRef } from './ec2.generated'; import { InstanceType } from './instance-types'; import { IKeyPair } from './key-pair'; import { CpuCredits, InstanceInitiatedShutdownBehavior } from './launch-template'; import { IMachineImage, OperatingSystemType } from './machine-image'; -import { IPlacementGroup } from './placement-group'; import { instanceBlockDeviceMappings } from './private/ebs-util'; import { ISecurityGroup, SecurityGroup } from './security-group'; import { UserData } from './user-data'; @@ -373,7 +372,7 @@ export interface InstanceProps { * * @default - no placement group will be used for this instance. */ - readonly placementGroup?: IPlacementGroup; + readonly placementGroup?: IPlacementGroupRef; /** * Whether the instance is enabled for AWS Nitro Enclaves. @@ -621,7 +620,7 @@ export class Instance extends Resource implements IInstance { ebsOptimized: props.ebsOptimized, disableApiTermination: props.disableApiTermination, instanceInitiatedShutdownBehavior: props.instanceInitiatedShutdownBehavior, - placementGroupName: props.placementGroup?.placementGroupName, + placementGroupName: props.placementGroup?.placementGroupRef.groupName, enclaveOptions: props.enclaveEnabled !== undefined ? { enabled: props.enclaveEnabled } : undefined, hibernationOptions: props.hibernationEnabled !== undefined ? { configured: props.hibernationEnabled } : undefined, ipv6AddressCount: props.ipv6AddressCount, diff --git a/packages/aws-cdk-lib/aws-ec2/lib/launch-template.ts b/packages/aws-cdk-lib/aws-ec2/lib/launch-template.ts index 29c677787a6b3..efc8b4b088685 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/launch-template.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/launch-template.ts @@ -1,10 +1,9 @@ import { Construct } from 'constructs'; import { Connections, IConnectable } from './connections'; -import { CfnLaunchTemplate, ILaunchTemplateRef, LaunchTemplateReference } from './ec2.generated'; +import { CfnLaunchTemplate, ILaunchTemplateRef, IPlacementGroupRef, LaunchTemplateReference } from './ec2.generated'; import { InstanceType } from './instance-types'; import { IKeyPair } from './key-pair'; import { IMachineImage, MachineImageConfig, OperatingSystemType } from './machine-image'; -import { IPlacementGroup } from './placement-group'; import { launchTemplateBlockDeviceMappings } from './private/ebs-util'; import { ISecurityGroup } from './security-group'; import { UserData } from './user-data'; @@ -450,7 +449,7 @@ export interface LaunchTemplateProps { * * @default - no placement group will be used for this launch template. */ - readonly placementGroup?: IPlacementGroup; + readonly placementGroup?: IPlacementGroupRef; } /** @@ -810,7 +809,7 @@ export class LaunchTemplate extends Resource implements ILaunchTemplate, iam.IGr metadataOptions: this.renderMetadataOptions(props), networkInterfaces, placement: props.placementGroup ? { - groupName: props.placementGroup.placementGroupName, + groupName: props.placementGroup.placementGroupRef.groupName, } : undefined, // Fields not yet implemented: diff --git a/packages/aws-cdk-lib/aws-ec2/lib/network-acl.ts b/packages/aws-cdk-lib/aws-ec2/lib/network-acl.ts index 5a2cfd437fa45..54d56464bde2d 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/network-acl.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/network-acl.ts @@ -10,6 +10,7 @@ import { import { AclCidr, AclTraffic } from './network-acl-types'; import { ISubnet, IVpc, SubnetSelection } from './vpc'; import { IResource, Resource, Tags } from '../../core'; +import { asNetworkAcl, asSubnet } from './private/conversions'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; @@ -20,8 +21,6 @@ const NAME_TAG: string = 'Name'; /** * A NetworkAcl - * - * */ export interface INetworkAcl extends IResource, INetworkAclRef { /** @@ -193,7 +192,6 @@ export interface INetworkAclEntry extends IResource, INetworkAclEntryRef { * The network ACL. */ readonly networkAcl: INetworkAcl; - } /** @@ -294,6 +292,7 @@ export interface NetworkAclEntryProps extends CommonNetworkAclEntryOptions { export class NetworkAclEntry extends NetworkAclEntryBase { /** Uniquely identifies this class. */ public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-ec2.NetworkAclEntry'; + public readonly networkAcl: INetworkAcl; public readonly networkAclEntryRef: NetworkAclEntryReference; @@ -307,7 +306,7 @@ export class NetworkAclEntry extends NetworkAclEntryBase { this.networkAcl = props.networkAcl; const resource = new CfnNetworkAclEntry(this, 'Resource', { - networkAclId: this.networkAcl.networkAclId, + networkAclId: this.networkAcl.networkAclRef.networkAclId, ruleNumber: props.ruleNumber, ruleAction: props.ruleAction ?? Action.ALLOW, egress: props.direction !== undefined ? props.direction === TrafficDirection.EGRESS : undefined, @@ -349,14 +348,11 @@ export interface SubnetNetworkAclAssociationProps { /** * The Network ACL this association is defined for - * - * @attribute */ - readonly networkAcl: INetworkAcl; + readonly networkAcl: INetworkAclRef; /** * ID of the Subnet - * @attribute */ readonly subnet: ISubnet; } @@ -396,19 +392,10 @@ export class SubnetNetworkAclAssociation extends SubnetNetworkAclAssociationBase */ public readonly subnetNetworkAclAssociationAssociationId: string; - /** - * ID for the current Network ACL - * @attribute - */ - public readonly networkAcl: INetworkAcl; - - /** - * ID of the Subnet - * @attribute - */ - public readonly subnet: ISubnet; + private readonly _subnet: ISubnet; private association: CfnSubnetNetworkAclAssociation; + private readonly _networkAcl: INetworkAclRef; constructor(scope: Construct, id: string, props: SubnetNetworkAclAssociationProps) { super(scope, id, { @@ -418,12 +405,26 @@ export class SubnetNetworkAclAssociation extends SubnetNetworkAclAssociationBase addConstructMetadata(this, props); this.association = new CfnSubnetNetworkAclAssociation(this, 'Resource', { - networkAclId: props.networkAcl.networkAclId, - subnetId: props.subnet.subnetId, + networkAclId: props.networkAcl.networkAclRef.networkAclId, + subnetId: props.subnet.subnetRef.subnetId, }); - this.networkAcl = props.networkAcl; - this.subnet = props.subnet; + this._networkAcl = props.networkAcl; + this._subnet = props.subnet; this.subnetNetworkAclAssociationAssociationId = this.association.attrAssociationId; } + + /** + * ID of the Subnet + */ + public get subnet(): ISubnet { + return asSubnet(this._subnet, this); + } + + /** + * ID for the current Network ACL + */ + public get networkAcl(): INetworkAcl { + return asNetworkAcl(this._networkAcl, this); + } } diff --git a/packages/aws-cdk-lib/aws-ec2/lib/private/conversions.ts b/packages/aws-cdk-lib/aws-ec2/lib/private/conversions.ts new file mode 100644 index 0000000000000..6a7d66e8a1f17 --- /dev/null +++ b/packages/aws-cdk-lib/aws-ec2/lib/private/conversions.ts @@ -0,0 +1,19 @@ +import { IConstruct } from 'constructs'; +import { ValidationError } from '../../../core/lib/errors'; +import { INetworkAclRef, ISubnetRef } from '../ec2.generated'; +import { INetworkAcl } from '../network-acl'; +import { ISubnet } from '../vpc'; + +export function asNetworkAcl(x: INetworkAclRef, scope: IConstruct): INetworkAcl { + if ('addEntry' in x) { + return x as INetworkAcl; + } + throw new ValidationError(`Provided networkAcl is not an instance of INetworkAcl: ${x.constructor.name}`, scope); +} + +export function asSubnet(x: ISubnetRef, scope: IConstruct): ISubnet { + if ('subnetId' in x) { + return x as ISubnet; + } + throw new ValidationError(`Provided subnet is not an instance of ISubnet: ${x.constructor.name}`, scope); +} diff --git a/packages/aws-cdk-lib/aws-ec2/lib/user-data.ts b/packages/aws-cdk-lib/aws-ec2/lib/user-data.ts index 8fc6cf1894732..4c047a428598e 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/user-data.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/user-data.ts @@ -1,5 +1,5 @@ import { OperatingSystemType } from './machine-image'; -import { IBucket } from '../../aws-s3'; +import { IBucketRef } from '../../aws-s3'; import { Fn, Resource, Stack, CfnResource, UnscopedValidationError } from '../../core'; /** @@ -40,7 +40,7 @@ export interface S3DownloadOptions { /** * Name of the S3 bucket to download from */ - readonly bucket: IBucket; + readonly bucket: IBucketRef; /** * The key of the file to download @@ -175,7 +175,7 @@ class LinuxUserData extends UserData { } public addS3DownloadCommand(params: S3DownloadOptions): string { - const s3Path = `s3://${params.bucket.bucketName}/${params.bucketKey}`; + const s3Path = `s3://${params.bucket.bucketRef.bucketName}/${params.bucketKey}`; const localPath = ( params.localFile && params.localFile.length !== 0 ) ? params.localFile : `/tmp/${ params.bucketKey }`; this.addCommands( `mkdir -p $(dirname '${localPath}')`, @@ -238,7 +238,7 @@ class WindowsUserData extends UserData { const localPath = ( params.localFile && params.localFile.length !== 0 ) ? params.localFile : `C:/temp/${ params.bucketKey }`; this.addCommands( `mkdir (Split-Path -Path '${localPath}' ) -ea 0`, - `Read-S3Object -BucketName '${params.bucket.bucketName}' -key '${params.bucketKey}' -file '${localPath}' -ErrorAction Stop` + (params.region !== undefined ? ` -Region ${params.region}` : ''), + `Read-S3Object -BucketName '${params.bucket.bucketRef.bucketName}' -key '${params.bucketKey}' -file '${localPath}' -ErrorAction Stop` + (params.region !== undefined ? ` -Region ${params.region}` : ''), ); return localPath; } diff --git a/packages/aws-cdk-lib/aws-ec2/lib/volume.ts b/packages/aws-cdk-lib/aws-ec2/lib/volume.ts index ac21d3565a154..8a854f88683c0 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/volume.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/volume.ts @@ -1,6 +1,5 @@ import { Construct } from 'constructs'; -import { CfnVolume, IVolumeRef, VolumeReference } from './ec2.generated'; -import { IInstance } from './instance'; +import { CfnVolume, IInstanceRef, IVolumeRef, VolumeReference } from './ec2.generated'; import { AccountRootPrincipal, Grant, IGrantable } from '../../aws-iam'; import { IKey, ViaServicePrincipal } from '../../aws-kms'; import { @@ -310,7 +309,7 @@ export interface IVolume extends IResource, IVolumeRef { * volume to. If not specified, then permission is granted to attach * to all instances in this account. */ - grantAttachVolume(grantee: IGrantable, instances?: IInstance[]): Grant; + grantAttachVolume(grantee: IGrantable, instances?: IInstanceRef[]): Grant; /** * Grants permission to attach the Volume by a ResourceTag condition. If you are looking to @@ -341,7 +340,7 @@ export interface IVolume extends IResource, IVolumeRef { * volume from. If not specified, then permission is granted to detach * from all instances in this account. */ - grantDetachVolume(grantee: IGrantable, instances?: IInstance[]): Grant; + grantDetachVolume(grantee: IGrantable, instances?: IInstanceRef[]): Grant; /** * Grants permission to detach the Volume by a ResourceTag condition. @@ -533,7 +532,7 @@ abstract class VolumeBase extends Resource implements IVolume { }; } - public grantAttachVolume(grantee: IGrantable, instances?: IInstance[]): Grant { + public grantAttachVolume(grantee: IGrantable, instances?: IInstanceRef[]): Grant { const result = Grant.addToPrincipal({ grantee, actions: ['ec2:AttachVolume'], @@ -579,7 +578,7 @@ abstract class VolumeBase extends Resource implements IVolume { return result; } - public grantDetachVolume(grantee: IGrantable, instances?: IInstance[]): Grant { + public grantDetachVolume(grantee: IGrantable, instances?: IInstanceRef[]): Grant { const result = Grant.addToPrincipal({ grantee, actions: ['ec2:DetachVolume'], @@ -608,14 +607,14 @@ abstract class VolumeBase extends Resource implements IVolume { return result; } - private collectGrantResourceArns(instances?: IInstance[]): string[] { + private collectGrantResourceArns(instances?: IInstanceRef[]): string[] { const stack = Stack.of(this); const resourceArns: string[] = [ `arn:${stack.partition}:ec2:${stack.region}:${stack.account}:volume/${this.volumeId}`, ]; const instanceArnPrefix = `arn:${stack.partition}:ec2:${stack.region}:${stack.account}:instance`; if (instances) { - instances.forEach(instance => resourceArns.push(`${instanceArnPrefix}/${instance?.instanceId}`)); + instances.forEach(instance => resourceArns.push(`${instanceArnPrefix}/${instance?.instanceRef.instanceId}`)); } else { resourceArns.push(`${instanceArnPrefix}/*`); } diff --git a/packages/aws-cdk-lib/aws-ec2/lib/vpc-flow-logs.ts b/packages/aws-cdk-lib/aws-ec2/lib/vpc-flow-logs.ts index fd87ef934d8c5..9fa355676f24d 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/vpc-flow-logs.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/vpc-flow-logs.ts @@ -1,6 +1,6 @@ import { Construct } from 'constructs'; -import { CfnFlowLog, FlowLogReference, IFlowLogRef } from './ec2.generated'; -import { ISubnet, IVpc } from './vpc'; +import { CfnFlowLog, FlowLogReference, IFlowLogRef, ISubnetRef } from './ec2.generated'; +import { IVpc } from './vpc'; import * as iam from '../../aws-iam'; import * as logs from '../../aws-logs'; import * as s3 from '../../aws-s3'; @@ -83,10 +83,10 @@ export abstract class FlowLogResourceType { /** * The subnet to attach the Flow Log to */ - public static fromSubnet(subnet: ISubnet): FlowLogResourceType { + public static fromSubnet(subnet: ISubnetRef): FlowLogResourceType { return { resourceType: 'Subnet', - resourceId: subnet.subnetId, + resourceId: subnet.subnetRef.subnetId, }; } diff --git a/packages/aws-cdk-lib/aws-ec2/lib/vpc.ts b/packages/aws-cdk-lib/aws-ec2/lib/vpc.ts index 0724d67dc64fd..e4c57b7af904c 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/vpc.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/vpc.ts @@ -2187,7 +2187,7 @@ export class Subnet extends Resource implements ISubnet { // subnet.attrNetworkAclAssociationId is the default ACL after the subnet // was just created. However, the ACL can be replaced at a later time. this._networkAcl = NetworkAcl.fromNetworkAclId(this, 'Acl', subnet.attrNetworkAclAssociationId); - this.subnetNetworkAclAssociationId = Lazy.string({ produce: () => this._networkAcl.networkAclId }); + this.subnetNetworkAclAssociationId = Lazy.string({ produce: () => this._networkAcl.networkAclRef.networkAclId }); this.node.defaultChild = subnet; const table = new CfnRouteTable(this, 'RouteTable', { diff --git a/packages/aws-cdk-lib/aws-ec2/test/client-vpn-authorization-rule.test.ts b/packages/aws-cdk-lib/aws-ec2/test/client-vpn-authorization-rule.test.ts index 8ff999a1829e2..e870e30a45a90 100644 --- a/packages/aws-cdk-lib/aws-ec2/test/client-vpn-authorization-rule.test.ts +++ b/packages/aws-cdk-lib/aws-ec2/test/client-vpn-authorization-rule.test.ts @@ -24,6 +24,9 @@ describe('ClientVpnAuthorizationRule constructor', () => { connections: new Connections(), node: stack.node, applyRemovalPolicy: () => { }, + clientVpnEndpointRef: { + clientVpnEndpointId: 'myClientVpnEndpoint', + }, }; new ClientVpnAuthorizationRule(stack, 'NormalRule', { cidr: '10.0.10.0/32', @@ -52,6 +55,9 @@ describe('ClientVpnAuthorizationRule constructor', () => { connections: new Connections(), node: stack.node, applyRemovalPolicy: () => { }, + clientVpnEndpointRef: { + clientVpnEndpointId: 'typoTypo', + }, }; const clientVpnEndpoint: IClientVpnEndpoint = { endpointId: 'myClientVpnEndpoint', @@ -61,6 +67,9 @@ describe('ClientVpnAuthorizationRule constructor', () => { connections: new Connections(), node: stack.node, applyRemovalPolicy: () => { }, + clientVpnEndpointRef: { + clientVpnEndpointId: 'myClientVpnEndpoint', + }, }; expect(() => { new ClientVpnAuthorizationRule(stack, 'RuleBothEndointAndEndpoint', { @@ -92,6 +101,9 @@ describe('ClientVpnAuthorizationRule constructor', () => { connections: new Connections(), node: stack.node, applyRemovalPolicy: () => { }, + clientVpnEndpointRef: { + clientVpnEndpointId: 'myClientVpnEndpoint', + }, }; new ClientVpnAuthorizationRule(stack, 'RuleWithEndointTypo', { cidr: '10.0.10.0/32', diff --git a/packages/aws-cdk-lib/aws-ecr/lib/repository.ts b/packages/aws-cdk-lib/aws-ecr/lib/repository.ts index 9424ab9aae637..1b4a7e6412c95 100644 --- a/packages/aws-cdk-lib/aws-ecr/lib/repository.ts +++ b/packages/aws-cdk-lib/aws-ecr/lib/repository.ts @@ -548,7 +548,7 @@ export interface RepositoryProps { * @default - If encryption is set to `KMS` and this property is undefined, * an AWS managed KMS key is used. */ - readonly encryptionKey?: kms.IKey; + readonly encryptionKey?: kms.IKeyRef; /** * Life cycle rules to apply to this registry @@ -979,7 +979,7 @@ export class Repository extends RepositoryBase { if (encryptionType === RepositoryEncryption.KMS) { return { encryptionType: 'KMS', - kmsKey: props.encryptionKey?.keyArn, + kmsKey: props.encryptionKey?.keyRef.keyArn, }; } diff --git a/packages/aws-cdk-lib/aws-ecs/lib/base/base-service.ts b/packages/aws-cdk-lib/aws-ecs/lib/base/base-service.ts index 09e04d5b177c2..74d1c0b304e56 100644 --- a/packages/aws-cdk-lib/aws-ecs/lib/base/base-service.ts +++ b/packages/aws-cdk-lib/aws-ecs/lib/base/base-service.ts @@ -283,7 +283,7 @@ export interface ServiceConnectTlsConfiguration { * * @default - none */ - readonly kmsKey?: kms.IKey; + readonly kmsKey?: kms.IKeyRef; /** * The IAM role that's associated with the Service Connect TLS. @@ -1023,7 +1023,7 @@ export abstract class BaseService extends Resource issuerCertificateAuthority: { awsPcaAuthorityArn: svc.tls.awsPcaAuthorityArn, }, - kmsKey: svc.tls.kmsKey?.keyArn, + kmsKey: svc.tls.kmsKey?.keyRef.keyArn, roleArn: svc.tls.role?.roleArn, } : undefined; @@ -1176,7 +1176,7 @@ export abstract class BaseService extends Resource })); } - if (logConfiguration?.s3Bucket?.bucketName) { + if (logConfiguration?.s3Bucket?.bucketRef.bucketName) { this.taskDefinition.addToTaskRolePolicy(new iam.PolicyStatement({ actions: [ 's3:GetBucketLocation', @@ -1187,14 +1187,14 @@ export abstract class BaseService extends Resource actions: [ 's3:PutObject', ], - resources: [`arn:${this.stack.partition}:s3:::${logConfiguration.s3Bucket.bucketName}/*`], + resources: [`arn:${this.stack.partition}:s3:::${logConfiguration.s3Bucket.bucketRef.bucketName}/*`], })); if (logConfiguration.s3EncryptionEnabled) { this.taskDefinition.addToTaskRolePolicy(new iam.PolicyStatement({ actions: [ 's3:GetEncryptionConfiguration', ], - resources: [`arn:${this.stack.partition}:s3:::${logConfiguration.s3Bucket.bucketName}`], + resources: [`arn:${this.stack.partition}:s3:::${logConfiguration.s3Bucket.bucketRef.bucketName}`], })); } } diff --git a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts index cd97c450c7bd8..0cbd66d9e31ef 100644 --- a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts @@ -9,7 +9,7 @@ import * as ec2 from '../../aws-ec2'; import * as iam from '../../aws-iam'; import { PolicyStatement, ServicePrincipal } from '../../aws-iam'; import * as kms from '../../aws-kms'; -import { IKey } from '../../aws-kms'; +import { IKey, IKeyRef } from '../../aws-kms'; import * as logs from '../../aws-logs'; import * as s3 from '../../aws-s3'; import * as cloudmap from '../../aws-servicediscovery'; @@ -439,7 +439,7 @@ export class Cluster extends Resource implements ICluster { }, managedStorageConfiguration: this._managedStorageConfiguration && { fargateEphemeralStorageKmsKeyId: this._managedStorageConfiguration.fargateEphemeralStorageKmsKey?.keyId, - kmsKeyId: this._managedStorageConfiguration.kmsKey?.keyId, + kmsKeyId: this._managedStorageConfiguration.kmsKey?.keyRef.keyId, }, }; } @@ -1495,7 +1495,7 @@ export interface ManagedStorageConfiguration { * * @default - Encrypted using AWS-managed key */ - readonly kmsKey?: IKey; + readonly kmsKey?: IKeyRef; } /** diff --git a/packages/aws-cdk-lib/aws-efs/lib/efs-file-system.ts b/packages/aws-cdk-lib/aws-efs/lib/efs-file-system.ts index 014e4cea807db..87d5045d58d74 100644 --- a/packages/aws-cdk-lib/aws-efs/lib/efs-file-system.ts +++ b/packages/aws-cdk-lib/aws-efs/lib/efs-file-system.ts @@ -230,7 +230,7 @@ export interface FileSystemProps { * * @default - if 'encrypted' is true, the default key for EFS (/aws/elasticfilesystem) is used */ - readonly kmsKey?: kms.IKey; + readonly kmsKey?: kms.IKeyRef; /** * A policy used by EFS lifecycle management to transition files to the Infrequent Access (IA) storage class. @@ -803,7 +803,7 @@ export class FileSystem extends FileSystemBase { this._resource = new CfnFileSystem(this, 'Resource', { encrypted: encrypted, - kmsKeyId: props.kmsKey?.keyArn, + kmsKeyId: props.kmsKey?.keyRef.keyArn, lifecyclePolicies: lifecyclePolicies.length > 0 ? lifecyclePolicies : undefined, performanceMode: props.performanceMode, throughputMode: props.throughputMode, diff --git a/packages/aws-cdk-lib/aws-eks/lib/cluster-resource.ts b/packages/aws-cdk-lib/aws-eks/lib/cluster-resource.ts index 6ed813b6a682e..958d48c459278 100644 --- a/packages/aws-cdk-lib/aws-eks/lib/cluster-resource.ts +++ b/packages/aws-cdk-lib/aws-eks/lib/cluster-resource.ts @@ -21,7 +21,7 @@ export interface ClusterResourceProps { readonly vpc: ec2.IVpc; readonly environment?: { [key: string]: string }; readonly subnets?: ec2.ISubnet[]; - readonly secretsEncryptionKey?: kms.IKey; + readonly secretsEncryptionKey?: kms.IKeyRef; readonly onEventLayer?: lambda.ILayerVersion; readonly clusterHandlerSecurityGroup?: ec2.ISecurityGroup; readonly tags?: { [key: string]: string }; @@ -212,7 +212,7 @@ export class ClusterResource extends Construct { 'kms:DescribeKey', 'kms:CreateGrant', ], - resources: [props.secretsEncryptionKey.keyArn], + resources: [props.secretsEncryptionKey.keyRef.keyArn], })); } diff --git a/packages/aws-cdk-lib/aws-eks/lib/cluster.ts b/packages/aws-cdk-lib/aws-eks/lib/cluster.ts index 016591964d5ee..9e2a04184429f 100644 --- a/packages/aws-cdk-lib/aws-eks/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-eks/lib/cluster.ts @@ -664,7 +664,7 @@ export interface ClusterOptions extends CommonClusterOptions { * all etcd volumes used by Amazon EKS are encrypted at the disk-level * using AWS-Managed encryption keys. */ - readonly secretsEncryptionKey?: kms.IKey; + readonly secretsEncryptionKey?: kms.IKeyRef; /** * Specify which IP family is used to assign Kubernetes pod and service IP addresses. @@ -1753,7 +1753,7 @@ export class Cluster extends ClusterBase { ...(props.secretsEncryptionKey ? { encryptionConfig: [{ provider: { - keyArn: props.secretsEncryptionKey.keyArn, + keyArn: props.secretsEncryptionKey.keyRef.keyArn, }, resources: ['secrets'], }], diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store-revocation.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store-revocation.ts index e3d527472188c..18eee1666b659 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store-revocation.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store-revocation.ts @@ -1,6 +1,6 @@ import { Construct } from 'constructs'; import { ITrustStore } from './trust-store'; -import { IBucket } from '../../../aws-s3'; +import { IBucketRef } from '../../../aws-s3'; import { Resource } from '../../../core'; import { addConstructMetadata } from '../../../core/lib/metadata-resource'; import { propertyInjectable } from '../../../core/lib/prop-injectable'; @@ -36,7 +36,7 @@ export interface RevocationContent { /** * The Amazon S3 bucket for the revocation file */ - readonly bucket: IBucket; + readonly bucket: IBucketRef; /** * The Amazon S3 path for the revocation file @@ -78,7 +78,7 @@ export class TrustStoreRevocation extends Resource { trustStoreArn: props.trustStore.trustStoreArn, revocationContents: props.revocationContents?.map(content => ({ revocationType: content.revocationType, - s3Bucket: content.bucket.bucketName, + s3Bucket: content.bucket.bucketRef.bucketName, s3Key: content.key, s3ObjectVersion: content.version, })), diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store.ts index fa27a64cec7e4..ed421255ba3a6 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store.ts @@ -1,6 +1,6 @@ import { Construct } from 'constructs'; -import { IBucket } from '../../../aws-s3'; -import { IResource, Resource, Fn, Names, Lazy, Token } from '../../../core'; +import { IBucketRef } from '../../../aws-s3'; +import { Fn, IResource, Lazy, Names, Resource, Token } from '../../../core'; import { ValidationError } from '../../../core/lib/errors'; import { addConstructMetadata } from '../../../core/lib/metadata-resource'; import { propertyInjectable } from '../../../core/lib/prop-injectable'; @@ -38,7 +38,7 @@ export interface TrustStoreProps { /** * The bucket that the trust store is hosted in */ - readonly bucket: IBucket; + readonly bucket: IBucketRef; /** * The key in S3 to look at for the trust store @@ -126,7 +126,7 @@ export class TrustStore extends Resource implements ITrustStore { const resource = new CfnTrustStore(this, 'Resource', { name: this.physicalName, - caCertificatesBundleS3Bucket: props.bucket.bucketName, + caCertificatesBundleS3Bucket: props.bucket.bucketRef.bucketName, caCertificatesBundleS3Key: props.key, caCertificatesBundleS3ObjectVersion: props.version, }); diff --git a/packages/aws-cdk-lib/aws-elasticsearch/lib/domain.ts b/packages/aws-cdk-lib/aws-elasticsearch/lib/domain.ts index e1ee0428c9924..48eb034cd32b6 100644 --- a/packages/aws-cdk-lib/aws-elasticsearch/lib/domain.ts +++ b/packages/aws-cdk-lib/aws-elasticsearch/lib/domain.ts @@ -380,7 +380,7 @@ export interface EncryptionAtRestOptions { * @default - uses default aws/es KMS key. * @deprecated use opensearchservice module instead */ - readonly kmsKey?: kms.IKey; + readonly kmsKey?: kms.IKeyRef; } /** @@ -1841,7 +1841,7 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable { encryptionAtRestOptions: { enabled: encryptionAtRestEnabled, kmsKeyId: encryptionAtRestEnabled - ? props.encryptionAtRest?.kmsKey?.keyId + ? props.encryptionAtRest?.kmsKey?.keyRef.keyId : undefined, }, nodeToNodeEncryptionOptions: { enabled: nodeToNodeEncryptionEnabled }, @@ -1970,7 +1970,7 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable { // empircal evidence shows this is indeed required: https://github.com/aws/aws-cdk/issues/11412 this.accessPolicy.grantPrincipal.addToPrincipalPolicy(new iam.PolicyStatement({ actions: ['kms:List*', 'kms:Describe*', 'kms:CreateGrant'], - resources: [this.encryptionAtRestOptions.kmsKey.keyArn], + resources: [this.encryptionAtRestOptions.kmsKey.keyRef.keyArn], effect: iam.Effect.ALLOW, })); } diff --git a/packages/aws-cdk-lib/aws-events-targets/README.md b/packages/aws-cdk-lib/aws-events-targets/README.md index 5666346b5a26d..3b3864902dd19 100644 --- a/packages/aws-cdk-lib/aws-events-targets/README.md +++ b/packages/aws-cdk-lib/aws-events-targets/README.md @@ -15,6 +15,7 @@ Currently supported are: - [Start a StepFunctions state machine](#start-a-stepfunctions-state-machine) - [Queue a Batch job](#queue-a-batch-job) - [Invoke an API Gateway REST API](#invoke-an-api-gateway-rest-api) + - [Invoke an AWS API](#invoke-an-aws-api) - [Invoke an API Destination](#invoke-an-api-destination) - [Invoke an AppSync GraphQL API](#invoke-an-appsync-graphql-api) - [Put an event on an EventBridge bus](#put-an-event-on-an-eventbridge-bus) @@ -333,6 +334,67 @@ declare const rule: events.Rule; rule.addTarget(new targets.ApiGatewayV2(httpApi)); ``` +## Invoke an AWS API + +Use the `AwsApi` target to make direct AWS API calls from EventBridge rules. This is useful for invoking AWS services that don't have a dedicated EventBridge target. + +### Basic Usage + +The following example shows how to update an ECS service when a rule is triggered: + +```ts +const rule = new events.Rule(this, 'Rule', { + schedule: events.Schedule.rate(Duration.hours(1)), +}); + +rule.addTarget(new targets.AwsApi({ + service: 'ECS', + action: 'updateService', + parameters: { + service: 'my-service', + forceNewDeployment: true, + }, +})); +``` + +### IAM Permissions + +By default, the AwsApi target automatically creates the necessary IAM permissions based on the service and action you specify. The permission format follows the pattern: `service:Action`. + +For example: + +- `ECS` service with `updateService` action → `ecs:UpdateService` permission +- `RDS` service with `createDBSnapshot` action → `rds:CreateDBSnapshot` permission + +### Custom IAM Policy + +In some cases, you may need to provide a custom IAM policy statement, especially when: + +- You need to restrict permissions to specific resources (instead of `*`) +- The service requires additional permissions beyond the main action +- You want more granular control over the permissions + +```ts +import * as iam from 'aws-cdk-lib/aws-iam'; +import * as s3 from 'aws-cdk-lib/aws-s3'; + +declare const rule: events.Rule; +declare const bucket: s3.Bucket; + +rule.addTarget(new targets.AwsApi({ + service: 's3', + action: 'GetBucketEncryption', + parameters: { + Bucket: bucket.bucketName, + }, + policyStatement: new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ['s3:GetEncryptionConfiguration'], + resources: [bucket.bucketArn], + }), +})); +``` + ## Invoke an API Destination Use the `targets.ApiDestination` target to trigger an external API. You need to @@ -636,7 +698,7 @@ rule.addTarget(new targets.RedshiftQuery(workgroup.attrWorkgroupWorkgroupArn, { ## Publish to an SNS Topic -Use the `SnsTopic` target to publish to an SNS Topic. +Use the `SnsTopic` target to publish to an SNS Topic. The code snippet below creates the scheduled event rule that publishes to an SNS Topic using a resource policy. @@ -664,4 +726,4 @@ const rule = new events.Rule(this, 'Rule', { }); rule.addTarget(new targets.SnsTopic(topic, { authorizeUsingRole: true })); -``` \ No newline at end of file +``` diff --git a/packages/aws-cdk-lib/aws-events/lib/rule.ts b/packages/aws-cdk-lib/aws-events/lib/rule.ts index 5ec0870f5d28e..8974dca825288 100644 --- a/packages/aws-cdk-lib/aws-events/lib/rule.ts +++ b/packages/aws-cdk-lib/aws-events/lib/rule.ts @@ -7,7 +7,7 @@ import { IRule } from './rule-ref'; import { Schedule } from './schedule'; import { IRuleTarget } from './target'; import { mergeEventPattern, renderEventPattern } from './util'; -import { IRole, PolicyStatement, Role, ServicePrincipal } from '../../aws-iam'; +import { IRole, IRoleRef, PolicyStatement, Role, ServicePrincipal } from '../../aws-iam'; import { App, IResource, Lazy, Names, Resource, Stack, Token, TokenComparison, PhysicalName, ArnFormat, Annotations, ValidationError } from '../../core'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; import { propertyInjectable } from '../../core/lib/prop-injectable'; @@ -61,7 +61,7 @@ export interface RuleProps extends EventCommonOptions { * * @default - No role associated */ - readonly role?: IRole; + readonly role?: IRoleRef; } /** @@ -129,7 +129,7 @@ export class Rule extends Resource implements IRule { eventPattern: Lazy.any({ produce: () => this._renderEventPattern() }), targets: Lazy.any({ produce: () => this.renderTargets() }), eventBusName: props.eventBus && props.eventBus.eventBusName, - roleArn: props.role?.roleArn, + roleArn: props.role?.roleRef.roleArn, }); this.ruleArn = this.getResourceArnAttribute(resource.attrArn, { diff --git a/packages/aws-cdk-lib/aws-fsx/lib/file-system.ts b/packages/aws-cdk-lib/aws-fsx/lib/file-system.ts index cfb71a8021367..226d9689fd4bd 100644 --- a/packages/aws-cdk-lib/aws-fsx/lib/file-system.ts +++ b/packages/aws-cdk-lib/aws-fsx/lib/file-system.ts @@ -1,5 +1,5 @@ import { Connections, IConnectable, ISecurityGroup, IVpc } from '../../aws-ec2'; -import { IKey } from '../../aws-kms'; +import { IKeyRef } from '../../aws-kms'; import { RemovalPolicy, Resource } from '../../core'; /** @@ -54,7 +54,7 @@ export interface FileSystemProps { * * @default - the aws/fsx default KMS key for the AWS account being deployed into. */ - readonly kmsKey?: IKey; + readonly kmsKey?: IKeyRef; /** * Security Group to assign to this file system. diff --git a/packages/aws-cdk-lib/aws-fsx/lib/lustre-file-system.ts b/packages/aws-cdk-lib/aws-fsx/lib/lustre-file-system.ts index d4bb8e483765f..7af63ed1937cd 100644 --- a/packages/aws-cdk-lib/aws-fsx/lib/lustre-file-system.ts +++ b/packages/aws-cdk-lib/aws-fsx/lib/lustre-file-system.ts @@ -349,7 +349,7 @@ export class LustreFileSystem extends FileSystemBase { fileSystemType: LustreFileSystem.DEFAULT_FILE_SYSTEM_TYPE, subnetIds: [props.vpcSubnet.subnetId], backupId: props.backupId, - kmsKeyId: (props.kmsKey ? props.kmsKey.keyId : undefined), + kmsKeyId: (props.kmsKey ? props.kmsKey.keyRef.keyId : undefined), lustreConfiguration, securityGroupIds: [securityGroup.securityGroupId], storageCapacity: props.storageCapacityGiB, diff --git a/packages/aws-cdk-lib/aws-iam/lib/managed-policy.ts b/packages/aws-cdk-lib/aws-iam/lib/managed-policy.ts index ccf4f43af17a4..869f1f78f0ac1 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/managed-policy.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/managed-policy.ts @@ -1,6 +1,12 @@ import { Construct, Node } from 'constructs'; -import { IGroup } from './group'; -import { CfnManagedPolicy, IManagedPolicyRef, ManagedPolicyReference } from './iam.generated'; +import { + CfnManagedPolicy, + IGroupRef, + IManagedPolicyRef, + IRoleRef, + IUserRef, + ManagedPolicyReference, +} from './iam.generated'; import { PolicyDocument } from './policy-document'; import { PolicyStatement } from './policy-statement'; import { AddToPrincipalPolicyResult, IGrantable, IPrincipal, PrincipalPolicyFragment } from './principals'; @@ -79,7 +85,7 @@ export interface ManagedPolicyProps { * * @default - No groups. */ - readonly groups?: IGroup[]; + readonly groups?: IGroupRef[]; /** * Initial set of permissions to add to this policy document. @@ -229,9 +235,9 @@ export class ManagedPolicy extends Resource implements IManagedPolicy, IGrantabl public readonly grantPrincipal: IPrincipal; - private readonly roles = new Array(); - private readonly users = new Array(); - private readonly groups = new Array(); + private readonly roles = new Array(); + private readonly users = new Array(); + private readonly groups = new Array(); private readonly _precreatedPolicy?: IManagedPolicy; constructor(scope: Construct, id: string, props: ManagedPolicyProps = {}) { @@ -261,9 +267,9 @@ export class ManagedPolicy extends Resource implements IManagedPolicy, IGrantabl managedPolicyName: this.physicalName, description: this.description, path: this.path, - roles: undefinedIfEmpty(() => this.roles.map(r => r.roleName)), - users: undefinedIfEmpty(() => this.users.map(u => u.userName)), - groups: undefinedIfEmpty(() => this.groups.map(g => g.groupName)), + roles: undefinedIfEmpty(() => this.roles.map(r => r.roleRef.roleName)), + users: undefinedIfEmpty(() => this.users.map(u => u.userRef.userName)), + groups: undefinedIfEmpty(() => this.groups.map(g => g.groupRef.groupName)), }); // arn:aws:iam::123456789012:policy/teststack-CreateTestDBPolicy-16M23YE3CS700 @@ -315,8 +321,8 @@ export class ManagedPolicy extends Resource implements IManagedPolicy, IGrantabl * Attaches this policy to a user. */ @MethodMetadata() - public attachToUser(user: IUser) { - if (this.users.find(u => u.userArn === user.userArn)) { return; } + public attachToUser(user: IUserRef) { + if (this.users.find(u => u.userRef.userArn === user.userRef.userArn)) { return; } this.users.push(user); } @@ -325,7 +331,7 @@ export class ManagedPolicy extends Resource implements IManagedPolicy, IGrantabl */ @MethodMetadata() public attachToRole(role: IRole) { - if (this.roles.find(r => r.roleArn === role.roleArn)) { return; } + if (this.roles.find(r => r.roleRef.roleArn === role.roleArn)) { return; } this.roles.push(role); } @@ -333,8 +339,8 @@ export class ManagedPolicy extends Resource implements IManagedPolicy, IGrantabl * Attaches this policy to a group. */ @MethodMetadata() - public attachToGroup(group: IGroup) { - if (this.groups.find(g => g.groupArn === group.groupArn)) { return; } + public attachToGroup(group: IGroupRef) { + if (this.groups.find(g => g.groupRef.groupArn === group.groupRef.groupArn)) { return; } this.groups.push(group); } diff --git a/packages/aws-cdk-lib/aws-iam/lib/principals.ts b/packages/aws-cdk-lib/aws-iam/lib/principals.ts index 2651acf9a7d72..4f33045a7ccbd 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/principals.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/principals.ts @@ -1,5 +1,5 @@ import { IDependable } from 'constructs'; -import { IOpenIdConnectProvider } from './oidc-provider'; +import { IOIDCProviderRef, ISAMLProviderRef } from './iam.generated'; import { PolicyDocument } from './policy-document'; import { Condition, Conditions, PolicyStatement } from './policy-statement'; import { defaultAddPrincipalToAssumeRole } from './private/assume-role-policy'; @@ -756,8 +756,8 @@ export class OpenIdConnectPrincipal extends WebIdentityPrincipal { * @param conditions The conditions under which the policy is in effect. * See [the IAM documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html). */ - constructor(openIdConnectProvider: IOpenIdConnectProvider, conditions: Conditions = {}) { - super(openIdConnectProvider.openIdConnectProviderArn, conditions ?? {}); + constructor(openIdConnectProvider: IOIDCProviderRef, conditions: Conditions = {}) { + super(openIdConnectProvider.oidcProviderRef.oidcProviderArn, conditions ?? {}); } public get policyFragment(): PrincipalPolicyFragment { @@ -773,8 +773,8 @@ export class OpenIdConnectPrincipal extends WebIdentityPrincipal { * Principal entity that represents a SAML federated identity provider */ export class SamlPrincipal extends FederatedPrincipal { - constructor(samlProvider: ISamlProvider, conditions: Conditions) { - super(samlProvider.samlProviderArn, conditions, 'sts:AssumeRoleWithSAML'); + constructor(samlProvider: ISAMLProviderRef, conditions: Conditions) { + super(samlProvider.samlProviderRef.samlProviderArn, conditions, 'sts:AssumeRoleWithSAML'); } public toString() { @@ -791,7 +791,7 @@ export class SamlConsolePrincipal extends SamlPrincipal { super(samlProvider, { ...conditions, StringEquals: { - 'SAML:aud': RegionInfo.get(samlProvider.stack.region).samlSignOnUrl ?? 'https://signin.aws.amazon.com/saml', + 'SAML:aud': RegionInfo.get(cdk.Stack.of(samlProvider).region).samlSignOnUrl ?? 'https://signin.aws.amazon.com/saml', }, }); } diff --git a/packages/aws-cdk-lib/aws-iam/lib/user.ts b/packages/aws-cdk-lib/aws-iam/lib/user.ts index 67caa906d33c6..77a62e5d9d303 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/user.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/user.ts @@ -215,7 +215,7 @@ export class User extends Resource implements IIdentity, IUser { public addToGroup(group: IGroup): void { new CfnUserToGroupAddition(Stack.of(group), `${this.userName}Group${this.groupId}`, { - groupName: group.groupName, + groupName: group.groupRef.groupName, users: [this.userName], }); this.groupId += 1; diff --git a/packages/aws-cdk-lib/aws-kms/lib/key.ts b/packages/aws-cdk-lib/aws-kms/lib/key.ts index 5d279e1611ada..461a309cafe55 100644 --- a/packages/aws-cdk-lib/aws-kms/lib/key.ts +++ b/packages/aws-cdk-lib/aws-kms/lib/key.ts @@ -791,8 +791,8 @@ export class Key extends KeyBase { * This method can only be used if the `returnDummyKeyOnMissing` option * is set to `true` in the `options` for the `Key.fromLookup()` method. */ - public static isLookupDummy(key: IKey): boolean { - return key.keyId === Key.DEFAULT_DUMMY_KEY_ID; + public static isLookupDummy(key: IKeyRef): boolean { + return key.keyRef.keyId === Key.DEFAULT_DUMMY_KEY_ID; } public readonly keyArn: string; diff --git a/packages/aws-cdk-lib/aws-lambda/lib/code.ts b/packages/aws-cdk-lib/aws-lambda/lib/code.ts index 3f72eab2b9c8f..2b7ea33756bc6 100644 --- a/packages/aws-cdk-lib/aws-lambda/lib/code.ts +++ b/packages/aws-cdk-lib/aws-lambda/lib/code.ts @@ -3,7 +3,7 @@ import { Construct } from 'constructs'; import * as ecr from '../../aws-ecr'; import * as ecr_assets from '../../aws-ecr-assets'; import * as iam from '../../aws-iam'; -import { IKey } from '../../aws-kms'; +import { IKeyRef } from '../../aws-kms'; import * as s3 from '../../aws-s3'; import * as s3_assets from '../../aws-s3-assets'; import * as cdk from '../../core'; @@ -338,7 +338,7 @@ export class S3CodeV2 extends Code { objectKey: this.key, objectVersion: this.options?.objectVersion, }, - sourceKMSKeyArn: this.options?.sourceKMSKey?.keyArn, + sourceKMSKeyArn: this.options?.sourceKMSKey?.keyRef.keyArn, }; } } @@ -400,7 +400,7 @@ export class AssetCode extends Code { bucketName: this.asset.s3BucketName, objectKey: this.asset.s3ObjectKey, }, - sourceKMSKeyArn: this.options.sourceKMSKey?.keyArn, + sourceKMSKeyArn: this.options.sourceKMSKey?.keyRef.keyArn, }; } @@ -450,7 +450,7 @@ export interface CfnParametersCodeProps { * The ARN of the KMS key used to encrypt the handler code. * @default - the default server-side encryption with Amazon S3 managed keys(SSE-S3) key will be used. */ - readonly sourceKMSKey?: IKey; + readonly sourceKMSKey?: IKeyRef; } /** @@ -463,7 +463,7 @@ export class CfnParametersCode extends Code { public readonly isInline = false; private _bucketNameParam?: cdk.CfnParameter; private _objectKeyParam?: cdk.CfnParameter; - private _sourceKMSKey?: IKey; + private _sourceKMSKey?: IKeyRef; constructor(props: CfnParametersCodeProps = {}) { super(); @@ -491,7 +491,7 @@ export class CfnParametersCode extends Code { bucketName: this._bucketNameParam.valueAsString, objectKey: this._objectKeyParam.valueAsString, }, - sourceKMSKeyArn: this._sourceKMSKey?.keyArn, + sourceKMSKeyArn: this._sourceKMSKey?.keyRef.keyArn, }; } @@ -720,5 +720,5 @@ export interface BucketOptions { * The ARN of the KMS key used to encrypt the handler code. * @default - the default server-side encryption with Amazon S3 managed keys(SSE-S3) key will be used. */ - readonly sourceKMSKey?: IKey; + readonly sourceKMSKey?: IKeyRef; } diff --git a/packages/aws-cdk-lib/aws-lambda/lib/function.ts b/packages/aws-cdk-lib/aws-lambda/lib/function.ts index 864faae421823..0eef2a936794f 100644 --- a/packages/aws-cdk-lib/aws-lambda/lib/function.ts +++ b/packages/aws-cdk-lib/aws-lambda/lib/function.ts @@ -3,7 +3,6 @@ import { AdotInstrumentationConfig, AdotLambdaExecWrapper } from './adot-layers' import { AliasOptions, Alias } from './alias'; import { Architecture } from './architecture'; import { Code, CodeConfig } from './code'; -import { ICodeSigningConfig } from './code-signing-config'; import { EventInvokeConfigOptions } from './event-invoke-config'; import { IEventSource } from './event-source'; import { FileSystem } from './filesystem'; @@ -12,7 +11,7 @@ import { calculateFunctionHash, trimFromStart } from './function-hash'; import { Handler } from './handler'; import { LambdaInsightsVersion } from './lambda-insights'; import { Version, VersionOptions } from './lambda-version'; -import { CfnFunction } from './lambda.generated'; +import { CfnFunction, ICodeSigningConfigRef } from './lambda.generated'; import { LayerVersion, ILayerVersion } from './layers'; import { LogRetentionRetryOptions } from './log-retention'; import { ParamsAndSecretsLayerVersion } from './params-and-secrets-layers'; @@ -524,14 +523,14 @@ export interface FunctionOptions extends EventInvokeConfigOptions { * * @default - AWS Lambda creates and uses an AWS managed customer master key (CMK). */ - readonly environmentEncryption?: kms.IKey; + readonly environmentEncryption?: kms.IKeyRef; /** * Code signing config associated with this function * * @default - Not Sign the Code */ - readonly codeSigningConfig?: ICodeSigningConfig; + readonly codeSigningConfig?: ICodeSigningConfigRef; /** * DEPRECATED @@ -1090,9 +1089,9 @@ export class Function extends FunctionBase { entryPoint: code.image?.entrypoint, workingDirectory: code.image?.workingDirectory, }), - kmsKeyArn: props.environmentEncryption?.keyArn, + kmsKeyArn: props.environmentEncryption?.keyRef.keyArn, fileSystemConfigs, - codeSigningConfigArn: props.codeSigningConfig?.codeSigningConfigArn, + codeSigningConfigArn: props.codeSigningConfig?.codeSigningConfigRef.codeSigningConfigArn, architectures: this._architecture ? [this._architecture.name] : undefined, runtimeManagementConfig: props.runtimeManagementMode?.runtimeManagementConfig, snapStart: this.configureSnapStart(props), diff --git a/packages/aws-cdk-lib/aws-logs/lib/cross-account-destination.ts b/packages/aws-cdk-lib/aws-logs/lib/cross-account-destination.ts index e6e1c8fdae054..382cac70bb6d3 100644 --- a/packages/aws-cdk-lib/aws-logs/lib/cross-account-destination.ts +++ b/packages/aws-cdk-lib/aws-logs/lib/cross-account-destination.ts @@ -24,7 +24,7 @@ export interface CrossAccountDestinationProps { * * The role must be assumable by 'logs.{REGION}.amazonaws.com'. */ - readonly role: iam.IRole; + readonly role: iam.IRoleRef; /** * The log destination target's ARN @@ -84,7 +84,7 @@ export class CrossAccountDestination extends cdk.Resource implements ILogSubscri destinationName: this.physicalName!, // Must be stringified policy destinationPolicy: this.lazyStringifiedPolicyDocument(), - roleArn: props.role.roleArn, + roleArn: props.role.roleRef.roleArn, targetArn: props.targetArn, }); diff --git a/packages/aws-cdk-lib/aws-logs/lib/data-protection-policy.ts b/packages/aws-cdk-lib/aws-logs/lib/data-protection-policy.ts index 1d7674b34113a..731c06f49031d 100644 --- a/packages/aws-cdk-lib/aws-logs/lib/data-protection-policy.ts +++ b/packages/aws-cdk-lib/aws-logs/lib/data-protection-policy.ts @@ -1,7 +1,8 @@ import { Construct } from 'constructs'; import { ILogGroup } from './log-group'; -import { IBucket } from '../../aws-s3'; +import { IBucketRef } from '../../aws-s3'; import { Stack, UnscopedValidationError } from '../../core'; + /** * Creates a data protection policy for CloudWatch Logs log groups. */ @@ -32,7 +33,7 @@ export class DataProtectionPolicy { if (this.dataProtectionPolicyProps.s3BucketAuditDestination) { findingsDestination.S3 = { - Bucket: this.dataProtectionPolicyProps.s3BucketAuditDestination.bucketName, + Bucket: this.dataProtectionPolicyProps.s3BucketAuditDestination.bucketRef.bucketName, }; } @@ -162,7 +163,7 @@ export interface DataProtectionPolicyProps { * * @default - no S3 bucket audit destination */ - readonly s3BucketAuditDestination?: IBucket; + readonly s3BucketAuditDestination?: IBucketRef; /** * Amazon Data Firehose delivery stream to send audit findings to. The delivery stream must already exist. diff --git a/packages/aws-cdk-lib/aws-logs/lib/log-group.ts b/packages/aws-cdk-lib/aws-logs/lib/log-group.ts index 67621ec498031..903e6bf900032 100644 --- a/packages/aws-cdk-lib/aws-logs/lib/log-group.ts +++ b/packages/aws-cdk-lib/aws-logs/lib/log-group.ts @@ -514,7 +514,7 @@ export interface LogGroupProps { * * @default Server-side encryption managed by the CloudWatch Logs service */ - readonly encryptionKey?: kms.IKey; + readonly encryptionKey?: kms.IKeyRef; /** * Name of the log group. @@ -666,7 +666,7 @@ export class LogGroup extends LogGroupBase { } const resource = new CfnLogGroup(this, 'Resource', { - kmsKeyId: props.encryptionKey?.keyArn, + kmsKeyId: props.encryptionKey?.keyRef.keyArn, logGroupClass, logGroupName: this.physicalName, retentionInDays, diff --git a/packages/aws-cdk-lib/aws-logs/lib/subscription-filter.ts b/packages/aws-cdk-lib/aws-logs/lib/subscription-filter.ts index 10268f11cbfe1..a6b2331f3e5b5 100644 --- a/packages/aws-cdk-lib/aws-logs/lib/subscription-filter.ts +++ b/packages/aws-cdk-lib/aws-logs/lib/subscription-filter.ts @@ -80,7 +80,7 @@ export class SubscriptionFilter extends Resource { new CfnSubscriptionFilter(this, 'Resource', { logGroupName: props.logGroup.logGroupName, destinationArn: destProps.arn, - roleArn: destProps.role && destProps.role.roleArn, + roleArn: destProps.role?.roleArn, filterPattern: props.filterPattern.logPatternString, filterName: this.physicalName, distribution: props.distribution, diff --git a/packages/aws-cdk-lib/aws-opensearchservice/lib/domain.ts b/packages/aws-cdk-lib/aws-opensearchservice/lib/domain.ts index 26691f38c8f1c..a466b8d4bd83f 100644 --- a/packages/aws-cdk-lib/aws-opensearchservice/lib/domain.ts +++ b/packages/aws-cdk-lib/aws-opensearchservice/lib/domain.ts @@ -258,7 +258,7 @@ export interface EncryptionAtRestOptions { * * @default - uses default aws/es KMS key. */ - readonly kmsKey?: kms.IKey; + readonly kmsKey?: kms.IKeyRef; } /** @@ -276,7 +276,7 @@ export interface CognitoOptions { * * @see https://docs.aws.amazon.com/opensearch-service/latest/developerguide/cognito-auth.html#cognito-auth-prereq */ - readonly role: iam.IRole; + readonly role: iam.IRoleRef; /** * The Amazon Cognito user pool ID that you want Amazon OpenSearch Service to use for OpenSearch Dashboards authentication. @@ -1988,7 +1988,7 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable { encryptionAtRestOptions: { enabled: encryptionAtRestEnabled, kmsKeyId: encryptionAtRestEnabled - ? props.encryptionAtRest?.kmsKey?.keyId + ? props.encryptionAtRest?.kmsKey?.keyRef.keyId : undefined, }, nodeToNodeEncryptionOptions: { enabled: nodeToNodeEncryptionEnabled }, @@ -1996,7 +1996,7 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable { cognitoOptions: props.cognitoDashboardsAuth ? { enabled: true, identityPoolId: props.cognitoDashboardsAuth?.identityPoolId, - roleArn: props.cognitoDashboardsAuth?.role.roleArn, + roleArn: props.cognitoDashboardsAuth?.role.roleRef.roleArn, userPoolId: props.cognitoDashboardsAuth?.userPoolId, } : undefined, vpcOptions: cfnVpcOptions, @@ -2188,7 +2188,7 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable { // empircal evidence shows this is indeed required: https://github.com/aws/aws-cdk/issues/11412 this.accessPolicy.grantPrincipal.addToPrincipalPolicy(new iam.PolicyStatement({ actions: ['kms:List*', 'kms:Describe*', 'kms:CreateGrant'], - resources: [this.encryptionAtRestOptions.kmsKey.keyArn], + resources: [this.encryptionAtRestOptions.kmsKey.keyRef.keyArn], effect: iam.Effect.ALLOW, })); } diff --git a/packages/aws-cdk-lib/aws-rds/README.md b/packages/aws-cdk-lib/aws-rds/README.md index 43e4962f8becc..899053e13aa15 100644 --- a/packages/aws-cdk-lib/aws-rds/README.md +++ b/packages/aws-cdk-lib/aws-rds/README.md @@ -418,6 +418,24 @@ To apply changes of the cluster, such as engine version, in the next scheduled m For details, see [Modifying an Amazon Aurora DB cluster](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Modifying.html). +### Retaining Automated Backups + +By default, when a database cluster is deleted, automated backups are removed immediately unless an AWS Backup policy specifies a point-in-time restore rule. You can control this behavior using the `deleteAutomatedBackups` property: + +```ts +declare const vpc: ec2.IVpc; +// Retain automated backups after cluster deletion +new rds.DatabaseCluster(this, 'Database', { + engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_01_0 }), + writer: rds.ClusterInstance.provisioned('writer'), + vpc, + deleteAutomatedBackups: false, +}); +``` + +When set to `false`, automated backups are retained according to the configured retention period after the cluster is deleted. When set to `true` or not specified (default), automated backups are deleted immediately when the cluster is deleted. +Detail about this feature can be found in the [AWS documentation](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Managing.Backups.Retaining.html). + ### Migrating from instanceProps Creating instances in a `DatabaseCluster` using `instanceProps` & `instances` is diff --git a/packages/aws-cdk-lib/aws-rds/lib/aurora-cluster-instance.ts b/packages/aws-cdk-lib/aws-rds/lib/aurora-cluster-instance.ts index 8c34c13e0f465..a4f458043cfec 100644 --- a/packages/aws-cdk-lib/aws-rds/lib/aurora-cluster-instance.ts +++ b/packages/aws-cdk-lib/aws-rds/lib/aurora-cluster-instance.ts @@ -8,7 +8,7 @@ import { PerformanceInsightRetention } from './props'; import { CfnDBInstance } from './rds.generated'; import { ISubnetGroup } from './subnet-group'; import * as ec2 from '../../aws-ec2'; -import { IRole } from '../../aws-iam'; +import { IRoleRef } from '../../aws-iam'; import * as kms from '../../aws-kms'; import { IResource, Resource, Duration, RemovalPolicy, ArnFormat, FeatureFlags } from '../../core'; import { ValidationError } from '../../core/lib/errors'; @@ -33,7 +33,7 @@ export interface ClusterInstanceBindOptions { * * @default - A role is automatically created for you */ - readonly monitoringRole?: IRole; + readonly monitoringRole?: IRoleRef; /** * The removal policy on the cluster @@ -578,7 +578,7 @@ class AuroraClusterInstance extends Resource implements IAuroraClusterInstance { dbSubnetGroupName: props.isFromLegacyInstanceProps ? props.subnetGroup?.subnetGroupName : undefined, dbParameterGroupName: instanceParameterGroupConfig?.parameterGroupName, monitoringInterval: props.monitoringInterval && props.monitoringInterval.toSeconds(), - monitoringRoleArn: props.monitoringRole && props.monitoringRole.roleArn, + monitoringRoleArn: props.monitoringRole?.roleRef.roleArn, autoMinorVersionUpgrade: props.autoMinorVersionUpgrade, allowMajorVersionUpgrade: props.allowMajorVersionUpgrade, caCertificateIdentifier: props.caCertificate && props.caCertificate.toString(), diff --git a/packages/aws-cdk-lib/aws-rds/lib/cluster-engine.ts b/packages/aws-cdk-lib/aws-rds/lib/cluster-engine.ts index a4d69a77954d9..c1d2d06612bcd 100644 --- a/packages/aws-cdk-lib/aws-rds/lib/cluster-engine.ts +++ b/packages/aws-cdk-lib/aws-rds/lib/cluster-engine.ts @@ -16,14 +16,14 @@ export interface ClusterEngineBindOptions { * * @default - none */ - readonly s3ImportRole?: iam.IRole; + readonly s3ImportRole?: iam.IRoleRef; /** * The role used for S3 exporting. * * @default - none */ - readonly s3ExportRole?: iam.IRole; + readonly s3ExportRole?: iam.IRoleRef; /** * The customer-provided ParameterGroup. @@ -203,13 +203,13 @@ abstract class MySqlClusterEngineBase extends ClusterEngineBase { const s3ImportParam = this.combineImportAndExportRoles ? 'aws_default_s3_role' : 'aurora_load_from_s3_role'; - parameterGroup?.addParameter(s3ImportParam, options.s3ImportRole.roleArn); + parameterGroup?.addParameter(s3ImportParam, options.s3ImportRole.roleRef.roleArn); } if (options.s3ExportRole) { const s3ExportParam = this.combineImportAndExportRoles ? 'aws_default_s3_role' : 'aurora_select_into_s3_role'; - parameterGroup?.addParameter(s3ExportParam, options.s3ExportRole.roleArn); + parameterGroup?.addParameter(s3ExportParam, options.s3ExportRole.roleRef.roleArn); } return { diff --git a/packages/aws-cdk-lib/aws-rds/lib/cluster.ts b/packages/aws-cdk-lib/aws-rds/lib/cluster.ts index d95c689613225..699a5b89aaeb6 100644 --- a/packages/aws-cdk-lib/aws-rds/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-rds/lib/cluster.ts @@ -373,7 +373,7 @@ interface DatabaseClusterBaseProps { * * @default - if storageEncrypted is true then the default master key, no key otherwise */ - readonly storageEncryptionKey?: kms.IKey; + readonly storageEncryptionKey?: kms.IKeyRef; /** * The storage type to be associated with the DB cluster. @@ -500,6 +500,13 @@ interface DatabaseClusterBaseProps { * @default undefined - AWS RDS default setting is `EngineLifecycleSupport.OPEN_SOURCE_RDS_EXTENDED_SUPPORT` */ readonly engineLifecycleSupport?: EngineLifecycleSupport; + + /** + * Specifies whether to remove automated backups immediately after the DB cluster is deleted. + * + * @default undefined - AWS RDS default is to remove automated backups immediately after the DB cluster is deleted, unless the AWS Backup policy specifies a point-in-time restore rule. + */ + readonly deleteAutomatedBackups?: boolean; } /** @@ -954,7 +961,7 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase { databaseName: props.defaultDatabaseName, enableCloudwatchLogsExports: props.cloudwatchLogsExports, // Encryption - kmsKeyId: props.storageEncryptionKey?.keyArn, + kmsKeyId: props.storageEncryptionKey?.keyRef.keyArn, storageEncrypted: props.storageEncryptionKey ? true : props.storageEncrypted, // Tags copyTagsToSnapshot: props.copyTagsToSnapshot ?? true, @@ -968,6 +975,7 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase { monitoringInterval: props.enableClusterLevelEnhancedMonitoring ? props.monitoringInterval?.toSeconds() : undefined, monitoringRoleArn: props.enableClusterLevelEnhancedMonitoring ? this.monitoringRole?.roleArn : undefined, engineLifecycleSupport: props.engineLifecycleSupport, + deleteAutomatedBackups: props.deleteAutomatedBackups, }; } @@ -1828,7 +1836,7 @@ function validatePerformanceInsightsSettings( nodeId?: string; performanceInsightsEnabled?: boolean; performanceInsightRetention?: PerformanceInsightRetention; - performanceInsightEncryptionKey?: kms.IKey; + performanceInsightEncryptionKey?: kms.IKeyRef; }, ): void { const target = instance.nodeId ? `instance \'${instance.nodeId}\'` : '`instanceProps`'; @@ -1856,11 +1864,11 @@ function validatePerformanceInsightsSettings( // undefined or the same as the value at cluster level. if (cluster.performanceInsightEncryptionKey && instance.performanceInsightEncryptionKey) { const clusterKeyArn = cluster.performanceInsightEncryptionKey.keyArn; - const instanceKeyArn = instance.performanceInsightEncryptionKey.keyArn; + const instanceKeyArn = instance.performanceInsightEncryptionKey.keyRef.keyArn; const compared = Token.compareStrings(clusterKeyArn, instanceKeyArn); if (compared === TokenComparison.DIFFERENT) { - throw new ValidationError(`\`performanceInsightEncryptionKey\` for each instance must be the same as the one at cluster level, got ${target}: '${instance.performanceInsightEncryptionKey.keyArn}', cluster: '${cluster.performanceInsightEncryptionKey.keyArn}'`, cluster); + throw new ValidationError(`\`performanceInsightEncryptionKey\` for each instance must be the same as the one at cluster level, got ${target}: '${instance.performanceInsightEncryptionKey.keyRef.keyArn}', cluster: '${cluster.performanceInsightEncryptionKey.keyRef.keyArn}'`, cluster); } // Even if both of cluster and instance keys are unresolved, check if they are the same token. if (compared === TokenComparison.BOTH_UNRESOLVED && clusterKeyArn !== instanceKeyArn) { diff --git a/packages/aws-cdk-lib/aws-rds/lib/instance-engine.ts b/packages/aws-cdk-lib/aws-rds/lib/instance-engine.ts index 462729dd0d780..b72a263949712 100644 --- a/packages/aws-cdk-lib/aws-rds/lib/instance-engine.ts +++ b/packages/aws-cdk-lib/aws-rds/lib/instance-engine.ts @@ -29,14 +29,14 @@ export interface InstanceEngineBindOptions { * * @default - none */ - readonly s3ImportRole?: iam.IRole; + readonly s3ImportRole?: iam.IRoleRef; /** * The role used for S3 exporting. * * @default - none */ - readonly s3ExportRole?: iam.IRole; + readonly s3ExportRole?: iam.IRoleRef; /** * The option group of the database @@ -3043,7 +3043,7 @@ abstract class SqlServerInstanceEngineBase extends InstanceEngineBase { // https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.SQLServer.Options.BackupRestore.html optionGroup.addConfiguration({ name: 'SQLSERVER_BACKUP_RESTORE', - settings: { IAM_ROLE_ARN: s3Role.roleArn }, + settings: { IAM_ROLE_ARN: s3Role.roleRef.roleArn }, }); } diff --git a/packages/aws-cdk-lib/aws-rds/lib/instance.ts b/packages/aws-cdk-lib/aws-rds/lib/instance.ts index 7266f15f8ae30..2b5151895cb97 100644 --- a/packages/aws-cdk-lib/aws-rds/lib/instance.ts +++ b/packages/aws-cdk-lib/aws-rds/lib/instance.ts @@ -597,7 +597,7 @@ export interface DatabaseInstanceNewProps { * * @default - A role is automatically created for you */ - readonly monitoringRole?: iam.IRole; + readonly monitoringRole?: iam.IRoleRef; /** * Whether to enable Performance Insights for the DB instance. @@ -620,7 +620,7 @@ export interface DatabaseInstanceNewProps { * * @default - default master key */ - readonly performanceInsightEncryptionKey?: kms.IKey; + readonly performanceInsightEncryptionKey?: kms.IKeyRef; /** * The database insights mode. @@ -709,7 +709,7 @@ export interface DatabaseInstanceNewProps { * * @default - The role will be created for you if `DatabaseInstanceNewProps#domain` is specified */ - readonly domainRole?: iam.IRole; + readonly domainRole?: iam.IRoleRef; /** * Existing subnet group for the instance. @@ -863,7 +863,7 @@ abstract class DatabaseInstanceNew extends DatabaseInstanceBase implements IData private readonly cloudwatchLogsRetentionRole?: iam.IRole; private readonly domainId?: string; - private readonly domainRole?: iam.IRole; + private readonly domainRole?: iam.IRoleRef; protected enableIamAuthentication?: boolean; @@ -976,11 +976,11 @@ abstract class DatabaseInstanceNew extends DatabaseInstanceBase implements IData enablePerformanceInsights: enablePerformanceInsights || props.enablePerformanceInsights, // fall back to undefined if not set, iops, monitoringInterval: props.monitoringInterval?.toSeconds(), - monitoringRoleArn: monitoringRole?.roleArn, + monitoringRoleArn: monitoringRole?.roleRef.roleArn, multiAz: props.multiAz, dbParameterGroupName: instanceParameterGroupConfig?.parameterGroupName, optionGroupName: props.optionGroup?.optionGroupName, - performanceInsightsKmsKeyId: props.performanceInsightEncryptionKey?.keyArn, + performanceInsightsKmsKeyId: props.performanceInsightEncryptionKey?.keyRef.keyArn, performanceInsightsRetentionPeriod: enablePerformanceInsights ? (props.performanceInsightRetention || PerformanceInsightRetention.DEFAULT) : undefined, @@ -995,7 +995,7 @@ abstract class DatabaseInstanceNew extends DatabaseInstanceBase implements IData vpcSecurityGroups: securityGroups.map(s => s.securityGroupId), maxAllocatedStorage: props.maxAllocatedStorage, domain: this.domainId, - domainIamRoleName: this.domainRole?.roleName, + domainIamRoleName: this.domainRole?.roleRef.roleName, networkType: props.networkType, caCertificateIdentifier: props.caCertificate ? props.caCertificate.toString() : undefined, applyImmediately: props.applyImmediately, @@ -1269,7 +1269,7 @@ export interface DatabaseInstanceProps extends DatabaseInstanceSourceProps { * * @default - default master key if storageEncrypted is true, no key otherwise */ - readonly storageEncryptionKey?: kms.IKey; + readonly storageEncryptionKey?: kms.IKeyRef; } /** @@ -1305,7 +1305,7 @@ export class DatabaseInstance extends DatabaseInstanceSource implements IDatabas const instance = new CfnDBInstance(this, 'Resource', { ...this.sourceCfnProps, characterSetName: props.characterSetName, - kmsKeyId: props.storageEncryptionKey && props.storageEncryptionKey.keyArn, + kmsKeyId: props.storageEncryptionKey && props.storageEncryptionKey.keyRef.keyArn, masterUsername: credentials.username, masterUserPassword: credentials.password?.unsafeUnwrap(), storageEncrypted: props.storageEncryptionKey ? true : props.storageEncrypted, @@ -1478,7 +1478,7 @@ export interface DatabaseInstanceReadReplicaProps extends DatabaseInstanceNewPro * * @default - default master key if storageEncrypted is true, no key otherwise */ - readonly storageEncryptionKey?: kms.IKey; + readonly storageEncryptionKey?: kms.IKeyRef; /** * The allocated storage size, specified in gibibytes (GiB). * @@ -1539,7 +1539,7 @@ export class DatabaseInstanceReadReplica extends DatabaseInstanceNew implements ...this.newCfnProps, // this must be ARN, not ID, because of https://github.com/terraform-providers/terraform-provider-aws/issues/528#issuecomment-391169012 sourceDbInstanceIdentifier: props.sourceDatabaseInstance.instanceArn, - kmsKeyId: props.storageEncryptionKey?.keyArn, + kmsKeyId: props.storageEncryptionKey?.keyRef.keyArn, storageEncrypted: props.storageEncryptionKey ? true : props.storageEncrypted, engine: shouldPassEngine ? engineType : undefined, allocatedStorage: props.allocatedStorage?.toString(), diff --git a/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts b/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts index da82e0ceae05c..aa935d0db1d59 100644 --- a/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts @@ -712,6 +712,27 @@ describe('cluster new api', () => { PreferredMaintenanceWindow: PREFERRED_MAINTENANCE_WINDOW, })); }); + + test.each([true, false])('deleteAutomatedBackups set to %s', (deleteAutomatedBackups) => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'Vpc'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA_MYSQL, + instanceProps: { + vpc, + }, + deleteAutomatedBackups, + }); + + // THEN + const template = Template.fromStack(stack); + template.hasResourceProperties('AWS::RDS::DBCluster', Match.objectLike({ + DeleteAutomatedBackups: deleteAutomatedBackups, + })); + }); }); describe('migrate from instanceProps', () => { diff --git a/packages/aws-cdk-lib/aws-route53/lib/record-set.ts b/packages/aws-cdk-lib/aws-route53/lib/record-set.ts index 315998792f51e..f08260b795873 100644 --- a/packages/aws-cdk-lib/aws-route53/lib/record-set.ts +++ b/packages/aws-cdk-lib/aws-route53/lib/record-set.ts @@ -1033,7 +1033,7 @@ export interface CrossAccountZoneDelegationRecordProps { /** * The delegation role in the parent account */ - readonly delegationRole: iam.IRole; + readonly delegationRole: iam.IRoleRef; /** * The resource record cache time to live (TTL). @@ -1083,7 +1083,7 @@ export class CrossAccountZoneDelegationRecord extends Construct { const addToPrinciplePolicyResult = role.addToPrincipalPolicy(new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['sts:AssumeRole'], - resources: [props.delegationRole.roleArn], + resources: [props.delegationRole.roleRef.roleArn], })); const customResource = new CustomResource(this, 'CrossAccountZoneDelegationCustomResource', { @@ -1091,7 +1091,7 @@ export class CrossAccountZoneDelegationRecord extends Construct { serviceToken: provider.serviceToken, removalPolicy: props.removalPolicy, properties: { - AssumeRoleArn: props.delegationRole.roleArn, + AssumeRoleArn: props.delegationRole.roleRef.roleArn, ParentZoneName: props.parentHostedZoneName, ParentZoneId: props.parentHostedZoneId, DelegatedZoneName: props.delegatedZone.zoneName, diff --git a/packages/aws-cdk-lib/aws-route53/lib/vpc-endpoint-service-domain-name.ts b/packages/aws-cdk-lib/aws-route53/lib/vpc-endpoint-service-domain-name.ts index b77241b68bbe6..a42255b276cbe 100644 --- a/packages/aws-cdk-lib/aws-route53/lib/vpc-endpoint-service-domain-name.ts +++ b/packages/aws-cdk-lib/aws-route53/lib/vpc-endpoint-service-domain-name.ts @@ -1,5 +1,5 @@ import { Construct } from 'constructs'; -import { IVpcEndpointService } from '../../aws-ec2'; +import { IVPCEndpointServiceRef } from '../../aws-ec2'; import { Fn, Names, Stack } from '../../core'; import { ValidationError } from '../../core/lib/errors'; import { md5hash } from '../../core/lib/helpers-internal'; @@ -14,7 +14,7 @@ export interface VpcEndpointServiceDomainNameProps { /** * The VPC Endpoint Service to configure Private DNS for */ - readonly endpointService: IVpcEndpointService; + readonly endpointService: IVPCEndpointServiceRef; /** * The domain name to use. @@ -37,7 +37,7 @@ export interface VpcEndpointServiceDomainNameProps { */ export class VpcEndpointServiceDomainName extends Construct { // Track all domain names created, so someone doesn't accidentally associate two domains with a single service - private static readonly endpointServices: IVpcEndpointService[] = []; + private static readonly endpointServices: IVPCEndpointServiceRef[] = []; // Track all domain names created, so someone doesn't accidentally associate two domains with a single service private static readonly endpointServicesMap: { [endpointService: string]: string} = {}; @@ -58,7 +58,7 @@ export class VpcEndpointServiceDomainName extends Construct { super(scope, id); const serviceUniqueId = Names.nodeUniqueId(props.endpointService.node); - const serviceId = props.endpointService.vpcEndpointServiceId; + const serviceId = props.endpointService.vpcEndpointServiceRef.serviceId; this.domainName = props.domainName; // Make sure a user doesn't accidentally add multiple domains diff --git a/packages/aws-cdk-lib/aws-s3-assets/lib/asset.ts b/packages/aws-cdk-lib/aws-s3-assets/lib/asset.ts index b0a604e3dcf6a..5e93ef978ad7f 100644 --- a/packages/aws-cdk-lib/aws-s3-assets/lib/asset.ts +++ b/packages/aws-cdk-lib/aws-s3-assets/lib/asset.ts @@ -54,7 +54,7 @@ export interface AssetOptions extends CopyOptions, cdk.FileCopyOptions, cdk.Asse * The ARN of the KMS key used to encrypt the handler code. * @default - the default server-side encryption with Amazon S3 managed keys(SSE-S3) key will be used. */ - readonly sourceKMSKey?: kms.IKey; + readonly sourceKMSKey?: kms.IKeyRef; /** * A display name for this asset diff --git a/packages/aws-cdk-lib/aws-s3-deployment/lib/bucket-deployment.ts b/packages/aws-cdk-lib/aws-s3-deployment/lib/bucket-deployment.ts index ea9a8c53bd420..dbc590a32556a 100644 --- a/packages/aws-cdk-lib/aws-s3-deployment/lib/bucket-deployment.ts +++ b/packages/aws-cdk-lib/aws-s3-deployment/lib/bucket-deployment.ts @@ -107,7 +107,7 @@ export interface BucketDeploymentProps { * * @default - No invalidation occurs */ - readonly distribution?: cloudfront.IDistribution; + readonly distribution?: cloudfront.IDistributionRef; /** * The file paths to invalidate in the CloudFront distribution. @@ -467,7 +467,7 @@ export class BucketDeployment extends Construct { Include: props.include, UserMetadata: props.metadata ? mapUserMetadata(props.metadata) : undefined, SystemMetadata: mapSystemMetadata(props), - DistributionId: props.distribution?.distributionId, + DistributionId: props.distribution?.distributionRef.distributionId, DistributionPaths: props.distributionPaths, SignContent: props.signContent, OutputObjectKeys: props.outputObjectKeys ?? true, @@ -957,8 +957,9 @@ export interface UserDefinedObjectMetadata { } function sourceConfigEqual(stack: cdk.Stack, a: SourceConfig, b: SourceConfig) { + const resolveName = (config: SourceConfig) => JSON.stringify(stack.resolve(config.bucket.bucketName)); return ( - JSON.stringify(stack.resolve(a.bucket.bucketName)) === JSON.stringify(stack.resolve(b.bucket.bucketName)) + resolveName(a) === resolveName(b) && a.zipObjectKey === b.zipObjectKey && a.markers === undefined && b.markers === undefined); } diff --git a/packages/aws-cdk-lib/aws-s3-notifications/lib/lambda.ts b/packages/aws-cdk-lib/aws-s3-notifications/lib/lambda.ts index 45a7a44773f63..62ce228fa3c6a 100644 --- a/packages/aws-cdk-lib/aws-s3-notifications/lib/lambda.ts +++ b/packages/aws-cdk-lib/aws-s3-notifications/lib/lambda.ts @@ -12,19 +12,19 @@ export class LambdaDestination implements s3.IBucketNotificationDestination { constructor(private readonly fn: lambda.IFunction) { } - public bind(scope: Construct, bucket: s3.IBucket): s3.BucketNotificationDestinationConfig { + public bind(scope: Construct, bucket: s3.IBucketRef): s3.BucketNotificationDestinationConfig { const permissionId = `AllowBucketNotificationsTo${Names.nodeUniqueId(this.fn.permissionsNode)}`; if (!(bucket instanceof Construct)) { throw new ValidationError(`LambdaDestination for function ${Names.nodeUniqueId(this.fn.permissionsNode)} can only be configured on a - bucket construct (Bucket ${bucket.bucketName})`, scope); + bucket construct (Bucket ${bucket.bucketRef.bucketName})`, scope); } if (bucket.node.tryFindChild(permissionId) === undefined) { this.fn.addPermission(permissionId, { sourceAccount: Stack.of(bucket).account, principal: new iam.ServicePrincipal('s3.amazonaws.com'), - sourceArn: bucket.bucketArn, + sourceArn: bucket.bucketRef.bucketArn, // Placing the permissions node in the same scope as the s3 bucket. // Otherwise, there is a circular dependency when the s3 bucket // and lambda functions declared in different stacks. diff --git a/packages/aws-cdk-lib/aws-s3-notifications/lib/sns.ts b/packages/aws-cdk-lib/aws-s3-notifications/lib/sns.ts index a1276c5d0caec..fb734d20f729d 100644 --- a/packages/aws-cdk-lib/aws-s3-notifications/lib/sns.ts +++ b/packages/aws-cdk-lib/aws-s3-notifications/lib/sns.ts @@ -12,13 +12,13 @@ export class SnsDestination implements s3.IBucketNotificationDestination { constructor(private readonly topic: sns.ITopic) { } - public bind(scope: Construct, bucket: s3.IBucket): s3.BucketNotificationDestinationConfig { + public bind(scope: Construct, bucket: s3.IBucketRef): s3.BucketNotificationDestinationConfig { this.topic.addToResourcePolicy(new iam.PolicyStatement({ principals: [new iam.ServicePrincipal('s3.amazonaws.com')], actions: ['sns:Publish'], resources: [this.topic.topicArn], conditions: { - ArnLike: { 'aws:SourceArn': bucket.bucketArn }, + ArnLike: { 'aws:SourceArn': bucket.bucketRef.bucketArn }, }, })); diff --git a/packages/aws-cdk-lib/aws-s3-notifications/lib/sqs.ts b/packages/aws-cdk-lib/aws-s3-notifications/lib/sqs.ts index c23901f4e100a..4e698e6c0b7fa 100644 --- a/packages/aws-cdk-lib/aws-s3-notifications/lib/sqs.ts +++ b/packages/aws-cdk-lib/aws-s3-notifications/lib/sqs.ts @@ -15,10 +15,10 @@ export class SqsDestination implements s3.IBucketNotificationDestination { * Allows using SQS queues as destinations for bucket notifications. * Use `bucket.onEvent(event, queue)` to subscribe. */ - public bind(_scope: Construct, bucket: s3.IBucket): s3.BucketNotificationDestinationConfig { + public bind(_scope: Construct, bucket: s3.IBucketRef): s3.BucketNotificationDestinationConfig { this.queue.grantSendMessages(new iam.ServicePrincipal('s3.amazonaws.com', { conditions: { - ArnLike: { 'aws:SourceArn': bucket.bucketArn }, + ArnLike: { 'aws:SourceArn': bucket.bucketRef.bucketArn }, }, })); diff --git a/packages/aws-cdk-lib/aws-s3/lib/destination.ts b/packages/aws-cdk-lib/aws-s3/lib/destination.ts index 0c11c6bdc8b29..0e896aeb1dbd2 100644 --- a/packages/aws-cdk-lib/aws-s3/lib/destination.ts +++ b/packages/aws-cdk-lib/aws-s3/lib/destination.ts @@ -1,5 +1,5 @@ import { Construct, IDependable } from 'constructs'; -import { IBucket } from './bucket'; +import { IBucketRef } from './s3.generated'; /** * Implemented by constructs that can be used as bucket notification destinations. @@ -12,7 +12,7 @@ export interface IBucketNotificationDestination { * idempotency in each destination. * @param bucket The bucket object to bind to */ - bind(scope: Construct, bucket: IBucket): BucketNotificationDestinationConfig; + bind(scope: Construct, bucket: IBucketRef): BucketNotificationDestinationConfig; } /** diff --git a/packages/aws-cdk-lib/aws-secretsmanager/lib/secret.ts b/packages/aws-cdk-lib/aws-secretsmanager/lib/secret.ts index db0f084c90d6a..5e5426d13a414 100644 --- a/packages/aws-cdk-lib/aws-secretsmanager/lib/secret.ts +++ b/packages/aws-cdk-lib/aws-secretsmanager/lib/secret.ts @@ -724,7 +724,7 @@ export class Secret extends SecretBase { * @param encryptionKey The customer-managed encryption key to use for encrypting the secret value. */ @MethodMetadata() - public addReplicaRegion(region: string, encryptionKey?: kms.IKey): void { + public addReplicaRegion(region: string, encryptionKey?: kms.IKeyRef): void { const stack = Stack.of(this); if (!Token.isUnresolved(stack.region) && !Token.isUnresolved(region) && region === stack.region) { throw new ValidationError('Cannot add the region where this stack is deployed as a replica region.', this); @@ -732,7 +732,7 @@ export class Secret extends SecretBase { this.replicaRegions.push({ region, - kmsKeyId: encryptionKey?.keyArn, + kmsKeyId: encryptionKey?.keyRef.keyArn, }); } } diff --git a/packages/aws-cdk-lib/aws-servicecatalog/lib/constraints.ts b/packages/aws-cdk-lib/aws-servicecatalog/lib/constraints.ts index 4375e8b1de1a9..09a308930eff5 100644 --- a/packages/aws-cdk-lib/aws-servicecatalog/lib/constraints.ts +++ b/packages/aws-cdk-lib/aws-servicecatalog/lib/constraints.ts @@ -39,7 +39,7 @@ export interface StackSetsConstraintOptions extends CommonConstraintOptions { /** * IAM role used to administer the StackSets configuration. */ - readonly adminRole: iam.IRole; + readonly adminRole: iam.IRoleRef; /** * IAM role used to provision the products in the Stacks. diff --git a/packages/aws-cdk-lib/aws-servicecatalog/lib/private/association-manager.ts b/packages/aws-cdk-lib/aws-servicecatalog/lib/private/association-manager.ts index dd777922ffbee..1e4896f14847d 100644 --- a/packages/aws-cdk-lib/aws-servicecatalog/lib/private/association-manager.ts +++ b/packages/aws-cdk-lib/aws-servicecatalog/lib/private/association-manager.ts @@ -100,9 +100,9 @@ export class AssociationManager { } } - public static setLaunchRole(portfolio: IPortfolio, product: IProduct, launchRole: iam.IRole, options: CommonConstraintOptions): void { + public static setLaunchRole(portfolio: IPortfolio, product: IProduct, launchRole: iam.IRoleRef, options: CommonConstraintOptions): void { this.setLaunchRoleConstraint(portfolio, product, options, { - roleArn: launchRole.roleArn, + roleArn: launchRole.roleRef.roleArn, }); } @@ -128,7 +128,7 @@ export class AssociationManager { productId: product.productId, accountList: options.accounts, regionList: options.regions, - adminRole: options.adminRole.roleArn, + adminRole: options.adminRole.roleRef.roleArn, executionRole: options.executionRoleName, stackInstanceControl: options.allowStackSetInstanceOperations ? 'ALLOWED' : 'NOT_ALLOWED', }); diff --git a/packages/aws-cdk-lib/aws-sns/lib/topic.ts b/packages/aws-cdk-lib/aws-sns/lib/topic.ts index 261be3c006666..bfe7d736ba12a 100644 --- a/packages/aws-cdk-lib/aws-sns/lib/topic.ts +++ b/packages/aws-cdk-lib/aws-sns/lib/topic.ts @@ -1,7 +1,7 @@ import { Construct } from 'constructs'; import { CfnTopic } from './sns.generated'; import { ITopic, TopicBase } from './topic-base'; -import { IRole } from '../../aws-iam'; +import { IRoleRef } from '../../aws-iam'; import { IKey, Key } from '../../aws-kms'; import { ArnFormat, Lazy, Names, Stack, Token } from '../../core'; import { ValidationError } from '../../core/lib/errors'; @@ -147,14 +147,14 @@ export interface LoggingConfig { * * @default None */ - readonly failureFeedbackRole?: IRole; + readonly failureFeedbackRole?: IRoleRef; /** * The IAM role to be used when logging successful message deliveries in Amazon CloudWatch. * * @default None */ - readonly successFeedbackRole?: IRole; + readonly successFeedbackRole?: IRoleRef; /** * The percentage of successful message deliveries to be logged in Amazon CloudWatch. @@ -394,8 +394,8 @@ export class Topic extends TopicBase { } return { protocol: spec.protocol, - failureFeedbackRoleArn: spec.failureFeedbackRole?.roleArn, - successFeedbackRoleArn: spec.successFeedbackRole?.roleArn, + failureFeedbackRoleArn: spec.failureFeedbackRole?.roleRef.roleArn, + successFeedbackRoleArn: spec.successFeedbackRole?.roleRef.roleArn, successFeedbackSampleRate: spec.successFeedbackSampleRate?.toString(), }; }; diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/bedrock/create-model-customization-job.ts b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/bedrock/create-model-customization-job.ts index 7ba7506110a46..088486a9ab4fd 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/bedrock/create-model-customization-job.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/bedrock/create-model-customization-job.ts @@ -198,7 +198,7 @@ export interface BedrockCreateModelCustomizationJobProps extends sfn.TaskStateBa * * @default - use auto generated role */ - readonly role?: iam.IRole; + readonly role?: iam.IRoleRef; /** * The S3 bucket configuration where the training data is stored. @@ -240,7 +240,7 @@ export class BedrockCreateModelCustomizationJob extends sfn.TaskStateBase { protected readonly taskPolicies?: iam.PolicyStatement[]; private readonly integrationPattern: sfn.IntegrationPattern; - private _role: iam.IRole; + private _role: iam.IRoleRef; constructor(scope: Construct, id: string, private readonly props: BedrockCreateModelCustomizationJobProps) { super(scope, id, props); @@ -271,7 +271,7 @@ export class BedrockCreateModelCustomizationJob extends sfn.TaskStateBase { const poliyStatement = new iam.PolicyStatement({ actions: ['kms:Decrypt', 'kms:GenerateDataKey', 'kms:DescribeKey', 'kms:CreateGrant'], resources: ['*'], - principals: [new iam.ArnPrincipal(this._role.roleArn)], + principals: [new iam.ArnPrincipal(this._role.roleRef.roleArn)], conditions: { StringEquals: { 'kms:ViaService': [ @@ -292,7 +292,10 @@ export class BedrockCreateModelCustomizationJob extends sfn.TaskStateBase { * The IAM role for the bedrock create model customization job */ public get role(): iam.IRole { - return this._role; + if ('grant' in this._role) { + return this._role as iam.IRole; + } + throw new ValidationError(`Role is not an instance of IRole: ${this._role.constructor.name}`, this); } /** @@ -300,7 +303,7 @@ export class BedrockCreateModelCustomizationJob extends sfn.TaskStateBase { * * @see https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-iam-role.html */ - private renderBedrockCreateModelCustomizationJobRole(): iam.IRole { + private renderBedrockCreateModelCustomizationJobRole(): iam.IRoleRef { if (this.props.role) { return this.props.role; } @@ -483,7 +486,7 @@ export class BedrockCreateModelCustomizationJob extends sfn.TaskStateBase { }), new iam.PolicyStatement({ actions: ['iam:PassRole'], - resources: [this._role.roleArn], + resources: [this._role.roleRef.roleArn], }), ]; return policyStatements; @@ -528,7 +531,7 @@ export class BedrockCreateModelCustomizationJob extends sfn.TaskStateBase { OutputDataConfig: { S3Uri: this.props.outputData.bucket.s3UrlForObject(this.props.outputData.path), }, - RoleArn: this._role.roleArn, + RoleArn: this._role.roleRef.roleArn, TrainingDataConfig: { S3Uri: this.props.trainingData.bucket.s3UrlForObject(this.props.trainingData.path), }, diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/evaluate-expression.ts b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/evaluate-expression.ts index 21f80cb83a6d6..a34bfe7381974 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/evaluate-expression.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/evaluate-expression.ts @@ -102,6 +102,7 @@ function createEvalFn(runtime: lambda.Runtime | undefined, scope: Construct) { const lambdaPurpose = 'Eval'; const nodeJsGuids = { + [lambda.Runtime.NODEJS_22_X.name]: 'b64e1fb8-9c89-4f7d-8a34-2e2a1c5f6d7e', [lambda.Runtime.NODEJS_20_X.name]: '9757c267-6d7c-45c2-af77-37a30d93d2c6', [lambda.Runtime.NODEJS_18_X.name]: '078d40d3-fb4e-4d53-94a7-9c46fc11fe02', [lambda.Runtime.NODEJS_16_X.name]: '2a430b68-eb4b-4026-9232-ee39b71c1db8', diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/sagemaker/base-types.ts b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/sagemaker/base-types.ts index 0949e697a1308..c528e8924cb5d 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/sagemaker/base-types.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/sagemaker/base-types.ts @@ -604,7 +604,7 @@ export interface TransformOutput { * * @default - default KMS key for Amazon S3 for your role's account. */ - readonly encryptionKey?: kms.IKey; + readonly encryptionKey?: kms.IKeyRef; /** * S3 path where you want Amazon SageMaker to store the results of the transform job. @@ -633,7 +633,7 @@ export interface TransformResources { * * @default - None */ - readonly volumeEncryptionKey?: kms.IKey; + readonly volumeEncryptionKey?: kms.IKeyRef; } /** diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/sagemaker/create-endpoint-config.ts b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/sagemaker/create-endpoint-config.ts index 32f01039317fc..711d992869fbc 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/sagemaker/create-endpoint-config.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/sagemaker/create-endpoint-config.ts @@ -19,7 +19,7 @@ interface SageMakerCreateEndpointConfigOptions { * * @default - None */ - readonly kmsKey?: kms.IKey; + readonly kmsKey?: kms.IKeyRef; /** * An list of ProductionVariant objects, one for each model that you want to host at this endpoint. @@ -121,7 +121,7 @@ export class SageMakerCreateEndpointConfig extends sfn.TaskStateBase { return { EndpointConfigName: this.props.endpointConfigName, Tags: this.props.tags?.value, - KmsKeyId: this.props.kmsKey?.keyId, + KmsKeyId: this.props.kmsKey?.keyRef.keyId, ProductionVariants: this.props.productionVariants.map((variant) => ({ InitialInstanceCount: variant.initialInstanceCount ? variant.initialInstanceCount : 1, InstanceType: isJsonPathOrJsonataExpression(variant.instanceType.toString()) diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/sagemaker/create-transform-job.ts b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/sagemaker/create-transform-job.ts index 9e232f5578e24..7ec073986c51b 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/sagemaker/create-transform-job.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/sagemaker/create-transform-job.ts @@ -245,7 +245,7 @@ export class SageMakerCreateTransformJob extends sfn.TaskStateBase { return { TransformOutput: { S3OutputPath: output.s3OutputPath, - ...(output.encryptionKey ? { KmsKeyId: output.encryptionKey.keyArn } : {}), + ...(output.encryptionKey ? { KmsKeyId: output.encryptionKey.keyRef.keyArn } : {}), ...(output.accept ? { Accept: output.accept } : {}), ...(output.assembleWith ? { AssembleWith: output.assembleWith } : {}), }, @@ -258,7 +258,7 @@ export class SageMakerCreateTransformJob extends sfn.TaskStateBase { InstanceCount: resources.instanceCount, InstanceType: isJsonPathOrJsonataExpression(resources.instanceType.toString()) ? resources.instanceType.toString() : `ml.${resources.instanceType}`, - ...(resources.volumeEncryptionKey ? { VolumeKmsKeyId: resources.volumeEncryptionKey.keyArn } : {}), + ...(resources.volumeEncryptionKey ? { VolumeKmsKeyId: resources.volumeEncryptionKey.keyRef.keyArn } : {}), }, }; } diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/stepfunctions/invoke-activity.ts b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/stepfunctions/invoke-activity.ts index 64193f657b1a2..c0c7f8ea650b2 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/stepfunctions/invoke-activity.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/stepfunctions/invoke-activity.ts @@ -1,7 +1,7 @@ import { Construct } from 'constructs'; import * as iam from '../../../aws-iam'; -import { IKey } from '../../../aws-kms'; +import { IKeyRef } from '../../../aws-kms'; import * as sfn from '../../../aws-stepfunctions'; import { CustomerManagedEncryptionConfiguration } from '../../../aws-stepfunctions/lib/customer-managed-key-encryption-configuration'; @@ -99,13 +99,13 @@ export class StepFunctionsInvokeActivity extends sfn.TaskStateBase { } // IAM policy for the State Machine execution role to use the Activity KMS key when encrypting inputs - private createPolicyStatements(kmskey: IKey): iam.PolicyStatement[] { + private createPolicyStatements(kmskey: IKeyRef): iam.PolicyStatement[] { return [ new iam.PolicyStatement({ actions: [ 'kms:Decrypt', 'kms:GenerateDataKey', ], - resources: [kmskey.keyArn], + resources: [kmskey.keyRef.keyArn], conditions: { StringEquals: { 'kms:EncryptionContext:aws:states:activityArn': this.props.activity.activityArn, diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/evaluate-expression.test.ts b/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/evaluate-expression.test.ts index 7c1e7b3613c39..e3b96560593ee 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/evaluate-expression.test.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/evaluate-expression.test.ts @@ -103,3 +103,18 @@ test('With Node.js 20.x', () => { Runtime: 'nodejs20.x', }); }); + +test('With Node.js 22.x', () => { + // WHEN + const task = new tasks.EvaluateExpression(stack, 'Task', { + expression: '$.a + $.b', + runtime: Runtime.NODEJS_22_X, + }); + new sfn.StateMachine(stack, 'SM', { + definition: task, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { + Runtime: 'nodejs22.x', + }); +}); diff --git a/packages/aws-cdk-lib/aws-stepfunctions/lib/states/distributed-map/result-writer.ts b/packages/aws-cdk-lib/aws-stepfunctions/lib/states/distributed-map/result-writer.ts index 11be34d130357..0ba2b47db7d64 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions/lib/states/distributed-map/result-writer.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions/lib/states/distributed-map/result-writer.ts @@ -193,7 +193,7 @@ export class ResultWriter { */ public render(queryLanguage?: QueryLanguage): any { const argumentOrParameter = { - Bucket: this.bucket.bucketName, + Bucket: this.bucket.bucketRef.bucketName, ...(this.prefix && { Prefix: this.prefix }), }; @@ -211,7 +211,7 @@ export class ResultWriter { * Compile policy statements to provide relevent permissions to the state machine */ public providePolicyStatements(): iam.PolicyStatement[] { - return this.bucket?.bucketName ? buildS3PutObjectPolicyStatements(this.bucket.bucketName) : []; + return this.bucket?.bucketRef.bucketName ? buildS3PutObjectPolicyStatements(this.bucket.bucketRef.bucketName) : []; } } @@ -259,7 +259,7 @@ export class ResultWriterV2 { // Resource and Parameters are only applicable if the bucket is defined, otherwise they shouldn't be rendered. const shouldRenderResourceAndParameters = !!(this.bucket || this.bucketNamePath); const argumentOrParameter = shouldRenderResourceAndParameters ? { - ...(this.bucket && { Bucket: this.bucket.bucketName }), + ...(this.bucket && { Bucket: this.bucket.bucketRef.bucketName }), ...(this.bucketNamePath && { Bucket: this.bucketNamePath }), ...(this.prefix && { Prefix: this.prefix }), }: undefined; diff --git a/packages/aws-cdk-lib/aws-synthetics/lib/code.ts b/packages/aws-cdk-lib/aws-synthetics/lib/code.ts index e91de5816a3f8..988c011c6675f 100644 --- a/packages/aws-cdk-lib/aws-synthetics/lib/code.ts +++ b/packages/aws-cdk-lib/aws-synthetics/lib/code.ts @@ -45,7 +45,7 @@ export abstract class Code { * * @returns `S3Code` associated with the specified S3 object. */ - public static fromBucket(bucket: s3.IBucket, key: string, objectVersion?: string): S3Code { + public static fromBucket(bucket: s3.IBucketRef, key: string, objectVersion?: string): S3Code { return new S3Code(bucket, key, objectVersion); } @@ -194,14 +194,14 @@ export class InlineCode extends Code { * S3 bucket path to the code zip file */ export class S3Code extends Code { - public constructor(private bucket: s3.IBucket, private key: string, private objectVersion?: string) { + public constructor(private bucket: s3.IBucketRef, private key: string, private objectVersion?: string) { super(); } public bind(_scope: Construct, _handler: string, _family: RuntimeFamily, _runtimeName?: string): CodeConfig { return { s3Location: { - bucketName: this.bucket.bucketName, + bucketName: this.bucket.bucketRef.bucketName, objectKey: this.key, objectVersion: this.objectVersion, }, diff --git a/packages/aws-cdk-lib/custom-resources/lib/provider-framework/provider.ts b/packages/aws-cdk-lib/custom-resources/lib/provider-framework/provider.ts index 7396003c165e9..a4105977ed1b8 100644 --- a/packages/aws-cdk-lib/custom-resources/lib/provider-framework/provider.ts +++ b/packages/aws-cdk-lib/custom-resources/lib/provider-framework/provider.ts @@ -163,7 +163,7 @@ export interface ProviderProps { * * @default - AWS Lambda creates and uses an AWS managed customer master key (CMK) */ - readonly providerFunctionEnvEncryption?: kms.IKey; + readonly providerFunctionEnvEncryption?: kms.IKeyRef; /** * Defines what execution history events of the waiter state machine are logged and where they are logged. @@ -222,7 +222,7 @@ export class Provider extends Construct implements ICustomResourceProvider { private readonly vpcSubnets?: ec2.SubnetSelection; private readonly securityGroups?: ec2.ISecurityGroup[]; private readonly role?: iam.IRole; - private readonly providerFunctionEnvEncryption?: kms.IKey; + private readonly providerFunctionEnvEncryption?: kms.IKeyRef; private readonly frameworkLambdaLoggingLevel?: lambda.ApplicationLogLevel; constructor(scope: Construct, id: string, props: ProviderProps) { diff --git a/packages/aws-cdk-lib/pipelines/test/testhelpers/test-app.ts b/packages/aws-cdk-lib/pipelines/test/testhelpers/test-app.ts index 40fd1c2a5d5ac..bb8c4ccaa019d 100644 --- a/packages/aws-cdk-lib/pipelines/test/testhelpers/test-app.ts +++ b/packages/aws-cdk-lib/pipelines/test/testhelpers/test-app.ts @@ -71,7 +71,7 @@ export class AppWithOutput extends Stage { super(scope, id, props); const stack = new BucketStack(this, props.stackId ?? 'Stack'); - this.theOutput = new CfnOutput(stack, 'MyOutput', { value: stack.bucket.bucketName }); + this.theOutput = new CfnOutput(stack, 'MyOutput', { value: stack.bucket.bucketRef.bucketName }); } } @@ -122,7 +122,7 @@ export class ThreeStackApp extends Stage { * It contains a single Bucket. Such robust. Much uptime. */ export class BucketStack extends Stack { - public readonly bucket: s3.IBucket; + public readonly bucket: s3.IBucketRef; constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); @@ -165,7 +165,7 @@ export class StageWithStackOutput extends Stage { const stack = new BucketStack(this, 'Stack'); this.output = new CfnOutput(stack, 'BucketName', { - value: stack.bucket.bucketName, + value: stack.bucket.bucketRef.bucketName, }); } } diff --git a/tools/@aws-cdk/lazify/test/no-double-getter.test.ts b/tools/@aws-cdk/lazify/test/no-double-getter.test.ts index d6b0ee2752c38..86ae1425bf802 100644 --- a/tools/@aws-cdk/lazify/test/no-double-getter.test.ts +++ b/tools/@aws-cdk/lazify/test/no-double-getter.test.ts @@ -1,11 +1,11 @@ import * as fs from 'fs-extra'; import * as path from 'path'; import { transformFileContents } from '../lib'; -import { parse } from 'cjs-module-lexer'; -// Write a .js file in this directory that will be imported by tests below +// Write a .js file in this directory that will be imported by tests below (make it work on Windows). +let someModulePath = path.join(__dirname, 'some-module.js').replace(/\\/g, '/'); beforeEach(async () => { - await fs.writeFile(path.join(__dirname, 'some-module.js'), [ + await fs.writeFile(someModulePath, [ 'Object.defineProperty(module.exports, "foo", {', // Necessary otherwise the way we find exported symbols (by actually including the file and iterating keys) // won't find this symbol. @@ -21,14 +21,20 @@ beforeEach(async () => { test('replace re-export with getter', () => { const fakeFile = path.join(__dirname, 'index.ts'); const transformed = transformFileContents(fakeFile, [ - '__exportStar(require("./some-module"), exports);' + `__exportStar(require("${someModulePath}"), exports);` ].join('\n')); const mod = evalModule(transformed); const logMock = jest.spyOn(console, 'log'); - expect(mod.foo).toEqual(42); - expect(mod.foo).toEqual(42); + + // If we do `expect(mod.foo).toEqual(...)` Jest has some magic somewhere to + // detect that it's a getter, rather than evaluate the getter to get to the + // number `42`. So do the getter evaluation outside of an `expect` statement. + const access1 = mod.foo; + expect(access1).toEqual(42); + const access2 = mod.foo; + expect(access2).toEqual(42); expect(logMock).toHaveBeenCalledTimes(1); }); diff --git a/tools/@aws-cdk/spec2cdk/package.json b/tools/@aws-cdk/spec2cdk/package.json index 63bb228d91a55..7292050c69f98 100644 --- a/tools/@aws-cdk/spec2cdk/package.json +++ b/tools/@aws-cdk/spec2cdk/package.json @@ -65,4 +65,4 @@ "dependencies/cdk-point-dependencies" ] } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 63cdc5ecbe597..82f81c63e8047 100644 --- a/yarn.lock +++ b/yarn.lock @@ -152,6 +152,13 @@ dependencies: "@cdklabs/tskb" "^0.0.3" +"@aws-cdk/service-spec-types@^0.0.155": + version "0.0.155" + resolved "https://registry.npmjs.org/@aws-cdk/service-spec-types/-/service-spec-types-0.0.155.tgz#a38ad6291700b38ef4f2e763555065811cae6c67" + integrity sha512-Z4kwxvQesTkbD33uZorUicIUlHlP8/fVunOa/1LGqwQw55b1gbKiZE+2o3tgm2YIOHMEsP/p1ZjqW71cFtOCyg== + dependencies: + "@cdklabs/tskb" "^0.0.3" + "@aws-crypto/crc32@5.2.0": version "5.2.0" resolved "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz#cfcc22570949c98c6689cfcbd2d693d36cdae2e1"