I am using common code for deploying resources on dev, INT and prod in azure(by diff varible groups for dev, INT and prod), I am trying to enable Availability zones only on Prod Redis not enabling on dev and INT envi, which feature condition/loops etc I need to use to fix this.
If your different environments are not substantially the same then I’d recommend using a separate root module for each of your environments. You can factor out all of the resources that are common across all of your environments into a shared module that you can reuse across all of them, but you can place any resources that are unique to a particular environment outside of that module.
While it is technically possible to use dynamic conditions to enable and disable objects, that’ll tend to make things harder to understand. Writing a tailored module for each environment and only reusing the part that’s actually common tends to lead to a more straightforward configuration overall.
Hi Apparentlymart,
Thanks for your time, is it possible to get the sample/example code for mentioned solution?.
Hi @rahulkammili4,
I cannot show a detailed example because I don’t know any details about how your system is designed.
The general idea I described would involve a directory structure something like this:
modules/
environment-common/
(.tf files)
environments/
prod/
(.tf files)
int/
(.tf files)
dev/
(.tf files)
The modules/environment-common
directory will be a shared module describing all of the infrastructure that should be declared in all three environments.
Inside each of the subdirectories of environments
you will have a module
block calling the shared module and then any other resources you need that are specific to each environment.
module "common" {
source = "../../modules/environment-common"
resource_group_name = "prod"
# ...
}
# (and then other resources here)
You’ll need to design the environment-common
module so that it takes input variables to describe any naming differences and other minor differences between the environments. For example, in Azure you will probably need input variables to define a name for the environment’s resource group, which I showed as resource_group_name
in the module
call above. Inside the environment-common
module you must declare those variables like this:
variable "resource_group_name" {
type = string
}
Your root module will probably also need some values from inside the environment-common
module to declare other related resources, which you can export as output values from the module. For example, you will probably need to export the resource group ID so that other resources can refer to it:
output "resource_group_id" {
value = azurerm_resource_group.example.id
}
The separate environment modules could then refer to the resource group ID by accessing that output value by reference to the module
block: module.common.resource_group_id
.
When you apply these configurations you’ll work separately in each environment directory, because these environments are completely isolated from each other. For example:
cd environments/prod/
terraform init
terraform apply
I hope that’s a helpful starting point! You’ll need to fill in the specific resources, input values, and output values that you need for your particular system but this shows the general pattern of calling into another module to share some declarations between multiple configurations.
Thanks for your valuable time and guidance, when I am going through the terraform docs and I found lifecycle option.
resource azurerm_redis_cache" “redis” {
…
lifecycle {
precondition {
condition = var.redis_azone_enabled == true ? 1 : 0
zones = [1, 2]
}
}
}
Variable redis_azone_enabled will be true for prod and false for other envi, any suggestions on above block of code, whether it works on not?.
Hi @rahulkammili4,
The purpose of a precondition block is to raise an error if the condition isn’t true.
Your condition expression is invalid because it produces a number rather than a boolean result. But even if it did produce a boolean result I don’t think it would achieve a useful result, because it would declare that it’s invalid to not have this variable enabled, raising an error in any situation where it is false.
I think you are thinking about the pattern of using a conditional expression in the count
argument to decide between either zero or one instances of a resource. That is a possible way to meet this requirement. It typically leads to a more complicated configuration overall because a reader must carefully understand all of the different combinations of functionality that are implied by all of your different conditions, but if you only have one or two conditions then it might work okay for your situation.
Hi @apparentlymart ,
is it possible to make a variable value(zones) as null for redis basic SKU?
resource azurerm_redis_cache" “redis” {
zones = var.redis.zone
}
variable “redis.zone”
{
type = list(any)
}