Skip to content

Commit

Permalink
fix(overall)documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin Sanvoisin committed Feb 3, 2023
1 parent 5cfbfe4 commit 18acd14
Show file tree
Hide file tree
Showing 13 changed files with 97 additions and 96 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.vscode
72 changes: 36 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ Guidelines to work with Terraform and Terragrunt

- [IAC Guidelines](#iac-guidelines)
- [🎯 Our purpose](#-our-purpose)
- [1. Layer/code organisation](#1-layercode-organisation)
- [2. Communication between your layers](#2-communication-between-your-layers)
- [3. Use of modules](#3-use-of-modules)
- [4. Naming convention](#4-naming-convention)
- [The 3 standards for a layer/code](#the-3-standards-for-a-layercode)
- [The standard for communicating between your layers](#the-standard-for-communicating-between-your-layers)
- [The standard use of modules](#the-standard-use-of-modules)
- [The standard naming convention](#the-standard-naming-convention)
- [🚀 Guidelines](#-guidelines)
- [🛗 Patterns](#-patterns)
- [🎓 Standards](#-standards)
Expand All @@ -20,62 +20,62 @@ Guidelines to work with Terraform and Terragrunt

This documentation is provided by the Padok IaC Guild. Its purpose is to present guidelines and best practices about terraform development.

You do not have to see these guidelines as an absolute truth but more as a proposition to answer frequently asked questions and avoid issues you will often face in your projects.
You do not have to see these guidelines as an absolute truth, but more as a proposition to answer frequently asked questions and avoid issues you will often face in your projects.

Our goal is to guide you in this non-exhausting serie of topics:
Here are the key learning :

### 1. Layer/code organisation
### The 3 standards for a layer/code

- Your layer corresponds to a unique terraform state
- Your code design reflects your business need
- Only one team contributes on a layer (you have a clear vision of contribution & ownership)
- Your layer design reflects a business need
- Only one team contributes has ownership of a layer (you have a clear vision of contribution & ownership)
- Your state refresh time is acceptable for a contribution purpose

### 2. Communication between your layers
### The standard for communicating between your layers

- Your can rebuild your infrastructure without the `-target` flag
- You can rebuild your infrastructure without the `-target` flag
- You do not have any cyclical dependencies between resources
- You use data blocks only in layers

### 3. Use of modules
### The standard use of modules

- Your module's dependencies are provided by the caller
- Your module abtracts code complexity
- Your module integrates custom logic / guidelines
- Your module is not a resource flat pass
- Your module is used in different layers
- A module should be created
- To abstract complexity
- If you have to reuse it frequently (More than twice)
- You should not create a module to be a flat pass between resources
- Your module’s dependencies are provided by the caller
- You use remote modules to avoid repetition between your different projects

### 4. Naming convention
### The standard naming convention

- You adapt your codebase to your client needs and standards
- You avoid stuttering
- You use snake_case convention
- The name of the file or folder should reflect what you are creating
- Adapt your codebase to your client needs and standards
- Avoid stuttering when naming Terraform resources.
- Use snake_case convention

We recommend everyone to follow the [WYSIWYG pattern](wysiwg_patterns.md) for terraform vanilla.
We recommend everyone to follow the [WYSIWYG pattern](terraform/wysiwg_patterns.md) for vanilla terraform.

## 🚀 Guidelines

You'll find bellow standards to follow when working with Terraform and Terragrunt.
Youll find below details of the standards to follow when working with Terraform and Terragrunt.

### 🛗 Patterns

> Reusable solution to a commonly occurring problem within a given context
- [WYSIWYG pattern](wysiwg_patterns.md)
- [WYSIWYG pattern](terraform/wysiwg_patterns.md)
- [Context pattern aka the terragrunt implementation](terragrunt/context_pattern.md)

### 🎓 Standards

> Standards help avoiding wast and ensure that we deliver value
> Standards help to avoid waste and ensure that we deliver value
#### Terraform

- [Distant values references](refering_to_resources_from_other_layers.md)
- [Versioning](terraform_versioning.md)
- [Naming](terraform_naming.md)
- [Pre-commits](pre-commits.md)
- [Iterate on your resources](iterate_on_your_resources.md)
- [Distant values references](terraform/refering_to_resources_from_other_layers.md)
- [Versioning](terraform/terraform_versioning.md)
- [Naming](terraform/terraform_naming.md)
- [Pre-commits](terraform/pre-commits.md)
- [Iterate on your resources](terraform/iterate_on_your_resources.md)

#### Terragrunt

Expand All @@ -85,12 +85,12 @@ You'll find bellow standards to follow when working with Terraform and Terragrun

### 🚩 Red flags

> Red flag is something that you must pay attention about. This is an advice or recommendation not a requirement.
> Red flag is something that you must pay attention about. This is an advice or recommendation, not a requirement.
- [Don'ts](donts.md)
- [Optional attributes (experimental feature)](optional-attributes.md)
- [Child modules depth limit](child_modules_depth_limit.md)
- [Dont’s](terraform/donts.md)
- [Optional attributes (experimental feature)](terraform/optional-attributes.md)
- [Child modules depth limit](terraform/child_modules_depth_limit.md)

### 🛠️ Tooling

- [Pre-commits](pre-commits.md)
- [Pre-commits](terraform/pre-commits.md)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion pre-commits.md → terraform/pre-commits.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ In order to use pre-commit with all recommanded features, you will need to insta
pre-commit install
```

3. Copy the [`.pre-commit-config.yaml` file](./assets/.pre-commit-config.yaml) at the root of your repository
3. Copy the [`.pre-commit-config.yaml` file](../assets/.pre-commit-config.yaml) at the root of your repository

## Usage

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Some infrastructure projects may be split in different layers or repositories.

There are different ways to use resources from other layers in your project.

This standard applies to `terraform` infrastructure. To go further, feel free to read our [terragrunt standard](./terragrunt/refering_to_resources_from_other_layers.md) about layers.
This standard applies to `terraform` infrastructure. To go further, feel free to read our [terragrunt standard](../terragrunt/refering_to_resources_from_other_layers.md) about layers.

## TL;DR

Expand Down Expand Up @@ -92,11 +92,11 @@ resource "azurerm_virtual_network" "example" {

The last way yo refer a resource from a different layer is to hard get the string value you want, and pray for it to be valid.

In a small infrastructure it may seem a good idea but it's not since:
In a small infrastructure it may seem a good idea, but its not since:

1. if you refactor, you will need to change every occurences of hard-coded strings
2. you will fail at apply and not at plan
3. if provider API changes your code will fail
1. if you refactor, you will need to alter every occurrences of hard-coded strings
2. you will fail to apply and not at plan
3. if provider API changes, your code will fail

Do not do that.

Expand Down Expand Up @@ -146,6 +146,6 @@ In that way, you will know where to search your existing data simply by its purp

Using data in terraform module is not recomanded because it can create circular dependencies between layers and force you to do target apply.

![Data Circular dependency](./assets/img/data_circular_dependency.png)
![Data Circular dependency](../assets/img/data_circular_dependency.png)

Prefer to set variables in your module, then call your data where your module is applied.
File renamed without changes.
14 changes: 7 additions & 7 deletions terraform_versioning.md → terraform/terraform_versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ It does not discuss the terraform module version management.

### Terraform < 1.0

At the root of a layer (ie, the directory where "terraform apply" is run),
At the root of a layer (ie, the directory where terraform apply is run),
best practice is to specify an exact version of Terraform to use. This is due
to terraform state incompatibility between 0.X versions. Use the
`= 0.2.3` constraint to do this.
Expand Down Expand Up @@ -41,7 +41,7 @@ terraform {
### Required providers version for layers

If the layer uses providers directly, as opposed to only through modules, then
you should also specify version contraints for those providers in the layer's
you should also specify version contraints for those providers in the layers
configuration.

In order to make the behaviour of layers completely deterministic, the version
Expand All @@ -61,17 +61,17 @@ therefore there are none in modules.

First of all, you have to review the [Terraform Changelog](https://github.com/hashicorp/terraform/blob/main/CHANGELOG.md) to identify changes that may affect the behavior of your code. As a recent example, the `optional` function was experimental, and passed standard in 1.3. It causes codes to be remanied to remove the declaration of an experimental feature, in the layer and used submodules.

You will have to change the version of your layer during this, that have to be done in your layer only ([modules shouldn't have fixed versions](https://github.com/padok-team/docs-terraform-guidelines/blob/main/terraform_versioning.md#module-layer-versioning)). Change also your Terraform CLI version, you can use tools such as `tfswitch`.
You will have to change the version of your layer during this, that have to be done in your layer only ([modules shouldnt have fixed versions](#module-layer-versioning)). Change also your Terraform CLI version, you can use tools such as `tfswitch`.

Perform a plan is okay, but don't apply during the phase of adaptation. You don't want to create any drift by upgrading your Terraform version. As the version is stored in the state file, under `terraform_version`, experimenting an upgrade and applying may lead to undesired conflicts of versions due to the state. Note: this field is automaticly updated when applying with a new Terraform version, even if Terraform output just displays that the infrastructure matches the configuration.
Perform a plan is okay, but dont apply during the phase of adaptation. You dont want to create any drift by upgrading your Terraform version. As the version is stored in the state file, under `terraform_version`, experimenting an upgrade and applying may lead to undesired conflicts of versions due to the state. Note: this field is automaticly updated when applying with a new Terraform version, even if Terraform output just displays that the infrastructure matches the configuration.

Finally, if your Terraform plan doesn't see any differences with the actual code, you can commit your code, then applying when merged on the principal branch. This way is impactless for your coworkers or a CI, because the first who will apply the latest code will perform the migration in the state.
Finally, if your Terraform plan doesnt see any differences with the actual code, you can commit your code, then applying when merged on the principal branch. This way is impactless for your coworkers or a CI, because the first who will apply the latest code will perform the migration in the state.

## Module layer versioning

### Terraform CLI version

In a module, you can allow more flexibility with regards to Terraform's
In a module, you can allow more flexibility with regards to Terraforms
minor and/or patch versions. For example, the `~> 1.0` constraint will allow
all 1.x.x versions of Terraform, while the `~> 1.0.0` constraint will allow
all 1.0.x versions.
Expand All @@ -89,7 +89,7 @@ terraform {
### Required providers version for modules

You can indicate that the module requires that certain providers are configured by the caller.
Again; use the "~> 1.0" constraint to allow all minor and/or patch versions.
Again; use the ~> 1.0 constraint to allow all minor and/or patch versions.

> For more information: <https://www.terraform.io/docs/language/providers/requirements.html>
Expand Down
24 changes: 12 additions & 12 deletions wysiwg_patterns.md → terraform/wysiwg_patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@

> Keep it simple stupid.
**Don’t put too much thought on the friendly name of files, the point is that a new comer can easily find code to understand the infrastructure and make modification.**
**Don’t put too much thought on the friendly name of files, the point is that a newcomer can easily find code to understand the infrastructure and make modification.**

### Layers, folders and projects

Expand All @@ -82,7 +82,7 @@ A project can host multiple folder to regroup different type of project need.

- This folder contains layer that answer project needs (Ex: having a production, pre-production and tooling environment)
- Each file in a layer is named with a friendly name (Ex: production, cluster, database, roles)
- Can be seperate with sub folder to have sub layers, thus a state per sub layer and not layer. (Ex: If you state is too big with too many resource you can divide it in different sub layer)
- Can be separate with sub folder to have sub layers, thus a state per sub layer and not layer. (Ex: If you state is too big with too many resources you can divide it in different sub layer)
- Only one file for the configuration of terraform for the layer named `_settings.tf`
- Defines required_version of terraform
- Terraform provider used but not it’s version
Expand All @@ -106,7 +106,7 @@ Modules are created for two reasons:

- If you need to create a resource multiple times (Ex: network, databases) ✅
- If you want to hide complexity to create a resource (Ex: EKS cluster) ✅
- They are **not** created to pass-through another module (Ex for public module) ❌
- They are **not** created to pass through another module (Ex for public module) ❌

Each file in a module is named with a friendly name (Ex: node_pool, roles, monitoring)

Expand All @@ -127,19 +127,19 @@ This versioning can be done on several layers:
- Version the whole repo with the local modules
- Pro :
- Simple usage and quick implementation of new feature
- Best suited for a one or two man team, synchronous collaboration
- Best suited for a one or two-man team, synchronous collaboration
- Cons
- Not suited for teams of more than two persons and asynchronous collaboration
- Need to copy module in a new folder `v2` and change source of module to test a breaking change
- The repo and the module are in remote repository
- Pro :
- Best suited for medium and large teams and asynchronous collaboration
- Fine grain control on versioning
- Con : Lead time to add a feature is long (Mulitple pull request to open)
- Con : Lead time to add a feature is long (Multiple pull request to open)

## Files and folder naming

> Keep it simple stupid.
> Keep it simple, stupid.
### Folders

Expand All @@ -153,7 +153,7 @@ This versioning can be done on several layers:
- Required_version of terraform
- Backend configuration
- Terraform provider used, but not it’s version.
- Terraform ouput of my layer ou module is named `output.tf` is the interface of my layer with the rest of the world
- Terraform output of my layer or module is named `output.tf` is the interface of my layer with the rest of the world
- Terraform file that create resources are named with a `reader_friendly_name.tf` after what they define
- Do not use main.tf if possible

Expand All @@ -169,13 +169,13 @@ Pros:

Cons

- Your layers are not always ISO between project need, because you can add .tf files to specify a ponctual need within a layer.
- With terraform you will have a bit of code duplication between layers, because they will each call the same module. These means you will have to write multiple times the same input for every instanciation of the module (Ex: Tenant id)
- To solve this issue I invite you to read the [Contexte pattern](contexte_pattern.md)
- Your layers are not always ISO between project need, because you can add .tf files to specify a punctual need within a layer.
- With terraform you will have a bit of code duplication between layers, because they will each call the same module. These means you will have to write multiple times the same input for every instantiation of the module (Ex: Tenant id)
- To solve this issue I invite you to read the [Context pattern](../terragrunt/context_pattern.md)

## Examples

### Example 1 : Project with a seperation per environment, module are in local repository with no versioning
### Example 1 : Project with a separation per environment, module are in local repository with no versioning

Main repository

Expand Down Expand Up @@ -207,7 +207,7 @@ Main repository
└── database
```

### Example 2 : Project with a seperation per application, module are in remote repository with versioning
### Example 2 : Project with a separation per application, module are in remote repository with versioning

Main repository

Expand Down
Loading

0 comments on commit 18acd14

Please sign in to comment.