How to get Resource Type

Hello, I’m working on a module with following input

variable "source_resource" {
  type = any
}

The input here will be an AWS resource e.g a Lambda function or a DynamoDb table. Is there a way to identify what resource type it is after we getting the input? I don’t find a common attribute of all AWS resources.
Technically I can use ARN but it’s after terraform apply. I would like to get the type which will be used on count attribute.

The ARN doesn’t work because it’s only available after deployment. If I use it in count, an error will be thrown:

The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to first apply only the resources that the count depends on.

Hi @xzhao1821,

Terraform has a structural type system rather than a nominal type system, and so it only keeps track of the shape of objects, not the name of the resource type (or whatever other object) they were created from.

With that said, I’m not really sure I follow exactly what you are trying to do. Can you show an example of what the rest of your configuration looks like when making use of this object? I understand that your approach with ARN didn’t work, but I’d still like to see the code you tried when you saw that error since hopefully it’ll help me to understand what you are trying to do and I can propose some other way to do it.

Hi @apparentlymart ,

Thanks for the reply. Sure I can share some simplified code

variable "source_resource" {
  type = any
}

resource "aws_lambda_permission" "lambda_permission" {
  count = # Check if var.source_resource is a ref to Resource: aws_api_gateway_rest_api ? 0 : 1
  ...
}

So basically if the input is a ref to object of ApiGateway RestApi, this module will create a lambda_permission resource. It’s conditional resource creation. Is there another way to do it?

Hi @xzhao1821,

Unfortunately what you are trying to do here won’t be possible exactly as you framed it… Terraform itself doesn’t “know” what resource type that object came from as soon as you pass it somewhere else; it just tracks what attributes the object has.

I think the closest you could get here is to define a separate input variable for each of the types you want to support and then make the caller of your module choose the correct input variable to use based on the type, like this:

module "example" {
  # ...

  aws_lambda_function = aws_lambda_function.example
}

Another way to do it would be to retain your existing single input variable called source_resource and then add a second input variable that specifies the resource type as a string, and then your caller would need to set both:

``
module “example” {

source_resource = aws_lambda_function.example
source_resource_type = “aws_lambda_function”
}


In both cases the user of your module will need to be explicit about which resource type their object is intended to be. An advantage of the first approach is that each input variable could have it's own exact object type constraint to help Terraform notice and return an error if the user assigns the wrong kind of object to the wrong argument, but an advantage of the second option is that you don't need to deal with the possible incorrect usage of setting more than one of the variables.