Show Menu
Cheatography

QK Terraform Module Cheat Sheet (DRAFT) by

The official QK Terraform module cheat sheet.

This is a draft cheat sheet. It is a work in progress and is not finished yet.

Main Reasons to Create a Module

Enforce standards, settings, and conven­tions when deploying resources.
Offer a larger building block to facilitate resource deploy­ment.
Implement logic to simplify users' life and improve Terraform adoption.

Naming Convention

BitBucket Project Key
We recommend you use a key that starts with
TF
and add an acronym to identify the main provid­er/­pla­tform (e.g.
TFAZ
= Azure,
TFGC
= GCP,
TFVR
= vRealize Automa­tion,
TFVS
= vSphere, ...).
Repository
All reposi­tor­ies­/mo­dules MUST be named using the
terraf­orm­-<p­rov­ide­r>-­<na­me>
convention (e.g.
terraf­orm­-vs­phe­re-­win­dows-vm
,
terraf­orm­-az­ure­rm-­key­vault
, ...).

Repository Structure

/
-
Root of the module
/examples
Required
Examples of how to use the module
/images
Optional
If your docume­ntation includes images, put them in this folder
/tests
Optional
If you have Terratest files put there in this folder

Base Module Files

.gitignore
Required
Git ignore (see also
Security
section)
.terra­for­m-d­ocs.yml
Required
terraf­orm­-docs
config­uration
.tfsec­/co­nfi­g.yml
Optional
If
tfsec
is enabled for the reposi­tory, it should have a config­uration file here
locals.tf
Optional
If you use Terraform locals, you should put them in this file
main.tf
Required
Main module code
outputs.tf
Required
Defini­tions of module outputs should be put in this file
provid­er.tf
Required
README.md
Required
Main module docume­ntation (see also QK's README.md Cheat Sheet)
variab­les.tf
Required
Module variables
If you prefer to organize your code in different
.tf
files, you can do so, but often a single
main.tf
is enough.
 

Coding Conven­tions & Style

Always add comments when useful. This is partic­ularly important to explain reasons behind a specific design, choice of resources or values, edge cases, known bugs, issues or limita­tions in the code, etc. Do not add comments just for the sake of it (e.g.
# Create resource foobar
), add comments when the code is not enough.
Use unders­cores (
_
) not dashes when naming resources (e.g.
vm_ima­ge_name
not
vm-ima­ge-name
).
When naming variables, check existing modules and re-use existing names and patterns. For example, if module X uses
google­_zone
and you also need to specify the zone, use the same name, not
gcp_zone
. Same for patterns, if the most common one is
google_*
use that pattern, not
gcp_*
.
Be consistent when naming resources and variables (e.g. don't name something
google_foo
only to name the next thing
gcp_bar
).
Remember that once your module is published, renaming resources and variables will become a breaking change and may impact existing projects negati­vely, so try to do it right the first time or chances are we'll need to live with it.
Validate all user inputs (varia­bles) when possible. Follow the "fail early" mantra, do not let user create 13 resources only to fail on the 14th when you can prevent it.
When validating variable inputs, use multiple
validation
blocks when doing different checks. This allows you to provide more meaningful error messages.
When it makes sense, provide useful defaults for variables.
Start the descri­ption of optional variables by "­**O­PTI­ONAL:** " followed by the descri­ption.
Do not use explicit depend­encies (
depends_on
) unless necessary and you understand the impacts. Always use implicit depend­encies instead.

Version Constr­aints

Your
provid­er.tf
file MUST include version constr­aints.
Version constr­aints of each provider should usually be locked to the major version of the provider (e.g.
version = "­>= 2.0, < 3.0"
) unless fully tested with multiple major versio­ns".
If your code requires a specific minor of fix version, use the correct constraint and document why (e.g.
Version 1.2.0 or newer is required to prevent issue when updating resources of type XYZ
`).

Semantic Versioning

Terraform modules MUST follow Semantic Versioning
Always pay attention to the changes you make to a module! Terraform can be very finicky and what may look like a simple change may trigger a destroy operation in existing project code.
Follow Semantic Versioning rules, do not fall for the "­small change­s" should not change the major version number mentality. For example, if you fix a typo in a variable name, any existing code using this variable will break, as such, small change = breaking change = new major version.
 

Project Upgrade Paths

When introd­ucing breaking changes, always think about the best implem­ent­ation for an upgrade path. We recommend you also create a
upgrad­e-v­X-t­o-vY.md
(for example:
update­-v2­-to­-v3.md
) file with instru­ctions on how to upgrade existing projects to the new major module version from the last major version. This is partic­ularly important if the breaking change may introduce data loss (trigger a Terraform destroy operat­ion).

Docume­ntation

Your module MUST include proper docume­nta­tion. See QK's README.md Cheat Sheet for details.
Docume­ntation MUST be part of the repository and MUST be written in Markdown. Feel free to split docume­ntation into multiple files if needed, but always make the
README.md
file the main point of entry.
We also recommend you review some of QK's GCP VM modules (e.g. Windows VM for some sample README files.

terraf­orm­-docs

Always ensure you have proper
.terra­for­m-d­ocs.yml
in your repository and run
terraf­orm­-docs .
after making changes to your module to update docume­ntation
Look into one of QK's latest Terraform module for a recent copy of the
.terra­for­m-d­ocs.yml
file.

Security

When one or more providers in your module are supported by the
tfsec
tool, you should create a base
.tfsec­/co­nfi­g.yml
and run the tool against your module to validate it. If any issues are found, fix them or if not possible, add the proper exceptions to the
config.yml
file and document them.
Always exclude
.tfvars
, state files, and any secrets using
.gitignore
before you commit code.

Releases

Always tag official releases with a proper
vX.Y.Z
semantic version tag.
Always ensure your README and any other docume­ntation is up-to-date before publishing a new release.
Always provide 2-3 up-to-date working examples with your modules. Exception of any authen­tic­ation and access, these should work out-of­-th­e-box for any user that wants to deploy them.

Tips

If your module relies on other modules, always lock their version using either version constr­aints (if using registry) or
git
URL
ref
(e.g.
?ref=v­1.2.3
).
When creating examples for your module, provide at least one
minimal
and one
complete
example.
Include all necessary files in your examples so they can be used as a starting point for a new project. For example, include a
.gitignore
even if not needed for the example to be functi­onal.