Override files in Terraform are used to partially override existing configuration objects in separate files. Here are few key pointers to be noted:
- Override files are named with a suffix of
_override.tf
or_override.tf.json
, and Terraform processes them after loading the regular configuration files. - For each top-level block defined in an override file, Terraform merges the contents of the block into the corresponding object in the regular configuration files.
- Use override files sparingly and only in special circumstances, as overusing them can hurt the readability and maintainability of your code.
- When using override files, use comments in the original files to indicate which override files apply changes to each block.
- Override files can be used to override any Terraform object, including resources, modules, and data sources.
Here are a few scenarios considered when you override the existing configuration. The second column has a sample override file configuration for AWS VPC and you can see what will happen if this is applied to the Original configuration file.
Feature | Sample Override file configuration | Original file configuration | Final result |
Top-level block | resource “aws_vpc” “vpc-new” { cidr_block = “172.16.0.0/16” enable_dns_hostnames = “true” } | resource “aws_vpc” “vpc-new” { cidr_block = “10.0.0.0/16” enable_dns_hostnames = “false” } | Merges with same block header; Replaces attribute arguments resource “aws_vpc” “vpc-new” { cidr_block = “172.16.0.0/16” enable_dns_hostnames = “true” } |
Blocks with attributes defined | resource “aws_vpc” “vpc-new” { cidr_block = “172.16.0.0/16” } | resource “aws_vpc” “vpc-new” { cidr_block = var.cidrblk enable_dns_hostnames = “false” } | Replaces or merges attribute arguments resource “aws_vpc” “vpc-new” { cidr_block = “172.16.0.0/16” enable_dns_hostnames = “false” } |
Nested blocks | resource “aws_vpc” “vpc-new” { cidr_block = “172.16.0.0/16” } | resource “aws_vpc” “vpc-new” { cidr_block = “192.168.0.0/16” lifecycle { create_before_destroy = true } } | > +/- create replacement and then destroy but applies to the configuration provided in Override file; any nested blocks within an override block replace all blocks of the same type in the original block. Any block types that do not appear in the override block remain from the original block. |
Lifecycle block | resource “aws_vpc” “vpc-new” { cidr_block = “192.168.0.0/16” lifecycle { ignore_changes = [ cidr_block, tags] } } | resource “aws_vpc” “vpc-new” { cidr_block = “10.0.0.0/16” enable_dns_hostnames = “false” lifecycle { create_before_destroy = true } } | Merged arg by arg; Ignores the relevant attributes using ignore_changes and make no changes |
Lifecycle block-ignore changes in the original file | resource “aws_vpc” “vpc-new” { cidr_block = “192.168.0.0/16” lifecycle { create_before_destroy = true } } | resource “aws_vpc” “vpc-new” { cidr_block = “10.0.0.0/16” lifecycle { ignore_changes = [ cidr_block, tags] } } | If an override block sets only the create_before_destroy argument then any ignore_changes argument in the original block will be preserved. |
Lifecycle block | resource “aws_vpc” “vpc-new” { cidr_block = “192.168.0.0/16” lifecycle { create_before_destroy = true } } | resource “aws_vpc” “vpc-new” { cidr_block = var.cidrblk enable_dns_hostnames = “false” lifecycle { create_before_destroy = false } } | Creates replacement and destroys the resource with cidr block of “192.168.0.0/16” |
Provisioner and connection block | provisioner “file” { source = “conf/newapp.conf” destination = “/etc/newapp.conf” connection { type = “ssh” user = “root” password = “${var.root_password}” host = “${var.host}” } } | provisioner “file” { source = “conf/myapp.conf” destination = “/etc/myapp.conf” connection { type = “ssh” user = “root” password = “${var.root_password}” host = “${var.host}” } } | If an overriding resource block contains one or more provisioner blocks then any provisioner blocks in the original block are ignored; If an overriding resource block contains a connection block then it completely overrides any connection block present in the original block. |
variable argument | variable “cidrblk” { type = string default = “192.168.0.0/16” } | variable “cidrblk” { type = string default = “10.0.0.0/16” } | Value considered is 192.168.0.0/16; Variable argument overrides |
Changes in variable type than the default value | variable “xyz” { description = “Testing” type = bool } | variable “xyz” { description = “Testing” type = string default = “yes” } | Changes in variable type (here ‘boolean’) takes precedence than the default value |
changes in default value should be compatible | variable “enabledns” { type = bool } | variable “enabledns” { type = string default = “false” } | default = “false” will be considered since it is compatible with the bool type |
Changes in variable type & default value | variable “enabledns” { type = bool default = true } | variable “enabledns” { type = string default = “false” } | Changes in variable type default = true will be considered |
required_providers | terraform { required_providers { aws = { version = “~> 4.12.0” } random = { version = “>= 2.1.2” } } } | terraform { required_providers { aws = { version = “~> 2.13.0” } random = { version = “>= 2.1.2” } } } | value merged element by element terraform { required_providers { aws = { version = “~> 4.12.0” } random = { version = “>= 2.1.2” } } } |
required_version | required_version = “~> 1.2.3” | required_version = “~> 0.12.29” | The base block is ignored required_version = “~> 1.2.3” |
Varied Backends | cloud | backend | cloud takes precedence |
Varied Backends | backend | cloud | backend takes precedence |