How to write module which abstracts provider

My target is create internal library of modules. Modules should support two or more providers. So when developer wants to create for example compute instance he can just import module from library and use it on AWS or Azure or some other.
So far I haven’t find a way how to do this on module level. Only solution so far is
to create folder structure like:
modules/aws/instance/main.tf etc…
modules/azure/instance/main.tf etc

And then on actual configuration:
provider “aws” {

}

module “instance” {
source = “modules/aws/instance”
}

But I want to be able to write like:
module “instance” {
source = “modules/instance”
}

And instance module includes (or source) correct version of actual implementation based on defined provider on root level.

Is there any way to do that or is it that terraform just not planned work this way?

Thanks!

You could probably get away with using a parameter like “cloud” with values like “aws” or “azure” and then a LOT of conditionals.

I would not recommend it though.

Hi @kertzi,

What you’re describing here is not a supported pattern in Terraform. Instead, the common way to do what you’re describing is like you tried already: implement multiple modules with similar variable and output blocks (thus ensuring they have a compatible interface) and then the calling module explicitly selects the required implementation, often then composing it with other modules that are compatible with any implementation.

This approach of course only works if the target vendors have similar enough offerings that you can define an abstraction over all of them. When implementing an approach like this, we’re normally thinking of higher-level abstractions like a kubernetes cluster, where there are many different ways to get one running but once they are running they all expose comparable functionality via the same API. I expect it would be difficult to define a useful abstraction over something as low-level as a single virtual machine instance, but depending on what you need from that abstraction it may be possible.

There’s more about this in the Module Composition section of the Terraform documentation, particularly in the section Multi-cloud Abstractions.

Okay, thanks for reply!