admin管理员组

文章数量:1277903

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_environmentpute_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 = varpute_environment
    content {
      order = compute_environment_order.value.order == "" ? 0 : compute_environment_order.value.order
      compute_environment = compute_environment_order.valuepute_environment == "" ? aws_batch_compute_environment.analytics_platform_ce[0].arn : compute_environment_order.valuepute_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_sandboxpute_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.

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_environmentpute_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 = varpute_environment
    content {
      order = compute_environment_order.value.order == "" ? 0 : compute_environment_order.value.order
      compute_environment = compute_environment_order.valuepute_environment == "" ? aws_batch_compute_environment.analytics_platform_ce[0].arn : compute_environment_order.valuepute_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_sandboxpute_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.

Share Improve this question asked Feb 23 at 22:13 rock'n rollarock'n rolla 2,2311 gold badge17 silver badges24 bronze badges 2
  • When you don't pass a compute_environment from the calling code are you still going to inject the compute environment created inside the module? – Chris Doyle Commented Feb 23 at 23:22
  • 1 Not directly related to your question, but FWIW: compute_environment_order.value.order == "" in your conditional expression will always return false, because "" (empty string) can never be equal to a value of number type. – Martin Atkins Commented Feb 24 at 21:59
Add a comment  | 

1 Answer 1

Reset to default 2

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)
        }
}

本文标签: Terraform dynamic block to be executed with default valuesStack Overflow