I wasn't able to solve this question by any other method, so I have to ask this here...
What is the logic behind using the equal sign (=) when assigning a map to a value in Terraform 0.11.
With =
resource "pseude_resource" "pseudo_name" {
value = {
key1 = value1
key2 = value2
}
}
Without =
resource "pseude_resource" "pseudo_name" {
value {
key1 = value1
key2 = value2
}
}
The = seems to be required when using arrays ([]), but isn't when using a map. What is the reason behind this and why on earth?? Can it just be omited?
In the Terraform language, there are two distinct constructs that have quite similar-looking syntax in the common case.
An argument in Terraform is a single name/value pair where the provider dictates (in the resource type schema) what type of value it expects. You are free to create a value of that expected type any way you like, whether it be as a literal value or as a complex expression.
The argument syntax is, in general:
name = value
If a particular argument is defined as being a map then one way you can set it is with a literal value, like this:
tags = {
Name = "foo bar baz"
}
...but you can also use a reference to some other value that is compatible with the map type:
# Tags are the same as on some other VPC object
tags = aws_vpc.example.tags
...or you can combine maps together using built-in Terraform functions:
tags = merge(local.default_tags, var.override_tags)
Generally speaking, you can use any expression whose result is a map with the expected element type.
In Terraform 0.11 these non-literal examples all need to be presented in the template interpolation syntax ${ ... }
, but the principle is the same nonetheless.
Whereas an argument sets some specific configuration setting for the object whose block it's embedded in, the nested block syntax conventionally declares the existence of another object that is related to the one the block is embedded in. Sometimes this really is a separate physical object, such as a rule associated with a security group, and other times it's a more conceptual "object", such as versioning
in aws_s3_bucket
which models the versioning feature as a separate "object" because the presence of it activates the feature.
The nested block syntax follows the same conventions as the syntax for the top-level resource
, variable
, terraform
, etc blocks:
block_type "label" {
nested_argument = value
}
Each block type will have a fixed number of labels it expects, which in many cases is no labels at all. Because each block represents the declaration of a separate object, the block structure is more rigid and must always follow the shape above; it's not possible to use arbitrary expressions in this case because Terraform wants to validate that each of the blocks has correct arguments inside it during its static validation phase.
Because the block syntax and the map literal syntax both use braces {
}
, they have a similar look in the configuration, but they mean something quite different to Terraform. With the block syntax, you can expect the content of the block to have a fixed structure with a specific set of argument names and nested block types decided by the resource type schema. With a map argument, you are free to choose whichever map keys you like (subject to any validation rules the provider or remote system might impose outside of the Terraform schema).
Unfortunately today the documentation for providers is often vague about exactly how each argument or nested block should be used, and sometimes even omits the expected type of an argument. The major providers are very large codebases and so their documentation has variable quality due to the fact that they've been written by many different people over several years and that ongoing improvements to the documentation can only happen gradually.
With that said, the provider documentation will commonly use the words "nested block" or "block type" in the description of something that is a nested block, and will refer to some definition elsewhere on the page for exactly which arguments and nested blocks belong inside that block. If the documentation states that a particular argument is a map or implies that the keys are free-form then that suggests that it's an argument expecting a map value. Another clue is that block type names are conventionally singular nouns (because each block describes a single object) while arguments that take maps and other collections conventionally use plural nouns.
If you find specific cases where the documentation is ambiguous about whether a particular name is a nested block type or an argument, it can be helpful to open an issue for it in the provider's repository to help improve the documentation. Terraform's documentation pages have an "Edit This Page" link in the footer which you can use to propose simple (single-page-only) edits as a pull request in the appropriate repository.
The longer-form explanation of these concepts is in the documentation section Arguments and Blocks.
The confusion comes from the behavior of the hcl language used by terraform. The functionality isn't very well documented in terraform but... In hcl, you can define a list by using repeating blocks, which is how resources like aws_route_table define inline routes, e.g.
resource "aws_route_table" "r" {
vpc_id = "${aws_vpc.default.id}"
route {
cidr_block = "10.0.1.0/24"
gateway_id = "${aws_internet_gateway.main.id}"
}
route {
ipv6_cidr_block = "::/0"
egress_only_gateway_id = "${aws_egress_only_internet_gateway.foo.id}"
}
tags = {
Name = "main"
}
}
which would be equivalent to
resource "aws_route_table" "r" {
vpc_id = "${aws_vpc.default.id}"
route = [
{
cidr_block = "10.0.1.0/24"
gateway_id = "${aws_internet_gateway.main.id}"
},
{
ipv6_cidr_block = "::/0"
egress_only_gateway_id = "${aws_egress_only_internet_gateway.foo.id}"
}
]
tags = {
Name = "main"
}
}
You want to make sure you're using the =
when you're assigning a value to something, and only use the repeating block syntax when you're working with lists. Also, from my experience I recommend NOT using inlines when an individual resource is available.
Some very limited documentation for hcl can be found in the readme for the repo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With