Terraform 0.11 — conditional assignment of a map to attribute.
I present a way to achieve that with some small hacks.
Problem :
You have a Terraform module in which you want to configure an attribute of a resource that takes a map as input.
As of Terraform 0.11 it’s not possible to pass maps or nested structures into the module. A workaround is to pass either minimum set of strings or flat arrays (with join-split) to module and inside a module, build variations of a map and then conditionally use it depending on parameters passed to module.
Example:
Kubernetes provider — resource replication controller https://www.terraform.io/docs/providers/kubernetes/r/replication_controller.html
has an attribute ‘readiness_probe’ and ‘liveness_probe’ those can be of type ‘exec’ or ‘http_get’, map for exec looks like that:
exec = [{
command = [“${split(“,”,var.readiness_probe_exec)}”]
}]
failure_threshold = “${var.failure_threshold}”
period_seconds = “${var.period_seconds}”
success_threshold = “${var.success_threshold}”
timeout_seconds = “${var.timeout_seconds}”
initial_delay_seconds = “${var.initial_delay_seconds}"
http_get on the other hand requires such config:
http_get = [{
path = “${var.http_probe_url}”
port = “${var.http_probe_port}”
}]
failure_threshold = “${var.failure_threshold}”
period_seconds = “${var.period_seconds}”
success_threshold = “${var.success_threshold}”
timeout_seconds = “${var.timeout_seconds}”
initial_delay_seconds = “${var.initial_delay_seconds}”
As we can see there are some differences, so big question is, how to conditionally assign a check to a resource in a module. Answer is, pre-defined map of maps and conditional as a key. Remember here that conditional assignments can only be done with string and strings only.
How does it look in practice:
locals {
probe {
http_probe {
http_get = [{
path = “${var.http_probe_url}”
port = “${var.http_probe_port}”
}]
failure_threshold = “${var.failure_threshold}”
period_seconds = “${var.period_seconds}”
success_threshold = “${var.success_threshold}”
timeout_seconds = “${var.timeout_seconds}”
initial_delay_seconds = “${var.initial_delay_seconds}”
}
exec_probe {
exec = [{
command = [“${split(“,”,var.readiness_probe_exec)}”]
}]
failure_threshold = “${var.failure_threshold}”
period_seconds = “${var.period_seconds}”
success_threshold = “${var.success_threshold}”
timeout_seconds = “${var.timeout_seconds}”
initial_delay_seconds = “${var.initial_delay_seconds}”
}
}
}readiness_probe = [“${local.probe[“${var.http_probe_url == “” || var.http_probe_port == “” ? “exec_probe” : “http_probe”}”]}”]
Above example is also available (in more readable form) on my github: https://github.com/jaceq/terraform-examples/blob/master/examples/conditional-map.tf