In order to provide consistency of quality and minimize disruption to projects making use of these modules, developers are asked to adhere to the following guidelines and standards for Terraform modules.
Repo Naming Guidelines
All repos must use the naming pattern of <PROVIDER>-<NAME>
, where <PROVIDER>
reflects
the main provider for the infrastructure and <NAME>
names the module (with additional
hyphens). Examples include aws-ssh-bastion
or aws-gitlab-runner
.
Documentation
Every module should be well documented. Each module should include, at a minimum, documentation that describes:
- Purpose & Description - include an architectural diagram, preferably using official AWS architecture icons.
- Any preconditions or assumptions
- Inputs for the module. Each input should include a description, type, default value (if applicable), and required flag (as yes/no)
- Outputs provided by the module
- Module versions (see below) and major changes included in those versions
sample-readme.md provides a starter README.md file.
Code Organization
Every module should contain the following:
-
versions.tf
- declaration of minimum Terraform and provider versions for the module -
main.tf
- the main resource file. Any submodules used should be declared here. If many resources are being managed, this file may be split into smaller resource-type-based files (dns.tf
,lb.tf
,networking.tf
, etc.) -
variables.tf
- declaration of all variables (inputs), both required and non-required -
outputs.tf
- the outputs for the module -
.gitignore
- files to ignore. See gitignore for a good starting point
Variables
Organize variables.tf
with required variables at the top, followed by optional and local variables. Each section should have the variables in alphabetical order.
###
# Required
###
variable "responsible_party" {
description = "Person (pid) who is primarily responsible for the configuration and maintenance of this resource"
}
variable "subnet_ids" {
description = "The subnet ids to use for the auto scaling group"
}
...
###
# Optional
###
variable "compliance_risk" {
description = "Should be `none`, `ferpa` or `pii`"
default = "none"
}
variable "data_risk" {
description = "Should be `low`, `medium` or `high` based on data-risk classifications defined in VT IT Policies"
default = "low"
}
...
###
# Locals
###
locals = {
...
}
If your module depends upon pre-existing resources (such as VPC, Subnets, etc.), use variables to accept the id of the resource rather than the name or some other ambiguous descriptor. For resources that are uniquely identified by an arn, it is acceptable to use that instead of an id.
Versioning
Every major change should result in a new version number. Breaking changes are always major changes. To create a new version number, do the following:
- Update your README.md to document the new version number and indicate what changed
- After your change has been merged to master, tag it with the version number.
Do not reuse version numbers.
Tagging of Resources
Proper tagging of cloud resources helps to reduce maintenance efforts as well as providing enhanced reporting capabilities from our AWS provider, DLT.
This AWS Tagging Strategis document is also helpful.
Note that in order to use cost allocation with DLT, some of the tag names are dictated to us here.
Guidelines
- Tag names
- should normally be CamelCase
- should consist of characters a-z, 0-9 and ‘-’ (dash)
- Tag values should often be lowercase, though there may be cases when mixed case makes sense
- Where a required tag doesn’t have a value or doesn’t apply, use the value ‘none’
- As much as possible all tags should be automatically populated by whatever provisioning mechanism is being used.
Expected Tags
Every resource created by your modules should be tagged with the following:
Tag | Description | Default |
---|---|---|
Name | the name of the resource | Based on the resource, but you may to allow users of your module to pass in a name prefix (or perhaps use the passed service name as a prefix). |
Service | the high level service this resource is primarily supporting | Allow the user to pass this as an input to your module |
Environment | e.g. 'development’, ‘test’, or ‘production’ | 'production', but allow the user to pass this as an input to your module |
ResponsibleParty | person (pid) who is primarily responsible for the configuration and maintenance of this resource | Allow the user to pass this as an input to your module |
ResponsibleParty2 | backup person for config and maint of this resource (previously secondary-admin) | 'none', but allow users to pass this as an input |
DataRisk | should be ‘low’, ‘medium’ or ‘high’ based on data-risk classifications defined here | 'low', but allow users to pass this as an input |
ComplianceRisk | should be 'none', ‘ferpa’ or ‘pii’ | 'none', but allow users to pass this as an input |
Documentation | link to documentation and/or history file | 'none', bult allow users to pass this as an input |
Version | the version of the resource, if applicable | the version of this module (you provide) |
Comments | any additional comments that are not covered by other tags | You decide |
VCS | A link to the repo in a version control system (usually Git) that manages this resource. | Allow the user to pass this as an input to your module |
- Additional required tags may be added as business requirements arise, but aren't generally necessary in modules.
Submitting merge requests
See TODO for the VT DevCom process for submitting merge requests.