linode/terraform-provider-linode

[Bug]: CDKTF: domain

nfcopier opened this issue · 3 comments

Terraform Version

Terraform v1.3.6

Linode Provider Version

version = "1.29.4"

Effected Terraform Resources

linode_domain
linode_domain_record

Terraform Config Files

import {TerraformStack} from "cdktf";
import {Construct} from "constructs";
import {Domain} from "./.gen/providers/linode/domain";
import {DomainRecord} from "./.gen/providers/linode/domain-record";

export class MyDomain extends TerraformStack {
    public constructor(scope: Construct, id: string) {
        super(scope, id);
        const myDomain = new Domain(this, "domain", {
            type: "master",
            domain: "example.com"
        });
        new DomainRecord(this, "domain-record", {
            recordType: "A",
            name: "test.example.com",
            target: "12.34.56.78",
            domainId: myDomain.id //TypeError `myDomain.id` is string, but `domainId` requires number
        })
    }
}

Debug Output

No response

Panic Output

No response

Expected Behavior

DomainRecord should expect the Terraform ID as a string, or Domain should export its numericId as a number instead of just the construct ID as a string. Relevent doc.

Actual Behavior

I have no way to link a Domain to a DomainRecord without a compilation error.

Steps to Reproduce

  • Create a cdktf TypeScript projec.
  • Add the Linode provider to cdktf.json:
{
  "terraformProviders": [
    {
      "name": "linode",
      "source": "linode/linode",
      "version": "1.29.4"
    }
  ]
}

Create a Domain construct.
Create a DomainRecord construct and try to use the Domain's id as the DomainRecord's domainId property.

Thanks for the report!
Looks like we'll just need to expose an ID schema field in the linode_domain resource since the implicit Terraform ID is always stored as a string. I'll add a ticket to our internal tracker to address this soon.

In the meantime, for anyone that comes across this issue or something similar, there's a way to get any Terraform attribute in cdktf regardless of whether it's exported on the TypeScript construct using getStringAttribute(), getNumberAttribute(), etc.

In this case, the workaround would look like this:

import {TerraformStack} from "cdktf";
import {Construct} from "constructs";
import {Domain} from "./.gen/providers/linode/domain";
import {DomainRecord} from "./.gen/providers/linode/domain-record";

export class MyDomain extends TerraformStack {
    public constructor(scope: Construct, id: string) {
        super(scope, id);
        const myDomain = new Domain(this, "domain", {
            type: "master",
            domain: "example.com"
        });
        new DomainRecord(this, "domain-record", {
            recordType: "A",
            name: "test.example.com",
            target: "12.34.56.78",
            domainId: myDomain.getNumberAttribute("id")
        })
    }
}

I used a similar workaround to get the IP address of the master node of an LKE cluster to use as the target:

const cluster = new LkeCluster(...);
// This assumes the master node is the first node in the first node pool
const firstNodePool = cluster.pool.get(0);
const masterNode = firstNodePool.get(0);
const masterInstanceId = masterNode.getStringAttribute("instance_id");
// Get the instance
const linodeInstances= new DataLinodeInstance(this, "instances", {
  filter: [{
    name: "id",
    values: [masterNodeId]
  }]
});
const masterInstance = linodeInstances.get(0);
// Get the IP address from the instance
// Note that if the node pool is recycled, the IP address will change the Terraform state would need to be updated
const ipAddress = masterInstances.ipAddress();

Note that in this case, there are several steps to get to the IP address, but it does work.

We've taken a look into this. It looks like terraform handles resource attributes called id as a special case making it impossible to expose the ID schema field in the linode_domain resource. Here is an alternate workaround you can use. I hope this helps!