diff --git a/packages/cdktf/lib/terraform-functions.ts b/packages/cdktf/lib/terraform-functions.ts index 57147e7b8b..1837d28499 100644 --- a/packages/cdktf/lib/terraform-functions.ts +++ b/packages/cdktf/lib/terraform-functions.ts @@ -1,6 +1,6 @@ // Copyright (c) HashiCorp, Inc // SPDX-License-Identifier: MPL-2.0 -import { rawString, Token } from "."; +import { propertyAccess, rawString, Token } from "."; import { FnGenerated } from "./functions/terraform-functions.generated"; // eslint-disable-next-line jsdoc/require-jsdoc @@ -21,12 +21,22 @@ export class Fn extends FnGenerated { * {@link https://www.terraform.io/docs/language/functions/lookup.html lookup} retrieves the value of a single element from a map, given its key. If the given key does not exist, the given default value is returned instead. * @param {any} inputMap * @param {string} key - * @param {Array} defaultValue + * @param {any} [defaultValue] */ - static lookup(inputMap: any, key: string, defaultValue: any) { + static lookup(inputMap: any, key: string, defaultValue?: any) { // overwritten because lookup() uses a variadic argument for its optional defaultValue - // we don't model it as optional since not passing it is deprecated in favor of the native Terraform expression "inputMap[key]" - return Fn._lookup(inputMap, key, [defaultValue]); + if (defaultValue) return Fn._lookup(inputMap, key, [defaultValue]); + return propertyAccess(inputMap, [key]); // -> renders inputMap[key] (which is recommened if no default value is given) + } + + /** + * returns a property access expression that accesses the property at the given path in the given inputMap. + * For example lookupNested(x, ["a", "b", "c"]) will return a Terraform expression like x["a"]["b"]["c"] + * @param {any} inputMap + * @param {Array} path + */ + static lookupNested(inputMap: any, path: any[]) { + return propertyAccess(inputMap, path); } /** diff --git a/packages/cdktf/test/functions.test.ts b/packages/cdktf/test/functions.test.ts index 267f47aa75..adb6581256 100644 --- a/packages/cdktf/test/functions.test.ts +++ b/packages/cdktf/test/functions.test.ts @@ -553,3 +553,43 @@ it("errors mentioning function name and argument", () => { `"Argument 1 of replace failed the validation: Error: 'this one \\" not' can not be used as value directly since it has unescaped double quotes in it. To safely use the value please use Fn.rawString on your string."` ); }); + +test("Property access using lookup and lookupNested functions", () => { + const app = Testing.app(); + const stack = new TerraformStack(app, "test"); + + const variable = new TerraformVariable(stack, "test-var", { + type: `object({a = object({b = string}), z = string})`, + }); + + new TerraformOutput(stack, "lookup", { + value: Fn.lookup(variable.value, "z", "defaultzzzz"), + }); + new TerraformOutput(stack, "native-access", { + value: Fn.lookup(variable.value, "z"), + }); + new TerraformOutput(stack, "native-access-nested", { + value: Fn.lookupNested(variable.value, ["a", "b"]), + }); + + expect(Testing.synth(stack)).toMatchInlineSnapshot(` + "{ + \\"output\\": { + \\"lookup\\": { + \\"value\\": \\"\${lookup(var.test-var, \\\\\\"z\\\\\\", \\\\\\"defaultzzzz\\\\\\")}\\" + }, + \\"native-access\\": { + \\"value\\": \\"\${var.test-var[\\\\\\"z\\\\\\"]}\\" + }, + \\"native-access-nested\\": { + \\"value\\": \\"\${var.test-var[\\\\\\"a\\\\\\"][\\\\\\"b\\\\\\"]}\\" + } + }, + \\"variable\\": { + \\"test-var\\": { + \\"type\\": \\"object({a = object({b = string}), z = string})\\" + } + } + }" + `); +});