User Experience with Terraform Default Values !
My Experience with default values
I have created few Terraform resources with the modules provided to me and it simply worked. However I started reviewing my experience and key points of my experiences are :
- Smile on my face ! :-)
- It worked at first go ! :-)
- Resources got created without any user intervention ! :-) :-(
- I realised that resources are created with configurations which I did not intend in my mind :-(
- I was expecting the module to prompt for some of those values ! :-(
- I then figured out that the default values need to be changed for some of the variables or needs to be overridden as I wanted different values
- I passed the correct set of values and executed the Terraform workflow few times till I got what I wanted :-):-(
This is not a big concern when working with small teams or very few resources. However I have seen such experience leading to time consuming deployment cycles , increased cost of development and frustrating experience especially in the Enterprise World. This is quite evident if your Terraform creates large infrastructure. For me the concerning factor was the increased development viscosity caused due to this !
There are various factors to cause increased development viscosity such as:
- Lack of appropriate documentation
- Not reading through the set of default values
- General tendency of developers to try out the code straight away with minimal or no reading of related documentation
- Use or inappropriate use of default values !
In this post I will focus on the default values causing increased development viscosity !
When to provide the default value ?
When appropriate, provide default values. But what is appropriate ?
The following guidelines worked well for me so far.
Provide default values for variables that have environment-independent values
This could be based on the company wide guidelines or based on general best practices followed.
- Disk Size for Amazon EKS Nodes
- No NAT Gateway should be created by default in the VPC
- By default No public IP for any of the EC2 instances
- …
Do NOT Provide default values for variables that need to have environment-specific values
Some of the use cases where you want user to specify those values could be :
- project-id /project-name/cost-centre
- region
- IP range for VPC
- EC2 Instance Type
- …
Specifying Default Value
I have seen different variations while specifying the variable values.
# example-1-default-valuevariable "var_name" {
type = string
default = "default-value"}# example-2-empty string
variable "var_name" {
type = string
default = ""
}# example-3-string with spaces (best to avoid)
variable "var_name" {
type = string
default = " "
}# example-4-null value variable "var_name {
type = string
default = null}#example-5 - no default value
variable "var_name" { type = string}
What should be the default value ?
Use Sensible defaults
The onus of putting default values should be on the module developer as module developer is writing TF config so they know what is the impact of it.
For e.g. EBS volume size = 8 GB
Empty defaults (example-2,example-3)
Use empty default values for variables (like empty strings or lists) only when the underlying provider API don’t reject it and you want to build some custom logic based on empty value.
I generally don’t use unless it is absolutely necessary.
Avoid usage of ‘example-3’ — This is mentioned because I have seen this in the projects.
Using NULL for Optional Elements (example-4)
Terraform v0.12 onward allows assigning the special value null
to an argument to mark it as "unset".
null
: a value that represents absence or omission. If you set an argument of a resource tonull
, Terraform behaves as though you had completely omitted it — it will use the argument's default value if it has one, or raise an error if the argument is mandatory.null
is most useful in conditional expressions, so you can dynamically omit an argument if a condition isn't met.
The following snippet of variables.tf from aws-s3-bucket module shows the default = null is set for bucket ,bucket_prefix and acl.
These variables are used in the the main.tf
You will notice that there is no difference in the way these variable are used in spite of having null default value.
In this case those variables with value = null will be omitted by the terraform and the underlying provider creates the resource considering those values are not set.
If the value of those variables are provided e.g. bucket = “testbucket2905200” then that will be used !
This is very useful as the AWS resources generally have large number of properties/settings/configurations for a given resource and it could be really overwhelming to provide default values for all , which in many cases may not be required !
It makes sense to use the ‘null’ as a default value for those variables which are optional and you understand the implication of not providing those values
Don’t provide the default value if you want consumer must provide the values
Follow this guideline judiciously as this creates a bit of inconvenience for the consumer of Terraform code. But it is a trade off with convenience so decide what works well for you and go for it.
Summary
Terraform input variables provide a way to provide default value for a given variable , making it optional to provide the value for the variable. However be judicious about setting up the default values. If you want consumer of the Terraform code must specify the value or ensure that user is conscious about values then do not provide any default values for that variable. This forces consumer of the Terraform Module to think about it rather than discovering after creation !