Skip to content

Commit

Permalink
fix: hcl rendering nested maps (#3536)
Browse files Browse the repository at this point in the history
Closes #3529
  • Loading branch information
DanielMSchmidt committed Mar 4, 2024
1 parent dc9bcd2 commit 639b61a
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 1 deletion.
10 changes: 10 additions & 0 deletions packages/cdktf/lib/hcl/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,16 @@ export function renderMapValue(value: any): string {
return `${value}`;
}

if (typeof value === "object") {
if (Array.isArray(value)) {
return renderListValue(value, "unknownStorageClass");
}
if (value === null) {
return "null";
}
return renderMap(value);
}

return `${value}`;
}

Expand Down
13 changes: 12 additions & 1 deletion packages/cdktf/test/helper/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface TestResourceConfig extends TerraformMetaArguments {
names?: string[];
tags?: { [key: string]: string };
nestedType?: { [key: string]: string };
anyMap?: { [key: string]: any };
listBlock?: IResolvable;
listAttribute?: IResolvable;
}
Expand All @@ -26,6 +27,7 @@ export class TestResource extends TerraformResource {
public names?: string[];
public tags?: { [key: string]: string };
public nestedType?: { [key: string]: string };
public anyMap?: { [key: string]: any };
public listBlock?: IResolvable; // real life bindings also allow an interface here, but we don't use that in our tests using this
public listAttribute?: IResolvable;

Expand All @@ -47,6 +49,7 @@ export class TestResource extends TerraformResource {
this.name = config.name;
this.names = config.names;
this.tags = config.tags;
this.anyMap = config.anyMap;
this.nestedType = config.nestedType;
this.listBlock = config.listBlock;
this.listAttribute = config.listAttribute;
Expand All @@ -58,6 +61,7 @@ export class TestResource extends TerraformResource {
names: this.names,
tags: this.tags,
nested_type: this.nestedType,
any_map: this.anyMap,
list_block: listMapper((a) => a, true)(this.listBlock), // identity function to skip writing a toTerraform function
list_attribute: listMapper((a) => a, false)(this.listAttribute), // identity function to skip writing a toTerraform function
};
Expand Down Expand Up @@ -88,9 +92,16 @@ export class TestResource extends TerraformResource {
storageClassType: "stringMap",
},

any_map: {
value: this.anyMap,
type: "map",
storageClassType: "anyMap",
},
list_block: listMapper((a) => a, true)(this.listBlock), // identity function to skip writing a toTerraform function
list_attribute: listMapper((a) => a, false)(this.listAttribute), // identity function to skip writing a toTerraform function
}).filter(([_, v]) => !!v?.value)
}).filter(
([_, value]) => value !== undefined && value.value !== undefined
)
);
}

Expand Down
87 changes: 87 additions & 0 deletions packages/cdktf/test/json-to-hcl.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,93 @@ describe("output", () => {
`);
});

test("deeply nested map ", async () => {
const app = Testing.app();
const stack = new TerraformStack(app, "test");

new TestProvider(stack, "provider", {});

new TestResource(stack, "probably-kubernetes", {
name: "foo",
anyMap: {
spec: {
metadata: {
name: "foo",
labels: {
"foo:bar": "baz",
simple: "true",
},
},
},
},
});

expect(Testing.synthHcl(stack)).toMatchInlineSnapshot(`
"terraform {
required_providers {
test = {
version = "~> 2.0"
}
}
}
provider "test" {
}
resource "test_resource" "probably-kubernetes" {
name = "foo"
any_map = {
spec = {
metadata = {
name = "foo"
labels = {
"foo:bar" = "baz"
simple = "true"
}
}
}
}
}"
`);
});

test("map with undefined / null value", async () => {
const app = Testing.app();
const stack = new TerraformStack(app, "test");

new TestProvider(stack, "provider", {});

new TestResource(stack, "sth-fishy", {
name: "foo",
anyMap: {
notDefined: undefined,
billionDollarMistake: null,
},
});

expect(Testing.synthHcl(stack)).toMatchInlineSnapshot(`
"terraform {
required_providers {
test = {
version = "~> 2.0"
}
}
}
provider "test" {
}
resource "test_resource" "sth-fishy" {
name = "foo"
any_map = {
billionDollarMistake = null
}
}"
`);
});

test("dependent output", async () => {
const app = Testing.app();
const stack = new TerraformStack(app, "test");
Expand Down

0 comments on commit 639b61a

Please sign in to comment.