Skip to content
Development
Skill

/azure-verified-modules

Azure Verified Modules (AVM) requirements and best practices for developing certified Azure Terraform modules. Use when creating or reviewing Azure modules that need AVM certification.

From plugin
hashicorp-agent-skills
79017 skills
Install
$ npx -y skills add hashicorp/agent-skills --skill azure-verified-modules --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/azure-verified-modules

Context preview

The summary Claude sees to decide when to auto-load this skill.

Azure Verified Modules (AVM) requirements and best practices for developing certified Azure Terraform modules. Use when creating or reviewing Azure modules that need AVM certification.

SKILL.md

azure-verified-modules.SKILL.md
name: azure-verified-modules
description: Azure Verified Modules (AVM) requirements and best practices for developing certified Azure Terraform modules. Use when creating or reviewing Azure modules that need AVM certification.

Azure Verified Modules (AVM) Requirements

This guide covers the mandatory requirements for Azure Verified Modules certification. These requirements ensure consistency, quality, and maintainability across Azure Terraform modules.

**References:**

  • [Azure Verified Modules](https://azure.github.io/Azure-Verified-Modules/)
  • [AVM Terraform Requirements](https://azure.github.io/Azure-Verified-Modules/specs/terraform/)

Table of Contents

  • [Module Cross-Referencing](#module-cross-referencing)
  • [Azure Provider Requirements](#azure-provider-requirements)
  • [Code Style Standards](#code-style-standards)
  • [Variable Requirements](#variable-requirements)
  • [Output Requirements](#output-requirements)
  • [Local Values Standards](#local-values-standards)
  • [Terraform Configuration Requirements](#terraform-configuration-requirements)
  • [Testing Requirements](#testing-requirements)
  • [Documentation Requirements](#documentation-requirements)
  • [Breaking Changes & Feature Management](#breaking-changes--feature-management)
  • [Contribution Standards](#contribution-standards)
  • [Compliance Checklist](#compliance-checklist)

---

Module Cross-Referencing

**Severity:** MUST | **Requirement:** TFFR1

When building Resource or Pattern modules, module owners **MAY** cross-reference other modules. However:

  • Modules **MUST** be referenced using HashiCorp Terraform registry reference to a pinned version
  • Example: `source = "Azure/xxx/azurerm"` with `version = "1.2.3"`
  • Modules **MUST NOT** use git references (e.g., `git::https://xxx.yyy/xxx.git` or `github.com/xxx/yyy`)
  • Modules **MUST NOT** contain references to non-AVM modules

---

Azure Provider Requirements

**Severity:** MUST | **Requirement:** TFFR3

Authors **MUST** only use the following Azure providers:

| Provider | Min Version | Max Version | |----------|-------------|-------------| | azapi | >= 2.0 | < 3.0 | | azurerm | >= 4.0 | < 5.0 |

**Requirements:**

  • Authors **MAY** select either Azurerm, Azapi, or both providers
  • **MUST** use `required_providers` block to enforce provider versions
  • **SHOULD** use pessimistic version constraint operator (`~>`)

**Example:**

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.0"
    }
    azapi = {
      source  = "Azure/azapi"
      version = "~> 2.0"
    }
  }
}

---

Code Style Standards

Lower snake_casing

**Severity:** MUST | **Requirement:** TFNFR4

**MUST** use lower snake_casing for:

  • Locals
  • Variables
  • Outputs
  • Resources (symbolic names)
  • Modules (symbolic names)

Example: `snake_casing_example`

Resource & Data Source Ordering

**Severity:** SHOULD | **Requirement:** TFNFR6

  • Resources that are depended on **SHOULD** come first
  • Resources with dependencies **SHOULD** be defined close to each other

Count & for_each Usage

**Severity:** MUST | **Requirement:** TFNFR7

  • Use `count` for conditional resource creation
  • **MUST** use `map(xxx)` or `set(xxx)` as resource's `for_each` collection
  • The map's key or set's element **MUST** be static literals

**Example:**

resource "azurerm_subnet" "pair" {
  for_each             = var.subnet_map  # map(string)
  name                 = "${each.value}-pair"
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.example.name
  address_prefixes     = ["10.0.1.0/24"]
}

Resource & Data Block Internal Ordering

**Severity:** SHOULD | **Requirement:** TFNFR8

**Order within resource/data blocks:**

1. **Meta-arguments (top)**:

  • `provider`
  • `count`
  • `for_each`

2. **Arguments/blocks (middle, alphabetical)**:

  • Required arguments
  • Optional arguments
  • Required nested blocks
  • Optional nested blocks

3. **Meta-arguments (bottom)**:

  • `depends_on`
  • `lifecycle` (with sub-order: `create_before_destroy`, `ignore_changes`, `prevent_destroy`)

Separate sections with blank lines.

Module Block Ordering

**Severity:** SHOULD | **Requirement:** TFNFR9

**Order within module blocks:**

1. **Top meta-arguments**:

  • `source`
  • `version`
  • `count`
  • `for_each`

2. **Arguments (alphabetical)**:

  • Required arguments
  • Optional arguments

3. **Bottom meta-arguments**:

  • `depends_on`
  • `providers`

Lifecycle ignore_changes Syntax

**Severity:** MUST | **Requirement:** TFNFR10

The `ignore_changes` attribute **MUST NOT** be enclosed in double quotes.

**Good:**

lifecycle {
  ignore_changes = [tags]
}

**Bad:**

lifecycle {
  ignore_changes = ["tags"]
}

Null Comparison for Conditional Creation

**Severity:** SHOULD | **Requirement:** TFNFR11

For parameters requiring conditional resource creation, wrap with `object` type to avoid "known after apply" issues during plan stage.

**Recommended:**

variable "security_group" {
  type = object({
    id = string
  })
  default = null
}

Dynamic Blocks for Optional Nested Objects

**Severity:** MUST | **Requirement:** TFNFR12

Nested blocks under conditions **MUST** use this pattern:

dynamic "identity" {
  for_each = <condition> ? [<some_item>] : []

  content {
    # block content
  }
}

Default Values with coalesce/try

**Severity:** SHOULD | **Requirement:** TFNFR13

**Good:**

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

**Bad:**

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

Provider Declarations in Modules

**Severity:** MUST | **Requirement:** TFNFR27

  • `provider` **MUST NOT** be declared in modules (except for `configuration_aliases`)
  • `provider` blocks in modules
Read more
Ships withhashicorp-agent-skills

A collection of Agent skills and Claude Code plugins for HashiCorp products. Legal Note: Your use of a third party MCP Client/LLM is subject solely to the terms of use for such MCP/LLM, and IBM is not responsible for the performance of such third party tools.

Get the whole plugin
Stats
791
Stars
118
Forks
Active
Maintenance
HCL
Language
MPL-2.0
License
5d ago
Last commit
9mo ago
Created

Repo: hashicorp/agent-skills