Reputation: 3256
I have following tf file:
provider "aws" {
region = "us-east-1"
}
module "ec2"{
source = “../service1”
app = "${var.app}"
env = "${var.env}"
}
module "workspaces"{
source = “../service2”
app = "${var.app}"
env = "${var.env}"
}
even though service1 and service2 are different modules their underlying variables.tf file is exactly the same. Is there a way to use common variables.tf file for both modules?
Upvotes: 3
Views: 1849
Reputation: 74109
The variable declarations for each module are totally independent, so there's no built-in feature in Terraform to share them.
If you're using a filesystem that supports symlinks, you can potentially symlink the same .tf
file into multiple directories to get a similar effect. However, unless the set of variable declarations is particularly large or complicated, I'd recommend just copying them: keeping each configuration self-contained is often more helpful in the long run than avoiding a little copying of simple boilerplate code.
If you are using Terraform v0.12, you may wish to combine all of these common settings into a single object value so that the boilerplate is reduced:
locals {
context = {
app = "example"
env = var.environment
}
}
module "ec2" {
source = "../service1"
context = local.context
}
module "workspaces" {
source = "../service2"
context = local.context
}
A variable declaration like the following (in each of your child modules) will make the shape of that context
object more explicit, so Terraform can detect and report an error about it if an inappropriate value is passed:
variable "context" {
type = object({
app = string
env = string
})
}
When decomposing into multiple modules, passing around a standard set of context like the above is often good enough, but if your system is particularly complicated (lots of different subsystems represented by modules) it can be helpful in the long run to think about exactly what each module needs and pass those individual things explicitly, rather than just passing the same object everywhere.
For example, if you wanted to decouple the ec2
module from its caller, perhaps you'd design it so that it has no concept of "app" or "environment" -- those concepts belong to the caller module, but are not EC2 concepts -- and instead express the same thing in a more EC2-centric way, such as via tags:
locals {
# Common tags for all AWS objects
aws_tags = {
Name = "example ${var.environment}"
Environment = var.environment
}
}
module "ec2" {
source = "../service1"
# (other EC2-oriented settings)
tags = local.aws_tags
}
With this approach, the EC2 module only cares about EC2 concepts, and the root module translates from its own ideas of "app" and "environment" to the EC2 idea of tags. This could allow the same EC2 module to be used later in a different context where a different tagging scheme is appropriate, for example.
There's more information on this approach in the Terraform documentation section on Module Composition.
Upvotes: 2
Reputation: 1077
Yes you can.
Folder structure will be:
/service1
--main.tf
--var.tf
/service2
--main.tf
--var.tf
main.tf
var.tf
Contents of ./service1/var.tf and ./service2/var.tf:
variable "app" {}
variable "env" {}
Contents of ./var.tf
variable "app" {
default = "YOUR-APP-NAME"
}
variable "env" {
default = "dev"
}
Or you can keep the contents of all var.tf same and pass -var flag from CLI.
Upvotes: 0