From f78dd8cde979ede349bbff02d7657d7498f00dbf Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Tue, 14 Jun 2022 12:42:49 +0200 Subject: [PATCH] fix: use both attribute and block types to find if an attribute is defined --- packages/@cdktf/hcl2cdk/lib/generation.ts | 24 ++++++++++---- packages/@cdktf/hcl2cdk/lib/provider.ts | 34 ++++++++++++++++++++ packages/@cdktf/hcl2cdk/test/hcl2cdk.test.ts | 2 -- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/packages/@cdktf/hcl2cdk/lib/generation.ts b/packages/@cdktf/hcl2cdk/lib/generation.ts index f5ba227964..5b033b0451 100644 --- a/packages/@cdktf/hcl2cdk/lib/generation.ts +++ b/packages/@cdktf/hcl2cdk/lib/generation.ts @@ -28,7 +28,11 @@ import { TerraformModuleConstraint, escapeAttributeName, } from "@cdktf/provider-generator"; -import { getBlockTypeAtPath, getAttributeTypeAtPath } from "./provider"; +import { + getBlockTypeAtPath, + getAttributeTypeAtPath, + getTypeAtPath, +} from "./provider"; function getReference(graph: DirectedGraph, id: string) { logger.debug(`Finding reference for ${id}`); @@ -124,17 +128,23 @@ export const valueToTs = async ( const isMapAttribute = Array.isArray(attribute?.type) ? attribute?.type?.[0] === "map" : false; + + const typeMetadata = getTypeAtPath( + scope.providerSchema, + itemPath + ); + + const isSingleItemBlock = + typeMetadata !== null && "max_items" in typeMetadata + ? typeMetadata?.max_items === 1 + : false; const shouldBeArray = typeof value === "object" && !Array.isArray(value) && - getBlockTypeAtPath(scope.providerSchema, itemPath) - ?.max_items !== 1 && + !isSingleItemBlock && !isMapAttribute && key !== "tags"; - - const isNeitherBlockNorAttribute = - getBlockTypeAtPath(scope.providerSchema, itemPath) === null && - getAttributeTypeAtPath(scope.providerSchema, itemPath) === null; + const isNeitherBlockNorAttribute = !typeMetadata; return t.objectProperty( t.stringLiteral( diff --git a/packages/@cdktf/hcl2cdk/lib/provider.ts b/packages/@cdktf/hcl2cdk/lib/provider.ts index a469124240..4f1d14b4cc 100644 --- a/packages/@cdktf/hcl2cdk/lib/provider.ts +++ b/packages/@cdktf/hcl2cdk/lib/provider.ts @@ -105,6 +105,40 @@ export function getAttributeTypeAtPath( return attributes[attributeName]; } +export function getTypeAtPath(schema: ProviderSchema, path: string) { + const resourceSchema = getResourceAtPath(schema, path); + if (!resourceSchema) { + return null; + } + const { resource, parts } = resourceSchema; + + let currentSchema: BlockType | typeof resource = resource; + do { + const part = parts.shift() as string; + if ( + !currentSchema.block.block_types || + !currentSchema.block.block_types.hasOwnProperty(part) + ) { + // Found no block property with this name, there could be an attribute + if ( + currentSchema.block.attributes && + currentSchema.block.attributes.hasOwnProperty(part) + ) { + if (parts.length === 0) { + return currentSchema.block.attributes[part]; + } else { + // We found an attribute, but the path goes deeper so we have no information + return null; + } + } + } + + currentSchema = currentSchema.block.block_types[part]; + } while (parts.length > 0); + + return currentSchema; +} + type Plan = z.infer; export function getProviderRequirements(plan: Plan) { // In Terraform one can implicitly define the provider by using resources of that type diff --git a/packages/@cdktf/hcl2cdk/test/hcl2cdk.test.ts b/packages/@cdktf/hcl2cdk/test/hcl2cdk.test.ts index b9e27787c3..0e28d046e9 100644 --- a/packages/@cdktf/hcl2cdk/test/hcl2cdk.test.ts +++ b/packages/@cdktf/hcl2cdk/test/hcl2cdk.test.ts @@ -1400,8 +1400,6 @@ describe("convert", () => { host = self.public_ip } } - - `, Synth.never );