As explained in #2114, the current override behavior is incomplete. The override behavior up to v0.53 is as follows:
Attributes in blocks with matching headers (type and labels) are merged.
Nested blocks are also merged recursively.
If there are multiple blocks with the same header (e.g. terraform, locals), only one of them will be overridden. Which one gets overwritten is non-deterministic.
The order in which override files are processed is completely random, not lexicographical.
# main.tf
resource "aws_instance" "foo" {
instance_type = "t2.micro" # => Should be c5.xlarge, but can be m5.xlarge
# The entire block is overwritten, the volume_type should be discarded, but only the volume_size is overwritten
ebs_block_device {
volume_type = "gp3"
volume_size = 20
}
}
# main1_override.tf
resource "aws_instance" "foo" {
instance_type = "m5.xlarge"
ebs_block_device {
volume_size = 50
}
}
# main2_override.tf
resource "aws_instance" "foo" {
instance_type = "c5.xlarge"
}
# main.tf
terraform {
backend "s3" {}
}
terraform {
# If the terraform block below is overridden then "google" will be merged,
# but if the one above is overridden then it will be ignored.
required_providers {
aws = {}
}
}
# main_override.tf
terraform {
required_providers {
google = {}
}
}
This PR fixes the override behavior to follow the Terraform spec. The following changes will be made:
Attributes in blocks with matching headers are merged, although some blocks, such as terraform blocks, are merged with different rules.
Nested blocks are replaced entirely instead of being recursively merged.
Overrides are processed in lexicographical order by filename.
In most cases, this change should be considered a bug fix as it results in stricter Terraform override behavior, and should have little to no impact unless you are doing complex overrides.
Finally, the behavior of overriding for multiply declarable blocks (e.g. terraform, locals) requires some caution: the GetModuleContent API returns different formats depending on whether there is one or more blocks.
For example, if only one required_providers is declared, the override will apply for that block:
# main.tf
terraform {
# Only one block with required_providers is returned, containing 3 attributes: "aws", "google", and "azurerm".
required_providers {
aws = {}
}
}
# main_override.tf
terraform {
required_providers {
google = {}
}
}
terraform {
required_providers {
azurerm= {}
}
}
On the other hand, if multiple required_providers are declared, the new attributes will be returned as a new block:
# main.tf
terraform {
required_providers {
aws = {}
}
}
terraform {
required_providers {
google = {} # => This will be overridden
}
}
# main_override.tf
terraform {
required_providers {
google = {}
azurerm = {} # => This is not merged with either one and is returned as a new block, meaning the caller receives 3 "terraform" blocks.
}
}
This is because it is not obvious which block the new attribute should be merged into.
Fixes https://github.com/terraform-linters/tflint/issues/2114
As explained in #2114, the current override behavior is incomplete. The override behavior up to v0.53 is as follows:
terraform
,locals
), only one of them will be overridden. Which one gets overwritten is non-deterministic.This PR fixes the override behavior to follow the Terraform spec. The following changes will be made:
terraform
blocks, are merged with different rules.In most cases, this change should be considered a bug fix as it results in stricter Terraform override behavior, and should have little to no impact unless you are doing complex overrides.
Finally, the behavior of overriding for multiply declarable blocks (e.g.
terraform
,locals
) requires some caution: theGetModuleContent
API returns different formats depending on whether there is one or more blocks.For example, if only one
required_providers
is declared, the override will apply for that block:On the other hand, if multiple
required_providers
are declared, the new attributes will be returned as a new block:This is because it is not obvious which block the new attribute should be merged into.