diff --git a/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts b/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts index 0134c6b2a0360..3b5962c1dcb9a 100644 --- a/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts +++ b/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts @@ -249,7 +249,7 @@ export class AutoScalingGroup extends cdk.Construct implements IAutoScalingGroup imageId: machineImage.imageId, keyName: props.keyName, instanceType: props.instanceType.toString(), - securityGroups: securityGroupsToken, + securityGroups: securityGroupsToken.toList(), iamInstanceProfile: iamProfile.ref, userData: userDataToken, associatePublicIpAddress: props.associatePublicIpAddress, @@ -274,8 +274,8 @@ export class AutoScalingGroup extends cdk.Construct implements IAutoScalingGroup maxSize: maxCapacity.toString(), desiredCapacity: desiredCapacity.toString(), launchConfigurationName: launchConfig.ref, - loadBalancerNames: new cdk.Token(() => this.loadBalancerNames.length > 0 ? this.loadBalancerNames : undefined), - targetGroupArns: new cdk.Token(() => this.targetGroupArns.length > 0 ? this.targetGroupArns : undefined), + loadBalancerNames: new cdk.Token(() => this.loadBalancerNames.length > 0 ? this.loadBalancerNames : undefined).toList(), + targetGroupArns: new cdk.Token(() => this.targetGroupArns.length > 0 ? this.targetGroupArns : undefined).toList(), }; if (props.notificationsTopic) { diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/alarm.ts b/packages/@aws-cdk/aws-cloudwatch/lib/alarm.ts index 706f05d3cf368..009834d0682b8 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/alarm.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/alarm.ts @@ -107,9 +107,9 @@ export class Alarm extends Construct { // Actions actionsEnabled: props.actionsEnabled, - alarmActions: new Token(() => this.alarmActionArns), - insufficientDataActions: new Token(() => this.insufficientDataActionArns), - okActions: new Token(() => this.okActionArns), + alarmActions: new Token(() => this.alarmActionArns).toList(), + insufficientDataActions: new Token(() => this.insufficientDataActionArns).toList(), + okActions: new Token(() => this.okActionArns).toList(), // Metric ...metricJson(props.metric) diff --git a/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts b/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts index 11ffdb9972482..f7cf5469c84cc 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts @@ -300,7 +300,7 @@ export class ServerDeploymentGroup extends ServerDeploymentGroupBase { autoScalingGroups: new cdk.Token(() => this._autoScalingGroups.length === 0 ? undefined - : this._autoScalingGroups.map(asg => asg.autoScalingGroupName)), + : this._autoScalingGroups.map(asg => asg.autoScalingGroupName)).toList(), loadBalancerInfo: this.loadBalancerInfo(props.loadBalancer), deploymentStyle: props.loadBalancer === undefined ? undefined diff --git a/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts b/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts index fa8365cc1d266..f6811d72eec3f 100644 --- a/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts +++ b/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts @@ -191,7 +191,7 @@ export abstract class BaseService extends cdk.Construct awsvpcConfiguration: { assignPublicIp: assignPublicIp ? 'ENABLED' : 'DISABLED', subnets: subnets.map(x => x.subnetId), - securityGroups: new cdk.Token(() => [securityGroup!.securityGroupId]), + securityGroups: new cdk.Token(() => [securityGroup!.securityGroupId]).toList(), } }; } diff --git a/packages/@aws-cdk/aws-iam/lib/group.ts b/packages/@aws-cdk/aws-iam/lib/group.ts index 7e68246eb7b1c..a8b82d68fab3f 100644 --- a/packages/@aws-cdk/aws-iam/lib/group.ts +++ b/packages/@aws-cdk/aws-iam/lib/group.ts @@ -50,7 +50,7 @@ export class Group extends Construct implements IPrincipal { */ public readonly principal: PolicyPrincipal; - private readonly managedPolicies: any[]; + private readonly managedPolicies: string[]; private readonly attachedPolicies = new AttachedPolicies(); private defaultPolicy?: Policy; diff --git a/packages/@aws-cdk/aws-iam/lib/util.ts b/packages/@aws-cdk/aws-iam/lib/util.ts index aeb0f2c39652f..e3d2bae372627 100644 --- a/packages/@aws-cdk/aws-iam/lib/util.ts +++ b/packages/@aws-cdk/aws-iam/lib/util.ts @@ -3,11 +3,11 @@ import { Policy } from './policy'; const MAX_POLICY_NAME_LEN = 128; -export function undefinedIfEmpty(f: () => T[]): Token { +export function undefinedIfEmpty(f: () => string[]): string[] { return new Token(() => { const array = f(); return (array && array.length > 0) ? array : undefined; - }); + }).toList(); } /** diff --git a/packages/@aws-cdk/aws-lambda/lib/function.ts b/packages/@aws-cdk/aws-lambda/lib/function.ts index 9d603e43dc860..657219c575cfc 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function.ts @@ -365,7 +365,7 @@ export class Function extends FunctionBase { functionName: props.functionName, description: props.description, code: new cdk.Token(() => props.code._toJSON(resource)), - layers: new cdk.Token(() => this.layers.length > 0 ? this.layers.map(layer => layer.layerVersionArn) : undefined), + layers: new cdk.Token(() => this.layers.length > 0 ? this.layers.map(layer => layer.layerVersionArn) : undefined).toList(), handler: props.handler, timeout: props.timeout, runtime: props.runtime.name, diff --git a/tools/cfn2ts/lib/codegen.ts b/tools/cfn2ts/lib/codegen.ts index e6a73ddc4a815..9ac2e9f0e74eb 100644 --- a/tools/cfn2ts/lib/codegen.ts +++ b/tools/cfn2ts/lib/codegen.ts @@ -579,8 +579,11 @@ export default class CodeGenerator { // render the union of all item types const itemTypes = genspec.specTypesToCodeTypes(resourceContext, itemTypeNames(propSpec)); - if (propName !== 'Tags') { - // Always accept a token in place of any list element + // 'tokenizableType' operates at the level of rendered type names in TypeScript, so stringify + // the objects. + const renderedTypes = itemTypes.map(t => this.renderCodeName(resourceContext, t)); + if (!tokenizableType(renderedTypes) && propName !== 'Tags') { + // Always accept a token in place of any list element (unless the list elements are tokenizable) itemTypes.push(genspec.TOKEN_NAME); } @@ -619,17 +622,20 @@ export default class CodeGenerator { return alternatives.join(' | '); } + /** + * Render a CodeName to a string representation of it in TypeScript + */ + private renderCodeName(context: genspec.CodeName, type: genspec.CodeName): string { + const rel = type.relativeTo(context); + const specType = rel.specName && this.spec.PropertyTypes[rel.specName.fqn]; + if (!specType || schema.isPropertyBag(specType)) { + return rel.fqn; + } + return this.findNativeType(context, specType); + } + private renderTypeUnion(context: genspec.CodeName, types: genspec.CodeName[]) { - return types - .map(type => type.relativeTo(context)) - .map(type => { - const specType = type.specName && this.spec.PropertyTypes[type.specName.fqn]; - if (!specType || schema.isPropertyBag(specType)) { - return type.fqn; - } - return this.findNativeType(context, specType); - }) - .join(' | '); + return types.map(t => this.renderCodeName(context, t)).join(' | '); } private docLink(link: string | undefined, ...before: string[]) {