Azure Verified Modules
Glossary GitHub GitHub Issues Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

SNFR7 - Idempotency Tests

ID: SNFR7 - Category: Testing - Idempotency Tests

Modules MUST implement idempotency end-to-end (deployment) testing. E.g. deploying the module twice over the top of itself.

Modules SHOULD pass the idempotency test, as we are aware that there are some exceptions where they may fail as a false-positive or legitimate cases where a resource cannot be idempotent.

Read full article gdoc_arrow_right_alt

TFFR1 - Cross-Referencing Modules

ID: TFFR1 - Category: Composition - Cross-Referencing Modules

Module owners MAY cross-references other modules to build either Resource or Pattern modules. However, they MUST be referenced only by a HashiCorp Terraform registry reference to a pinned version e.g.,

module "other-module" {
  source  = "Azure/xxx/azurerm"
  version = "1.2.3"
}

They MUST NOT use git reference to a module.

Read full article gdoc_arrow_right_alt

TFFR2 - Additional Terraform Outputs

ID: TFFR2 - Category: Outputs - Additional Terraform Outputs

Authors SHOULD NOT output entire resource objects as these may contain sensitive outputs and the schema can change with API or provider versions. Instead, authors SHOULD output the computed attributes of the resource as discreet outputs. This kind of pattern protects against provider schema changes and is known as an anti-corruption layer .

Read full article gdoc_arrow_right_alt

TFNFR1 - Descriptions

ID: TFNFR1 - Category: Documentation - Descriptions

Where descriptions for variables and outputs spans multiple lines. The description MAY provide variable input examples for each variable using the HEREDOC format and embedded markdown.

Example:

variable "my_complex_input" {
  type = map(object({
    param1 = string
    param2 = optional(number, null)
  }))
  description = <<DESCRIPTION
A complex input variable that is a map of objects.
Each object has two attributes:

- `param1`: A required string parameter.
- `param2`: (Optional) An optional number parameter.

Example Input:

```terraform
my_complex_input = {
  "object1" = {
    param1 = "value1"
    param2 = 2
  }
  "object2" = {
    param1 = "value2"
  }
}
```
DESCRIPTION
}

TFNFR11 - Null Comparison Toggle

ID: TFNFR11 - Category: Code Style - Null Comparison Toggle

Sometimes we need to ensure that the resources created are compliant to some rules at a minimum extent, for example a subnet has to be connected to at least one network_security_group. The user SHOULD pass in a security_group_id and ask us to make a connection to an existing security_group, or want us to create a new security group.

Read full article gdoc_arrow_right_alt

TFNFR12 - Dynamic for Optional Nested Objects

ID: TFNFR12 - Category: Code Style - Dynamic for Optional Nested Objects

An example from the community:

resource "azurerm_kubernetes_cluster" "main" {
  ...
  dynamic "identity" {
    for_each = var.client_id == "" || var.client_secret == "" ? [1] : []

    content {
      type                      = var.identity_type
      user_assigned_identity_id = var.user_assigned_identity_id
    }
  }
  ...
}

Please refer to the coding style in the example. Nested blocks under conditions, MUST be declared as:

Read full article gdoc_arrow_right_alt

TFNFR13 - Default Values with coalesce/try

ID: TFNFR13 - Category: Code Style - Default Values with coalesce/try

The following example shows how "${var.subnet_name}-nsg" SHOULD be used when var.new_network_security_group_name is null or ""

Good examples:

coalesce(var.new_network_security_group_name, "${var.subnet_name}-nsg")
try(coalesce(var.new_network_security_group.name, "${var.subnet_name}-nsg"), "${var.subnet_name}-nsg")

Bad examples:

var.new_network_security_group_name == null ? "${var.subnet_name}-nsg" : var.new_network_security_group_name)

TFNFR14 - Not allowed variables

ID: TFNFR14 - Category: Inputs - Not allowed variables

Since Terraform 0.13, count, for_each and depends_on are introduced for modules, module development is significantly simplified. Module’s owners MUST NOT add variables like enabled or module_depends_on to control the entire module’s operation. Boolean feature toggles are acceptable however.

Read full article gdoc_arrow_right_alt

TFNFR15 - Variable Definition Order

ID: TFNFR15 - Category: Code Style - Variable Definition Order

Input variables SHOULD follow this order:

  1. All required fields, in alphabetical order
  2. All optional fields, in alphabetical order

A variable without default value is a required field, otherwise it’s an optional one.

Read full article gdoc_arrow_right_alt