{% hint style="info" %} There should be no reason to not follow at least these :) {% endhint %}
- 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" {}
- Good:
- 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 typeaws_nat_gateway
and multiple resources of typeaws_route_table
, soaws_nat_gateway
should be namedthis
andaws_route_table
should have more descriptive names - likeprivate
,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 bydepends_on
andlifecycle
, 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 uselength
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}"
{% hint style="success" %} {% code-tabs %} {% code-tabs-item title="main.tf" %}
resource "aws_route_table" "public" {
count = "2"
vpc_id = "vpc-12345678"
# ... remaining arguments omitted
}
{% endcode-tabs-item %} {% endcode-tabs %} {% endhint %}
{% hint style="danger" %} {% code-tabs %} {% code-tabs-item title="main.tf" %}
resource "aws_route_table" "public" {
vpc_id = "vpc-12345678"
count = "2"
# ... remaining arguments omitted
}
{% endcode-tabs-item %} {% endcode-tabs %} {% endhint %}
{% hint style="success" %} {% code-tabs %} {% code-tabs-item title="main.tf" %}
resource "aws_nat_gateway" "this" {
count = "1"
allocation_id = "..."
subnet_id = "..."
tags = {
Name = "..."
}
depends_on = ["aws_internet_gateway.this"]
lifecycle {
create_before_destroy = true
}
}
{% endcode-tabs-item %} {% endcode-tabs %} {% endhint %}
{% hint style="danger" %} {% code-tabs %} {% code-tabs-item title="main.tf" %}
resource "aws_nat_gateway" "this" {
count = "1"
tags = "..."
depends_on = ["aws_internet_gateway.this"]
lifecycle {
create_before_destroy = true
}
allocation_id = "..."
subnet_id = "..."
}
{% endcode-tabs-item %} {% endcode-tabs %} {% endhint %}
{% hint style="success" %}
- {% code-tabs %}
{% code-tabs-item title="main.tf" %}
{% endcode-tabs-item %} {% endcode-tabs %}
count = "${length(var.public_subnets) > 0 ? 1 : 0}"
- {% code-tabs %}
{% code-tabs-item title="main.tf" %}
{% endcode-tabs-item %} {% endcode-tabs %} {% endhint %}
count = "${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 isdefault = []
also. - Omit
type = "map"
declaration if there isdefault = {}
also. - Use plural form in name of variables of type
list
andmap
. - 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}
foraws_subnet
issubnet
, foraws_vpc
it isvpc
.{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:
{% hint style="success" %} {% code-tabs %} {% code-tabs-item title="outputs.tf" %}
output "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)}"
}
{% endcode-tabs-item %} {% endcode-tabs %} {% endhint %}
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
:
{% hint style="danger" %} {% code-tabs %} {% code-tabs-item title="outputs.tf" %}
output "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)}"
}
{% endcode-tabs-item %} {% endcode-tabs %} {% endhint %}
{% hint style="success" %} {% code-tabs %} {% code-tabs-item title="outputs.tf" %}
output "this_rds_cluster_instance_endpoints" {
description = "A list of all cluster instance endpoints"
value = ["${aws_rds_cluster_instance.this.*.endpoint}"]
}
{% endcode-tabs-item %} {% endcode-tabs %} {% endhint %}
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.
{% hint style="success" %} {% code-tabs %} {% code-tabs-item title="outputs.tf" %}
output "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)}"
}
{% endcode-tabs-item %} {% endcode-tabs %} {% endhint %}
****