Skip to content

Add: struct-typed values via Lazy producers / provider-function arguments need the resource's own xxxToTerraform mapper #26

Description

@vincenthsh

Problem

Any value that reaches a generated resource's nested-struct property without going through plain synth-time attribute assignment — a Lazy.anyValue({ produce: ... }) producer, or the raw argument to a provider-defined function call (provider::<name>::<function>) — bypasses that struct's generated xxxToTerraform mapper entirely, so it must be pre-shaped by hand (either hand-written in the Terraform schema's own snake_case, or run through the exported xxxToTerraform function yourself). This is currently undocumented in both places a user would hit it:

  1. Lazy producers. concepts/constructs.mdx's only Lazy example (new Lazy({ produce: () => buckets }) as a TerraformOutput value) is a flat list-of-strings case that never needs struct mapping, so it doesn't demonstrate the requirement. api-reference/*/classes/lazy.mdx (all languages) is API-reference only, no usage guidance. concepts/tokens.mdx has no mention of Lazy, xxxToTerraform, or canInspect at all — the actual mechanism (canInspect() returns false for an unresolved token, so the struct mapper's early-return skips it, and the raw produce() result is substituted in later during whole-tree token resolution, never touching the mapper) isn't explained anywhere.
  2. Provider-defined functions. concepts/functions.mdx covers only the built-in Fn.* set and explicitly scopes provider-defined functions out even of the function-availability-validation section ("Provider-defined functions (provider::<name>::<function>) are out of scope"). There's no conceptual doc for provider-defined functions at all yet, so there's nowhere this gotcha could currently be documented even if someone wanted to add it.

Concrete repro

Demonstrated in cdktn-provider-features-demo (l2-kinesis-stream): assigning a plain camelCase object as one branch of a provider::cfncompat::condition_if(...) call and passing it as a struct-typed resource attribute renders with the wrong (camelCase) keys unless it's first run through the resource's own generated xxxToTerraform mapper — e.g. kinesisStreamStreamEncryptionToTerraform({ encryptionType: "KMS", keyId: "alias/aws/kinesis" }) instead of hand-writing { encryption_type: "KMS", key_id: "alias/aws/kinesis" }. The wrapper has a real ergonomic edge too: its argument is the typed KinesisStreamStreamEncryption shape, so typos/wrong types are caught by tsc, unlike a raw any-typed provider-function argument.

Ask

  • Add a Lazy example to concepts/constructs.mdx (or tokens.mdx) that produces a nested struct property (not just a flat value), showing the required xxxToTerraform(...) wrap and briefly explaining why (canInspect()/token-resolution timing).
  • Add a conceptual "Provider Functions" doc (concepts/provider-functions.mdx or similar — functions.mdx currently only covers built-in Fn.*), including the same struct-argument gotcha, since it's the identical underlying cause.
  • cdktn-provider-features-demo's l2-kinesis-stream example is a live, working repro of both patterns side by side if useful as a doc example source.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions