hashicorp / terraform-cdk

Define infrastructure resources using programming constructs and provision them using HashiCorp Terraform
https://www.terraform.io/cdktf
Mozilla Public License 2.0
4.79k stars 441 forks source link

COMPONENT: convert doesn't convert locals {} #3633

Open infowolfe opened 1 month ago

infowolfe commented 1 month ago

Expected Behavior

Python example code is printed to the console.

I was trying to figure out how to actually do concatenation since cloudflare is sloppy (their provider breaks convert completely and you can't overwrite the same fqdn because they're gluing the record + zone together behind the scenes), which required doing a Fn.trimsuffix().... and there's for some reason no way in cdktf to glue the name and zone back together again.

Actual Behavior

I'm redirected to a bug that @DanielMSchmidt closed #842 instead of something helpful.

Adding package @cdktf/provider-aws @ 19.20.1
[2024-05-26T20:53:26.803] [ERROR] default - Found a reference that is unknown: ${var.documents_path == "" ? format("%s/%s",path.module,"documents") : var.documents_path} has reference "var.documents_path".The id was not found in ["local.documents_path"] with temporary values [].
Please leave a comment at https://cdk.tf/bugs/convert-expressions if you run into this issue.
[2024-05-26T20:53:26.803] [ERROR] default - Found a reference that is unknown: ${var.documents_path == "" ? format("%s/%s",path.module,"documents") : var.documents_path} has reference "var.documents_path".The id was not found in ["local.documents_path"] with temporary values [].
Please leave a comment at https://cdk.tf/bugs/convert-expressions if you run into this issue.
from constructs import Construct
class MyConvertedCode(Construct):
    def __init__(self, scope, name):
        super().__init__(scope, name)

Steps to Reproduce

copy this:

locals {
 documents_path = "${var.documents_path == "" ? format("%s/%s",path.module,"documents") : var.documents_path}" 
}

(pbpaste is for mac user convenience) pbpaste | cdktf convert --language python --provider hashicorp/aws

Versions

language: python cdktf-cli: 0.20.7 node: v20.13.1 cdktf: 0.20.7 constructs: 10.3.0 jsii: 1.98.0 terraform: 1.5.7 arch: x64 os: darwin 21.6.0 python: Python 3.12.3 pip: null pipenv: pipenv, version 2023.12.1 providers aws@undefined (LOCAL) terraform provider version: 5.49.0 cloudflare/cloudflare@undefined (LOCAL) terraform provider version: 4.33.0 cdktf-cdktf-provider-aws (PREBUILT) terraform provider version: 5.43.0 prebuilt provider version: 19.12.0 cdktf version: ^0.20.0 cdktf-cdktf-provider-cloudflare (PREBUILT) terraform provider version: 4.33.0 prebuilt provider version: 11.11.0 cdktf version: ^0.20.0

Providers

────────────────────────────┬──────┬────────┬──────────────────────────────────┐ ────── ───── ── ─── ────────── ──── Provider Name Provider │ CDKTF│ Constra│ Package Name Package │ Version nt Version ────────────────────────────┼──────┼────────┼──────────────────────────────────┤ ────── ───── ── ─── ────────── ──── aws 5.49.0 │ │ │ │

────────────────────────────┼──────┼────────┼──────────────────────────────────┤ ────── ───── ── ─── ────────── ──── cloudflare/clou 4.33.0 │ │ │ │ flare ────────────────────────────┼──────┼────────┼──────────────────────────────────┤ ────── ───── ── ─── ────────── ──── aws 5.43.0 │ │ │ cdktf-cdktf-provider- 19.12.0 │ ^0.20.0 ws

────────────────────────────┼──────┼────────┼──────────────────────────────────┤ ────── ───── ── ─── ────────── ──── cloudflare/clou 4.33.0 │ │ │ cdktf-cdktf-provider- 11.11.0 │ flare ^0.20.0 loudflare

────────────────────────────┴──────┴────────┴──────────────────────────────────┘ ────── ───── ── ─── ────────── ────

Gist

No response

Possible Solutions

No response

Workarounds

No response

Anything Else?

@DanielMSchmidt please do not close bugs that have url shorteners pointed at them like https://cdk.tf/bugs/convert-expressions

References

Help Wanted

Community Note

nbaju1 commented 1 month ago

As I see it, the error message is correct. You are referencing something that is unknown, i.e. the variable documents_path.

Converting this succeeds:

variable "documents_path" {
  type        = string
  description = "The path to the documents folder"
  default     = "test"

}

locals {
  documents_path = var.documents_path == "" ? format("%s/%s", path.module, "documents") : var.documents_path
}
class MyConvertedCode(Construct):
    def __init__(self, scope, name):
        super().__init__(scope, name)
        # Terraform Variables are not always the best fit for getting inputs in the context of Terraform CDK.
        #     You can read more about this at https://cdk.tf/variables
        documents_path = TerraformVariable(self, "documents_path",
            default="test",
            description="The path to the documents folder",
            type=VariableType.STRING
        )
infowolfe commented 1 month ago
class MyConvertedCode(Construct):
    def __init__(self, scope, name):
        super().__init__(scope, name)
        # Terraform Variables are not always the best fit for getting inputs in the context of Terraform CDK.
        #     You can read more about this at https://cdk.tf/variables
        documents_path = TerraformVariable(self, "documents_path",
            default="test",
            description="The path to the documents folder",
            type=VariableType.STRING
        )

If you review, the format function isn't referenced here, so it's still a failure.

The main reason for this bug is because the terraform version of format takes any number of arguments you'd like but the cdktf version does not, which means that if someone wants to figure out how to concat 2 generated values (I forget the specific terminology), think something like a cloudflare_record.name + cloudflare_zone.name... there aren't really any options to do that.

nbaju1 commented 1 month ago

I think the issue here is that locals isn't being converted at all. Setting

variable "documents_path" {
  type        = string
  description = "The path to the documents folder"
  default     = "test"
}
locals {
  documents_path = var.documents_path
}

still results in the same Python code as above. Interestingly, setting it to a static string while still keeping the variable results in an empty class.

infowolfe commented 1 month ago

I guess this is probably going to get backlogged then.

It's always funny when you file a bug because you can't figure out how to do something (Fn.format() expects 3 arguments) and run into something completely unrelated.