Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions packages/aws-cdk-lib/core/lib/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -400,3 +400,14 @@ function isCloudFormationDynamicReference(x: any) {
class CfnSynthesisError extends Error {
public readonly type = 'CfnSynthesisError';
}

/**
* Ensures that a property is either undefined or a string.
* Used in spec2cdk to have better error messages in other languages.
*/
export function ensureStringOrUndefined(value: any, propName: string, possibleType: string): string | undefined {
if (value !== undefined && typeof value !== 'string') {
throw new TypeError(`Property ${propName} should be one of ${possibleType}`);
}
return value;
}
3 changes: 3 additions & 0 deletions tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export interface Relationship {
readonly referenceName: string;
/** The property to extract from the reference object (e.g. "roleArn") */
readonly propName: string;
/** Human friendly name of the reference type for error generation (e.g. "iam.IRoleRef") */
readonly typeDisplayName: string;
}

/**
Expand Down Expand Up @@ -118,6 +120,7 @@ export class RelationshipDecider {
referenceType: aliasedTypeName ?? interfaceName,
referenceName: refPropStructName,
propName: referencePropertyName(relationship.propertyName, targetResource.name),
typeDisplayName: `${typeAliasPrefixFromResource(targetResource).toLowerCase()}.${interfaceName}`,
});
}
return parsedRelationships;
Expand Down
7 changes: 6 additions & 1 deletion tools/@aws-cdk/spec2cdk/lib/cdk/resolver-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ export class ResolverBuilder {
? Type.arrayOf(Type.distinctUnionOf(resolvableType.arrayOfType, ...newTypes))
: Type.distinctUnionOf(resolvableType, ...newTypes);

const typeDisplayNames = [
...relationships.map(r => r.typeDisplayName),
resolvableType.arrayOfType?.toString() ?? resolvableType.toString(),
].join(' | ');

// Generates code like:
// For single value: (props.roleArn as IRoleRef)?.roleRef?.roleArn ?? (props.roleArn as IUserRef)?.userRef?.userArn ?? props.roleArn
// For array: props.roleArns?.map((item: any) => (item as IRoleRef)?.roleRef?.roleArn ?? (item as IUserRef)?.userRef?.userArn ?? item)
Expand All @@ -84,7 +89,7 @@ export class ResolverBuilder {
const buildChain = (itemName: string) => [
...[...arnRels, ...otherRels]
.map(r => `(${itemName} as ${r.referenceType})?.${r.referenceName}?.${r.propName}`),
itemName,
`cdk.ensureStringOrUndefined(${itemName}, "${name}", "${typeDisplayNames}")`,
].join(' ?? ');
const resolver = (_: Expression) => {
if (resolvableType.arrayOfType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors";
*
* @stability experimental
*/
export interface IRoleRef extends constructs.IConstruct {
export interface IRoleRef extends constructs.IConstruct, cdk.IEnvironmentAware {
/**
* A reference to a Role resource.
*/
Expand Down Expand Up @@ -165,7 +165,7 @@ function CfnRolePropsFromCloudFormation(properties: any): cfn_parse.FromCloudFor
*
* @stability experimental
*/
export interface IResourceRef extends constructs.IConstruct {
export interface IResourceRef extends constructs.IConstruct, cdk.IEnvironmentAware {
/**
* A reference to a Resource resource.
*/
Expand Down Expand Up @@ -280,7 +280,7 @@ export interface CfnResourceProps {
function flattenCfnResourcePermissionProperty(props: cdk.IResolvable | CfnResource.PermissionProperty): cdk.IResolvable | CfnResource.PermissionProperty {
if (cdk.isResolvableObject(props)) return props;
return {
"roleArn": (props.roleArn as IRoleRef)?.roleRef?.roleArn ?? props.roleArn
"roleArn": (props.roleArn as IRoleRef)?.roleRef?.roleArn ?? cdk.ensureStringOrUndefined(props.roleArn, "roleArn", "iam.IRoleRef | string")
};
}

Expand Down Expand Up @@ -391,7 +391,7 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors";
*
* @stability experimental
*/
export interface IRoleRef extends constructs.IConstruct {
export interface IRoleRef extends constructs.IConstruct, cdk.IEnvironmentAware {
/**
* A reference to a Role resource.
*/
Expand Down Expand Up @@ -544,7 +544,7 @@ function CfnRolePropsFromCloudFormation(properties: any): cfn_parse.FromCloudFor
*
* @stability experimental
*/
export interface IUserRef extends constructs.IConstruct {
export interface IUserRef extends constructs.IConstruct, cdk.IEnvironmentAware {
/**
* A reference to a User resource.
*/
Expand Down Expand Up @@ -697,7 +697,7 @@ function CfnUserPropsFromCloudFormation(properties: any): cfn_parse.FromCloudFor
*
* @stability experimental
*/
export interface IPolicyRef extends constructs.IConstruct {
export interface IPolicyRef extends constructs.IConstruct, cdk.IEnvironmentAware {
/**
* A reference to a Policy resource.
*/
Expand Down Expand Up @@ -752,7 +752,7 @@ export class CfnPolicy extends cdk.CfnResource implements cdk.IInspectable, IPol
"properties": props
});

this.principalArn = (props.principalArn as IRoleRef)?.roleRef?.roleArn ?? (props.principalArn as IUserRef)?.userRef?.userArn ?? props.principalArn;
this.principalArn = (props.principalArn as IRoleRef)?.roleRef?.roleArn ?? (props.principalArn as IUserRef)?.userRef?.userArn ?? cdk.ensureStringOrUndefined(props.principalArn, "principalArn", "iam.IRoleRef | iam.IUserRef | string");
}

public get policyRef(): PolicyReference {
Expand Down Expand Up @@ -859,7 +859,7 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors";
*
* @stability experimental
*/
export interface IRoleRef extends constructs.IConstruct {
export interface IRoleRef extends constructs.IConstruct, cdk.IEnvironmentAware {
/**
* A reference to a Role resource.
*/
Expand Down Expand Up @@ -1012,7 +1012,7 @@ function CfnRolePropsFromCloudFormation(properties: any): cfn_parse.FromCloudFor
*
* @stability experimental
*/
export interface ITaskRef extends constructs.IConstruct {
export interface ITaskRef extends constructs.IConstruct, cdk.IEnvironmentAware {
/**
* A reference to a Task resource.
*/
Expand Down Expand Up @@ -1127,7 +1127,7 @@ export interface CfnTaskProps {
function flattenCfnTaskExecutionConfigProperty(props: CfnTask.ExecutionConfigProperty | cdk.IResolvable): CfnTask.ExecutionConfigProperty | cdk.IResolvable {
if (cdk.isResolvableObject(props)) return props;
return {
"roleArn": (props.roleArn as IRoleRef)?.roleRef?.roleArn ?? props.roleArn
"roleArn": (props.roleArn as IRoleRef)?.roleRef?.roleArn ?? cdk.ensureStringOrUndefined(props.roleArn, "roleArn", "iam.IRoleRef | string")
};
}

Expand Down Expand Up @@ -1238,7 +1238,7 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors";
*
* @stability experimental
*/
export interface IRoleRef extends constructs.IConstruct {
export interface IRoleRef extends constructs.IConstruct, cdk.IEnvironmentAware {
/**
* A reference to a Role resource.
*/
Expand Down Expand Up @@ -1391,7 +1391,7 @@ function CfnRolePropsFromCloudFormation(properties: any): cfn_parse.FromCloudFor
*
* @stability experimental
*/
export interface IJobRef extends constructs.IConstruct {
export interface IJobRef extends constructs.IConstruct, cdk.IEnvironmentAware {
/**
* A reference to a Job resource.
*/
Expand Down Expand Up @@ -1523,7 +1523,7 @@ export interface CfnJobProps {
function flattenCfnJobConfigProperty(props: CfnJob.ConfigProperty | cdk.IResolvable): CfnJob.ConfigProperty | cdk.IResolvable {
if (cdk.isResolvableObject(props)) return props;
return {
"roleArn": (props.roleArn as IRoleRef)?.roleRef?.roleArn ?? props.roleArn,
"roleArn": (props.roleArn as IRoleRef)?.roleRef?.roleArn ?? cdk.ensureStringOrUndefined(props.roleArn, "roleArn", "iam.IRoleRef | string"),
"timeout": props.timeout
};
}
Expand Down Expand Up @@ -1577,7 +1577,7 @@ function CfnJobConfigPropertyFromCloudFormation(properties: any): cfn_parse.From
function flattenCfnJobOldConfigProperty(props: cdk.IResolvable | CfnJob.OldConfigProperty): cdk.IResolvable | CfnJob.OldConfigProperty {
if (cdk.isResolvableObject(props)) return props;
return {
"roleArn": (props.roleArn as IRoleRef)?.roleRef?.roleArn ?? props.roleArn
"roleArn": (props.roleArn as IRoleRef)?.roleRef?.roleArn ?? cdk.ensureStringOrUndefined(props.roleArn, "roleArn", "iam.IRoleRef | string")
};
}

Expand Down Expand Up @@ -1688,7 +1688,7 @@ import * as cdk_errors from "aws-cdk-lib/core/lib/errors";
*
* @stability experimental
*/
export interface IRoleRef extends constructs.IConstruct {
export interface IRoleRef extends constructs.IConstruct, cdk.IEnvironmentAware {
/**
* A reference to a Role resource.
*/
Expand Down Expand Up @@ -1841,7 +1841,7 @@ function CfnRolePropsFromCloudFormation(properties: any): cfn_parse.FromCloudFor
*
* @stability experimental
*/
export interface IFunctionRef extends constructs.IConstruct {
export interface IFunctionRef extends constructs.IConstruct, cdk.IEnvironmentAware {
/**
* A reference to a Function resource.
*/
Expand Down Expand Up @@ -1896,7 +1896,7 @@ export class CfnFunction extends cdk.CfnResource implements cdk.IInspectable, IF
"properties": props
});

this.roleArn = (props.roleArn as IRoleRef)?.roleRef?.roleArn ?? props.roleArn;
this.roleArn = (props.roleArn as IRoleRef)?.roleRef?.roleArn ?? cdk.ensureStringOrUndefined(props.roleArn, "roleArn", "iam.IRoleRef | string");
}

public get functionRef(): FunctionReference {
Expand Down
Loading