Module Interface

We have many modules that we use to create aws resources and all of them are used independently for deployments. For common patterns, I want the user to only have to call one module for their deployment. I don’t want to duplicate the code in the modules we have already created so I was thinking of doing something like creating a serverless api module that would call the individual modules to create the pattern.

Is there a better way of doing this? Would this be a bad idea?

Have you considered refering remote module source code instead of dupilcate in your own repo?

eg:

##main.tf

module "hashicat" {
  source  = "app.terraform.io/yulei/hashicat/aws"
  version = "0.0.1"
  # insert required variables here
  prefix = "yulei"
  height="1024"
  width = "15326"
  region="ap-southeast-2"
  instance_type = "t3.micro"

}%

I think maybe I didn’t explain the use case very well. I can not use publicly available modules that are in the terraform registry, I have to use internally created modules for this. Currently we have something like this that the user has to do:

##main.tf

module "lambda" {
  source  = "git::https://my-lambda-module.git?ref=1.0.0"
  
  # insert required variables here
}

module "apigateway" {
  source  = "git::https://my-apigateway-module.git?ref=1.0.0"
  
  # insert required variables here
}

module "alb" {
  source  = "git::https://my-alb-module.git?ref=1.0.0"
  
  # insert required variables here
}

module "route53" {
  source  = "git::https://my-route53-module.git?ref=1.0.0"
  
  # insert required variables here
}

What I would like to is have the user only need to call one module like this:

module "serverless-api" {
  source  = "git::https://my-serverless-api-module.git?ref=1.0.0"
  
  # insert required variables here
}

My question is how best to do that?

I don’t want to copy my code from the other modules into one because that would be hard to maintain since if I make a change in one of the modules then I have to do the same in the serverless module.

Could I have the main.tf of the serverless-api module reference all the other modules that are needed or is that against best practices?

It’s certainly possible, but it comes with some drawbacks:

  • You have to write a lot of repetitive code to pass through all the input variables through the serverless-api module to the lambda, apigateway, alb modules.

  • The user cannot individually specify the versions of the lambda, apigateway, alb modules, so you’ll frequently need to re-release the serverless-api module just to increment the version numbers of the contained modules.

If these seem acceptable to you, then yes, you should go ahead with this approach.

The first issue I am not really concerned with, it is the versioning on the serverless API module that concerns me because to your point, it could be versioned often.

Any ideas on a better approach?

Just have the users specify all of the other modules explicitly then.

I started this thread because I don’t want to do that.

I can’t image others haven’t it this same issue so just wondering what others have done.

Terraform is pretty inflexible about module source values - they can’t be variables, for example.

That being the case, I think you have a simple choice between:

  • Users specify all the modules
  • You create a bundling module, with the drawbacks already discussed

You’re not really happy with either of those options, but I don’t think any others exist.

Instead of using modules stored in Git publish them to a registry.

With git modules you can only reference versions using git tags & branches (as that is all git provides), so generally you’d point at a fixed version tag.

If you publish to a Terraform registry you are able to use a more fully featured version constraints system, such as equal to, greater than, less than, and clauses or pinning to major/minor versions.

So for example you could publish your module that pins each sub-module usage to a given major version number, and then you’d only need to publish a new master module if there are breaking changes (which you’d likely have to do anyway, as other code would likely have to change at that point too)

1 Like

Thank you, I was about to ask about that. We are in process of creating an internal terraform registry so I will wait for that to be completed.