This is my existing terraform module code for AWS Batch
resources:
resource "aws_batch_compute_environment" "compute_environment" {
count = var.create_compute_environment ? 1 : 0
...
...
}
resource "aws_batch_job_queue" "job_queue" {
count = var.create_batch_job_queue ? 1 : 0
...
compute_environments = length(var.batch_job_queue_ce) == 0 ? [aws_batch_compute_environment.compute_environment[0].arn] : var.batch_job_queue_ce
}
This allows me to create an AWS Batch Compute environment
and a Job queue
. If my job queue
has just 1 compute environment
to be associated with, I don't have to define anything in the calling module and it associates with the corresponding compute environment
created as part of the module. If there are more than 1, I pass a list of those in the variable batch_job_queue_ce
.
Now, I'm trying to replace the compute_environments
argument with the compute_environment_order
as it is deprecated. Read here
I'm trying to add a dynamic
block for compute_environment_order
in my module:
resource "aws_batch_job_queue" "job_queue" {
count = var.create_batch_job_queue ? 1 : 0
...
dynamic "compute_environment_order" {
for_each = var.compute_environment
content {
order = compute_environment_order.value.order == "" ? 0 : compute_environment_order.value.order
compute_environment = compute_environment_order.value.compute_environment == "" ? aws_batch_compute_environment.analytics_platform_ce[0].arn : compute_environment_order.value.compute_environment
}
}
}
variable "compute_environment" {
description = "Compute environments to be associated with the job queue"
type = list(object({
order = number
compute_environment = string
}))
default = []
}
What I now want is to not define anything related to this dynamic
block in the calling module, like it was the case earlier, if there is just 1 compute environment to be associated with the job queue, again as was the condition earlier.
In my calling submodule, if I don't pass anything for compute_environment
variable or if I just pass compute_environment = []
, it fails with the error:
ā Exactly one of these attributes must be configured: ā [compute_environments,compute_environment_order]
If I define a value like this in my calling module:
compute_environment = [
{
order = 0
compute_environment = module.dev_dsm_batch_sandbox.compute_environment_arn[0]
}
]
it works fine, but I would like to avoid doing this, for the reasons explained above.
I think I'm missing a point here regarding the use of dynamic blocks for such a use case. Would appreciate pointing me in the right direction.
I don't have access to an AWS environment to reproduce your code, but the below demonstrates the concept of using a dynamic block and then having a default if the var is an empty list, if not then use the var.
mod1/main.tf Here we can set the default value, then use the coalesclist function to pick the first non empty list. We start with the var then fall back to the default
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = ">=3.0.0"
}
}
}
locals {
default_volumes = [
{
name = "myapp_config"
path = "/etc/my/app/config"
}
]
container_volumes = coalescelist(var.volumes, local.default_volumes)
}
variable "volumes" {
default = []
}
resource "docker_container" "myapp" {
name = "myapp"
image = "myapphub/myapp"
dynamic volumes {
for_each = local.container_volumes
content {
volume_name = volumes.value["name"]
container_path = volumes.value["path"]
}
}
}
main.tf we call the module twice, once with an empty var and once with a list in the var
module "test1" {
source = "./mod1"
}
module "test2" {
source = "./mod1"
volumes = [
{
name = "myapp_logs"
path = "/etc/my/app/log"
},
{
name = "myapp_profile"
path = "/etc/my/app/profile"
}
]
}
And what we see in the output is for the first module call which didnt define a var, it uses the default in the module.
Terraform will perform the following actions:
# module.test1.docker_container.myapp will be created
+ resource "docker_container" "myapp" {
...
...
+ volumes {
+ container_path = "/etc/my/app/config"
+ volume_name = "myapp_config"
# (2 unchanged attributes hidden)
}
}
In the second call where we have defined the var as a list of two items, it uses those two instead of the default.
# module.test2.docker_container.myapp will be created
+ resource "docker_container" "myapp" {
...
...
+ volumes {
+ container_path = "/etc/my/app/log"
+ volume_name = "myapp_logs"
# (2 unchanged attributes hidden)
}
+ volumes {
+ container_path = "/etc/my/app/profile"
+ volume_name = "myapp_profile"
# (2 unchanged attributes hidden)
}
}