Hi @bingerk,
It sounds like your downstream configuration (the one with the data
block) needs to be parameterized with an environment name, at least, in order to be able to represent the necessary variations between your environments.
The main building-block for that would be to declare a variable to represent the environment name, like this:
variable "environment" {
type = string
}
The question then becomes how best to populate it. My preferred strategy is to put all of the objects whose configuration is the same across environments into a shared module and then create separate small root modules for each environment that only configure a suitable backend and call the module, like this:
# Configuration specific to the "prod' environment, for example
terraform {
backend "azurerm" {
key = "prod.terraform.tfstate"
# and so on...
}
}
module "main" {
source = "../modules/main"
environment = "prod"
}
The other way to do it is to have only a single root module and combine the -var-file
argument to terraform apply
with the -backend-config
argument to terraform init
to populate the environment-specific parts, but I prefer the above because it keeps everything together in one place and allows just running the normal terraform init
and terraform apply
commands with no special arguments.
Another pattern to consider is having a data-only module which takes an environment name and returns structured information about that environment, which can then avoid duplicating information about how to fetch the various bits of information across every caller and thus allow you to potentially change to get that information in other ways (like a dedicated configuration store) in future.
# (this example is in the "main" module
# I declared in the above example)
variable "environment" {
type = string
}
module "env" {
source = "../join-environment"
environment = var.environment
}
data “azurerm_log_analytics_workspace” “diagnostic” {
name = module.env.log_analytics_workspace_name
resource_group_name = module.env.resource_group_name
}
If access to the “log analytics workspace” is a trait common to most or all of your different configurations then you could potentially put the data source in the join-environment
module and export the information it returns as outputs, but exactly what to include in the “environment” vs. what to include in the downstream configurations is an engineering tradeoff rather than a straightforward rule.
For the sake of keeping this example relatively similar to what you shared, here I assumed that the environment module just contains the construction rule to statically produce a log analytics workspace name given an environment name, leaving the calling module to actually fetch the data from that object if needed.