How to use $file in cdktf

I’d like to reference a local yaml file when creating a helm chart with cdktf.

I have the following cdktf config:

{
  "language": "typescript",
  "app": "npx ts-node main.ts",
  "projectId": "...",
  "terraformProviders": [
    "hashicorp/aws@~> 3.42",
    "hashicorp/kubernetes@ ~> 2.7.0",
    "hashicorp/http@ ~> 2.1.0",
    "hashicorp/tls@ ~> 3.1.0",
    "hashicorp/helm@ ~> 2.4.1",
    "hashicorp/random@ ~> 3.1.0",
    "gavinbunney/kubectl@ ~> 1.14.0"
  ],
  "terraformModules": [
    {
      "name": "secrets-store-csi",
      "source": "app.terraform.io/goldsky/secrets-store-csi/aws",
      "version": "0.1.5"
    }
  ],
  "context": {
    "excludeStackIdFromLogicalIds": "true",
    "allowSepCharsInLogicalIds": "true"
  }
}

Note npx ts-node main.ts as the app.

In main.ts I have the following helm release

    new helm.Release(this, "datadog-agent", {
      chart: "datadog",
      name: "datadog",
      repository: "https://helm.datadoghq.com",
      version: "3.1.3",
      set: [
        {
          name: "datadog.clusterChecks.enabled",
          value: "true",
        },
        {
          name: "clusterAgent.enabled",
          value: "true"
        },
      ],
      values: ["${file(\"datadog-values.yaml\")}"],
    });

Note that I’m referencing a yaml file called datadog-values.yaml similar to this example from the helm provider.

datadog-values.yaml is a sister file to main.ts

However, when I try to deploy this with cdktf deploy I get the following error

│ Error: Invalid function argument
│
│   on cdk.tf.json line 1017, in resource.helm_release.datadog-agent.values:
│ 1017:           "${file(\"datadog-values.yaml\")}"
│
│ Invalid value for "path" parameter: no file exists at
│ "datadog-values.yaml"; this function works only with files that are
│ distributed as part of the configuration source code, so if this file will
│ be created by a resource in this configuration you must instead obtain this
goldsky-infra-dev  ╷
                   │ Error: Invalid function argument
                   │
                   │   on cdk.tf.json line 1017, in resource.helm_release.datadog-agent (datadog-agent).values:
                   │ 1017:           "${file(\"datadog-values.yaml\")}"
                   │
                   │ Invalid value for "path" parameter: no file exists at
                   │ "datadog-values.yaml"; this function works only with files that are
                   │ distributed as part of the configuration source code, so if this file will
                   │ be created by a resource in this configuration you must instead obtain this
                   │ result from an attribute of that resource.

To run a deployment I execute npm run deploy:dev which is a customer script in my package.json:

    "build": "tsc",
    "deploy:dev": "npm run build && npx cdktf deploy",

How can I reference my datadog yaml file in a helm release like in the example shown by the helm provider?

Hi @naturita_ellertson,

As the error message mentions, the file function is intended for reading files that exist as part of the Terraform module directory on disk. When you use CDK for Terraform the “module on disk” is some generated code produced by CDK for Terraform, rather than a module you wrote directly, and so the file function isn’t so useful in that context.

Since your CDK for Terraform input source code is running in a NodeJS runtime I expect it’ll work better to load the file using NodeJS’s filesystem functions instead. Then the contents of your file will be included as part of the Terraform module that CDK for Terraform quietly generates behind the scenes, and so at runtime Terraform will read it directly from that generated configuration rather than trying to read the file from disk itself.

Calling Terraform’s own functions in CDK for Terraform can be useful if the arguments you’re providing are generated dynamically at runtime while Terraform Core is running, but in your case you already know exactly which filename you want to load from and so it’s safe to do the work directly in Node as part of the module synthesis step because you already have all of the information required to do that before Terraform Core is running.

1 Like

Another option is to use a TerraformAsset. It’s a construct that explicitly bundles a file/folder into the cdktf output.

1 Like