Skip to content

Commit 13e9a39

Browse files
Gowiemgberenice
andauthored
feat: first pass at reworking to more holistic example (#5)
## what - Reworking the `client-tf-templates` repo into `example-tf` ## why - I want to have something more holistic that shows + describes how we do things. The way things are now is great, but I want to setup this project so that we can use it for more. This is a first attempt at doing so. cc @gberenice I want to collab on this, so we'll discuss soon 👍 ## references - N/A <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Documentation** - Revised repository overview and module guides for clearer usage instructions. - **New Features** - Introduced a new configuration for streamlined CLI tool version management. - **Chores** - Removed obsolete pre-commit settings. - Updated tool versions and added a new linting action to enhance overall quality. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Veronika Gnilitska <[email protected]>
1 parent 506e656 commit 13e9a39

File tree

15 files changed

+97
-29
lines changed

15 files changed

+97
-29
lines changed

.pre-commit-config.yaml

Lines changed: 0 additions & 7 deletions
This file was deleted.

.trunk/trunk.yaml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# To learn more about the format of this file, see https://docs.trunk.io/reference/trunk-yaml
33
version: 0.1
44
cli:
5-
version: 1.22.10
5+
version: 1.22.11
66
# Trunk provides extensibility via plugins. (https://docs.trunk.io/plugins)
77
plugins:
88
sources:
@@ -22,20 +22,21 @@ lint:
2222
enabled:
2323
2424
25-
25+
2626
- git-diff-check
2727
28-
28+
2929
30-
- trivy@0.59.1
31-
32-
- yamllint@1.35.1
30+
- trivy@0.60.0
31+
32+
- yamllint@1.36.2
3333
ignore:
3434
- linters: [tofu]
3535
paths:
3636
- "**/backend.tf.json"
3737
actions:
3838
enabled:
39+
- terraform-docs
3940
- trunk-announce
4041
- trunk-check-pre-push
4142
- trunk-fmt-pre-commit

README.md

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
1-
# client-tf-templates
1+
# example-tf
22

3-
This repository serves as a template for creating Terraform [child](https://opentofu.org/docs/language/modules/#child-modules) and [root](https://opentofu.org/docs/language/modules/#the-root-module) modules, providing a standardized structure and essential files for efficient module development. It's designed to ensure consistency and best practices across Terraform projects.
3+
This repository serves as an example and template for how Masterpoint thinks about organizing a vanilla Terraform or OpenTofu (from now on referred to as "TF") monorepo with root modules, child modules, and accompanying tooling.
44

5-
Child module example is provided in [terraform-random-pet](./terraform-random-pet/) directory.
5+
This includes example configurations and recommendations around the following topics:
66

7-
Root module example is provided in [root-module](./root-module/) directory.
7+
<!-- TODO: Link to what Multi-instance root modules are once https://github.com/masterpointio/masterpoint.io/pull/49 ships -->
88

9-
This README.md serves as the module's primary documentation and entry point.
9+
1. Example organizational structure for an IaC Monorepo (Multi-instance Root Modules + Child Modules)
10+
1. Root module example is provided in the [root-modules/template-root-module](./root-modules/template-root-module/) directory.
11+
2. Child module example is provided in the [child-modules/random-pet](./child-modules/random-pet/) directory
12+
2. [Recommendations for module file structure](#structure) with [file-by-file guidance](#file-by-file-guidance)
13+
3. [Recommendations for version pinning TF + Providers](#versioning-tf-and-providers)
14+
4. [Managing which TF binary is used per project](#managing-which-tf-binary-is-used-per-project)
15+
5. [Guidance on linting + CI for TF](#tf-linting--ci)
16+
6. [Frequently Asked Questions](#frequently-asked-questions)
1017

11-
## Recommenations
18+
<!-- TODO
19+
1. Example Native TF Tests with accompanying GitHub Action workflow for running tests
20+
-->
21+
22+
## Recommendations (TODO: Discuss)
1223

1324
We recommend to include:
1425

@@ -123,14 +134,16 @@ We’re particular about how we version providers and Terraform/OpenTofu in chil
123134
124135
### Child Modules
125136
126-
Since child-modules are intended to be used many times throughout your code, it’s important to make it so that they create as little restrictions on the consuming consuming root module as possible.
137+
<!-- TODO: Update to link Child Modules to Terms blog post once live -->
138+
139+
Since child-modules are intended to be used many times throughout your or others code, it’s important to make it so that they create as little restrictions on the consuming root module as possible.
127140
128141
This means you should:
129142
130143
- Identify the earliest Terraform/OpenTofu and provider versions your child module supports.
131144
- Use the `>=` operator to ensure that consumers run at least these versions.
132145
133-
By setting a lower bound (e.g., `>= 1.3`) rather than pinning exact versions, you allow root modules to choose their own Terraform and provider versions. This means a root module can upgrade Terraform or providers without requiring updates to all child modules.
146+
By setting a lower bound (e.g., `>= 1.3`) rather than pinning exact versions, you allow root modules to choose their own Terraform/OpenTofu and provider versions. This means a root module can upgrade their TF or providers versions without requiring updates to the child modules that they consume.
134147
135148
Example:
136149
@@ -147,15 +160,17 @@ terraform {
147160
}
148161
```
149162

150-
In this example, the child module only demands a minimum version (Terraform 1.3, Random provider 3.0), letting the root module run newer versions as they become available.
163+
In this example, the child module only demands a minimum version (Terraform or OpenTofu 1.3, Random provider 3.0), letting the root module run newer versions as they become available.
151164

152165
### Root Modules
153166

154-
Root modules are intended to be planned and applied and therefore they should be more prescriptive so that they’re called consistently in each case that you instantiate a new root module instance (i.e. a state file).
167+
<!-- TODO: Update to link Root Modules to Terms blog post once live -->
168+
169+
Root modules are intended to be planned and applied and therefore they should be more prescriptive so that they’re called consistently in each case that you instantiate a new root module instance (i.e. create a new state file).
155170

156171
To accomplish that, you should do the following:
157172

158-
- Explicitly pin the latest version of Terraform/OpenTofu that your root module supports. You’ll need to upgrade this version each time you want to use a new TF version across your code base.
173+
- Explicitly pin the latest version of TF that your root module supports. You’ll need to upgrade this version each time you want to use a new TF version across your code base.
159174
- Identify the highest stable provider versions your root module supports, then use the [pessimistic operator](https://developer.hashicorp.com/terraform/language/expressions/version-constraints#operators) `~>` to allow only patch-level updates. This gives you automatic bug fixes and minor improvements without risking major breaking changes.
160175

161176
Example:
@@ -173,9 +188,55 @@ terraform {
173188
}
174189
```
175190

176-
In this example Terraform is pinned exactly at 1.3.7, the AWS provider is pinned with `~> 5.81.0`, which means it can update to 5.81.1, 5.81.2, etc., but not jump to 5.82.0.
191+
In this example two things are happening:
192+
193+
1. TF is pinned exactly at `1.3.7`, which ensures your entire team will use the correct version with this root module.
194+
2. The AWS provider is pinned with `~> 5.81.0`, which means it can update to `5.81.1`, `5.81.2`, etc., but not jump to `5.82.0`.
195+
196+
If you're more willing to use the bleeding edge of providers, you can always use the `~>` operator on the minor version like so `version = "~> 5.81"`. This will enable any new minor version updates and is essentially a shorthand for `>= 5.81.0 && < 6.0`. Be aware that providers do break and this has the possibility to frustrating bugs from providers to affect your project.
177197

198+
## Managing which TF binary is used per project
199+
200+
At Masterpoint, we're big fans of [Aqua](https://aquasecurity.github.io/aqua/) for managing which TF binary is used per project. This allows us to have a single TF binary that is used across our entire project, but still enables us to use root module specific TF versions if needed.
201+
202+
Check out the [aqua.yaml](.aqua/aqua.yaml) file to see how simple it is to use aqua for this project and check out [the Aqua docs](https://aquasecurity.github.io/aqua/getting-started/installation/) on how you can use this tool for your own project.
203+
204+
<!--
205+
TODO: Work these into other sections.
178206
## Additional Tips
179207
180208
- Testing and Examples: Consider adding an examples/ directory with sample configurations and a test/ directory (if using tools like terratest or native Terraform testing) to ensure the module works as intended
181-
- Continuous Improvement: Update documentation and constraints (versions.tf) as Terraform and providers evolve, and as you refine the module’s functionality.
209+
- Continuous Improvement: Update documentation and constraints (versions.tf) as Terraform and providers evolve, and as you refine the module’s functionality. -->
210+
211+
## TF Linting + CI
212+
213+
There are many tools to format, lint, and ensure consistency of TF code. The tool that we recommend is [trunk Code Quality](https://docs.trunk.io/code-quality). This single tool allows us to do the following:
214+
215+
1. Format our TF code with `terraform fmt` or `tofu fmt` within our IDE and ensure this is run on each commit.
216+
1. [This is handled by the trunk `terraform` or `tofu` linter](https://docs.trunk.io/code-quality/linters/supported/tofu).
217+
2. Validate our TF code with `terraform validate` or `tofu validate` within our IDE and ensure this is run on each commit.
218+
1. [This is handled by the trunk `terraform` or `tofu` linter](https://docs.trunk.io/code-quality/linters/supported/tofu).
219+
3. Generate documentation for our TF code with `terraform-docs` and ensure it is kept up-to-date on each commit.
220+
1. [This is handled by the trunk `terraform-docs` action](https://github.com/trunk-io/plugins/tree/main/actions/terraform-docs), which [Masterpoint originally developed](https://github.com/trunk-io/plugins/pull/966).
221+
4. Run TFLint against our code to ensure it is written against the best practices.
222+
1. [This is handled by the trunk `tflint` linter](https://docs.trunk.io/code-quality/linters/supported/tflint).
223+
5. Run a TF security scan against our code to ensure we're not introducing any security vulnerabilities.
224+
1. [This is handled by the trunk `trivy` linter](https://docs.trunk.io/code-quality/linters/supported/trivy).
225+
6. Run these checks in a CI pipeline to ensure they're enforced on each PR.
226+
1. [This is handled by the trunk-action workflow](https://docs.trunk.io/code-quality/setup-and-installation/github-integration) in the [.github/workflows/lint.yaml](.github/workflows/lint.yaml) file.
227+
228+
As you can see, this is a LOT of checks that trunk is supporting for us and this consolidation on one tool to support this (and much more) is a huge win.
229+
230+
Check out our [.trunk/trunk.yaml](.trunk/trunk.yaml) file to see how we configure this and [check the trunk Code Quality getting started documentation](https://docs.trunk.io/code-quality) on how you can use this tool for your own project.
231+
232+
## Frequently Asked Questions
233+
234+
### Why do you prefer DRY (Don't Repeat Yourself) Root Modules vs WET (Write Every Time) Root Modules?
235+
236+
We advocate IaC should be treated like code and traditional software. You encode some level of business logic into it, and consistently copying+pasting that logic as part of your day-to-day processes creates a maintenance burden that we believe should be avoided. This particularly shows up when IaC is managed at scale and we have seen these types of setups lead to a lot of toil and a lot of technical debt.
237+
238+
We will write up more on this soon and link to it here.
239+
240+
### Why don't you use a TF Framework like [Terragrunt](https://terragrunt.gruntwork.io/), [Terramate](https://terramate.io/), or [Atmos](https://atmos.tools/)?
241+
242+
We're big fans of the frameworks (particularly Atmos + Terramate, which we have a good deal of experience with), and we believe they're fantastic options for sophisticated teams that are starting from scratch. But for projects that aren't starting from scratch or have a desire to keep things simple, we believe Vanilla TF combined with a strong automation platform is a great option.

aqua.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
# aqua - Declarative CLI Version Manager
3+
# https://aquaproj.github.io/
4+
# checksum:
5+
# enabled: true
6+
# require_checksum: true
7+
# supported_envs:
8+
# - all
9+
registries:
10+
- type: standard
11+
ref: v4.331.0 # renovate: depName=aquaproj/aqua-registry
12+
packages:
13+
- name: opentofu/[email protected]

terraform-random-pet/README.md renamed to child-modules/random-pet/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# terraform-random-pet
22

3-
This is a template child module.
3+
This is a template child module to create a random pet resource. It can be easily copied and updated for other use-cases.
44

55
<!-- README TEMPLATE: AFTER READING THE BELOW SECTION, DELETE THE BELOW SECTION AND REPLACE WITH YOUR OWN CONTENT -->
66

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

root-module/README.md renamed to root-modules/template-root-module/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# root-module
1+
# template-root-module
22

3-
This is a template root module.
3+
This is a template root module that creates a random pet resource. It can be easily copied and updated for other use-cases.
44

55
<!-- README TEMPLATE: AFTER READING THE BELOW SECTION, DELETE THE BELOW SECTION AND REPLACE WITH YOUR OWN CONTENT -->
66

0 commit comments

Comments
 (0)