Open alex-harvey-z3q opened 5 years ago
Hi @alexharv074,
The first issue here is that all object keys are required in order to set a default. If you want each of those to be null, then you have to explicitly set them as such in the config.
You also have the option of setting the default as null
(or not having a default, and requiring the caller set a value). In that case however, you need to avoid passing a null
object into merge
, which you can do using a condition or coalesce
:
merged_map_keys = merge(local.default_map_keys, coalesce(var.prod_vpc, {}))
Using merge
to assign default attributes to an object is an interesting idea, which merge
wasn't really intended to do. We'll keep this in mind though as we gather more data about how users are building configuration with the new type system, as we may be able to build a nicer solution to this problem.
@jbardin so, I am just reading the docs here and using merge like that appears to be the recommendation. Maybe docs need updating here?
@alexharv074, I'm not sure I understand what you mean. Those docs only mention the merging of maps, but you're using an object type.
The merge
function though is only documented to accept maps. That could probably be updated to match the actual implementation, though like I said, this wasn't exactly the use case we had in mind so we may want to consider whether the implementation needs to be updated as well.
so ... yeah. this question is open again. just to clarify my use case this entire object / map /merge kerfuffle:
i would like to be able to define an object (so that i'm type safe, and the available fields are all visible etc etc), and then fill everything with examples or "reasonable defaults", so they can be overridden at some other point. it would be nice if this was possible without repetition.
i have some more details (and alex's initial comments) here:
i think we need a way to have default values get merged into objects... although i could see this being tricky with type safe checking
@alekstorm faced the same issue and one way I got it working was to use type string and use jsondecode
/jsonencode
to substitute my variables
N.B: The method will only work if it is a module
module/main.tf
variable "prod_vpc" {
default = ""
}
locals {
prod_vpc = var.prod_vpc != "" ? jsondecode(var.prod_vpc) : {}
default_map_keys = {
name = "PROD"
region = "eu-central-1"
single_nat_gw = true
create = false,
supernet = "0.0.0.0/0"
}
merged_map_keys = merge(local.default_map_keys, local.prod_vpc)
}
output "test" {
value = local.merged_map_keys
}
main.tf
module "test" {
source = "./module"
}
output "test" {
value = module.test
}
module "test2" {
source = "./module"
prod_vpc = jsonencode({"name" = "DEV", "region" = "eu-west-1"})
}
output "test2" {
value = module.test2
}
Outputs:
test = {
"test" = {
"create" = false
"name" = "PROD"
"region" = "eu-central-1"
"single_nat_gw" = true
"supernet" = "0.0.0.0/0"
}
}
test2 = {
"test" = {
"create" = false
"name" = "DEV"
"region" = "eu-west-1"
"single_nat_gw" = true
"supernet" = "0.0.0.0/0"
}
}
Invalid default value for variable
on variables.tf line 25, in variable "vpc_zone_identifier": 25: default = 2
This default value is not compatible with the variable's type constraint: list of string required. `im getting this error
`
@jeevanashanthi vpc_zone_identifier
should be a list, and not a number/string. Try setting default = []
.
okay tq
Summary
When attempting to set an empty map as the default in a variable of type object(map), a message
This default value is not compatible with the variable's type constraint
is seen.Terraform Version
Steps to reproduce
Create the following content in a file test.tf and apply it:
Debug Output
Nothing interesting seen when setting TF_LOG.
Expected Behavior
I expected this to apply fine and output the merged has. I note a comment by Martin Atkins here that suggests this syntax should work.
Actual Behavior
References
See also docs here.