Reputation: 2329
I have the following module which creating a private bucket. I only want to use logging, when I define a non-empty logging
argument in my module call:
variable "tags" {
description = "A mapping of tags to assign to the bucket."
type = "map"
default = {}
}
variable "logging" {
description = "A mapping of logging to assign to the bucket."
type = "map"
default = {}
}
resource "aws_s3_bucket" "private_bucket" {
bucket = "${var.bucket}"
acl = "private"
policy = "${data.aws_iam_policy_document.policy.json}"
tags = "${var.tags}"
# logging = "${var.logging}"
logging = "${length(keys(var.logging)) > 0 ? var.logging : null}"
# ...
# This block is replaced by the argument
/* logging {
target_bucket = "${var.logging_bucket}"
target_prefix = "s3/${local.bucket_id}/"
} */
# ...
}
However this is not working. I calling the module like this:
module "private_bucket" {
source = "modules/private-bucket"
bucket = "${local.private_bucket_name}"
tags {
Name = "Serverless stack private bucket"
Environment = "${local.stage}"
}
}
Why top-level if-else not implemented in Terraform? Is there any alternative to initialize a variable in a module/resource with conditional, not just it's value?
Edit:
Here is a pseudo-code, what I want to achieve:
resource "aws_s3_bucket" "private_bucket" {
bucket = "${var.bucket}"
acl = "private"
policy = "${data.aws_iam_policy_document.policy.json}"
tags = "${var.tags}"
# if var.logging is not an empty object,
# then initialize logging with the object
if (var.logging != {}) {
logging = "${var.logging}"
}
# ...
}
Upvotes: 2
Views: 13739
Reputation: 12419
If you need to check this inside a loop and you are using Terraform 0.12+, you can do it as follows. In other words, checking length(keys(...))
works now (as of Terraform 0.12).
locals {
possible_subnets = [
var.k8s_cluster_1_subnet,
var.database_subnet,
var.vpc_solr_subnet
]
}
...
module "my-module" {
...
subnet_names = [for subnet in local.possible_subnets :
subnet.name if length(keys(subnet)) > 0
]
}
Upvotes: 2
Reputation: 1507
You may use from version 0.12 (I'm not sure if before was possible before), the way to achieve what your pseudo code wants to do, may be achieved with the fllowing terraform hcl script
locals {
if_logging = var.logging ? [{}] : []
}
... (assume rest of the bucket resource definition here)
dynamic "logging" {
for_each = local.if_logging
content {
target_bucket = var.bucket
target_prefix = var.prefix
}
}
This is due to the way dynamic works.
Check dynamic docs for terraform at https://www.terraform.io/docs/configuration/expressions.html#dynamic-blocks
Upvotes: 2
Reputation: 36
You can't use maps in the then or else sections. I think that Terraform 0.12 might be more flexible.
I did the same on Azure, and ended up using the merge function in the locals{} section, with var.tags defaulting to {}:
tags = "${merge(data.azurerm_resource_group.env.tags, var.tags)}"
I then use ${local.tags}
against the resource blocks.
Upvotes: 2