There should be no reason to not follow at least these :)
Use _
(underscore) instead of -
(dash) in all: resource names, data source names, variable names, outputs.
Beware that actual cloud resources have many hidden restrictions in their naming conventions. Some cannot contain dashes, some must be camel cased. These conventions refer to Terraform names themselves.
Only use lowercase letters and numbers.
Do not repeat resource type in resource name (not partially, nor completely):
Good: resource "aws_route_table" "public" {}
Bad: resource "aws_route_table" "public_route_table" {}
Bad: resource "aws_route_table" "public_aws_route_table" {}
Resource name should be named this
if there is no more descriptive and general name available, or if resource module creates single resource of this type (eg, there is single resource of type aws_nat_gateway
and multiple resources of typeaws_route_table
, so aws_nat_gateway
should be named this
and aws_route_table
should have more descriptive names - like private
, public
, database
).
Always use singular nouns for names.
Use -
inside arguments values and in places where value will be exposed to a human (eg, inside DNS name of RDS instance).
Include count
argument inside resource blocks as the first argument at the top and separate by newline after it. See example.
Include tags
argument, if supported by resource as the last real argument, following by depends_on
and lifecycle
, if necessary. All of these should be separated by single empty line. See example.
When using condition in count
argument use boolean value, if it makes sense, otherwise use length
or other interpolation. See example.
To make inverted conditions don't introduce another variable unless really necessary, use 1 - boolean value
instead. For example, count = "${1 - var.create_public_subnets}"
main.tfresource "aws_route_table" "public" {count = "2"​vpc_id = "vpc-12345678"# ... remaining arguments omitted}
main.tfresource "aws_route_table" "public" {vpc_id = "vpc-12345678"count = "2"​# ... remaining arguments omitted}
main.tfresource "aws_nat_gateway" "this" {count = "1"​allocation_id = "..."subnet_id = "..."​tags = {Name = "..."}​depends_on = ["aws_internet_gateway.this"]​lifecycle {create_before_destroy = true}}
main.tfresource "aws_nat_gateway" "this" {count = "1"​tags = "..."​depends_on = ["aws_internet_gateway.this"]​lifecycle {create_before_destroy = true}​allocation_id = "..."subnet_id = "..."}
main.tfcount = "${length(var.public_subnets) > 0 ? 1 : 0}"
main.tfcount = "${var.create_public_subnets}"
Don't reinvent the wheel in resource modules - use the same variable names, description and default as defined in "Argument Reference" section for the resource you are working on.
Omit type = "list"
declaration if there is default = []
also.
Omit type = "map"
declaration if there is default = {}
also.
Use plural form in name of variables of type list
and map
.
When defining variables order the keys: description
, type
, default
.
Always include description
for all variables even if you think it is obvious.
Name for the outputs is important to make them consistent and understandable outside of its scope (when user is using a module it should be obvious what type and attribute of the value is returned).
The general recommendation for the names of outputs is that it should be descriptive for the value it contains and be less free-form than you would normally want.
Good structure for names of output looks like {name}_{type}_{attribute}
, where:
{name}
is a resource or data source name without provider prefix. {name}
for aws_subnet
is subnet
, foraws_vpc
it is vpc
.
{type}
is a type of a resource sources
{attribute}
is an attribute returned by the output
​See examples.
If output is returning a value with interpolation functions and multiple resources, the {name}
and {type}
there should be as generic as possible (this
is often the most generic and should be preferred). See example.
If the returned value is a list it should have plural name. See example.
Always include description
for all outputs even if you think it is obvious.
Return at most one ID of security group:
outputs.tfoutput "this_security_group_id" {description = "The ID of the security group"value = "${element(concat(coalescelist(aws_security_group.this.*.id, aws_security_group.this_name_prefix.*.id), list("")), 0)}"}
When there are multiple resources of the same type, this
should be preferred and it should be part of name in output, also another_security_group_id
should be named web_security_group_id
:
outputs.tfoutput "security_group_id" {description = "The ID of the security group"value = "${element(concat(coalescelist(aws_security_group.this.*.id, aws_security_group.web.*.id), list("")), 0)}"}​output "another_security_group_id" {description = "The ID of web security group"value = "${element(concat(aws_security_group.web.*.id, list("")), 0)}"}
outputs.tfoutput "this_rds_cluster_instance_endpoints" {description = "A list of all cluster instance endpoints"value = ["${aws_rds_cluster_instance.this.*.endpoint}"]}
There are two resources of type aws_db_instance
with names this
and this_mssql
where at most one resource can be created at the same time.
outputs.tfoutput "this_db_instance_id" {description = "The RDS instance ID"value = "${element(concat(coalescelist(aws_db_instance.this_mssql.*.id, aws_db_instance.this.*.id), list("")), 0)}"}
****