TFRMNFR2 - Primary Resource Naming
ID: TFRMNFR2 - Category: Naming/Composition - Primary Resource Naming
The primary azapi_resource (or equivalent AzAPI resource) declared in a Terraform resource module MUST be named this. The same rule applies to the primary resource declared in any submodule (per TFRMNFR1).
The “primary resource” is the single Azure resource that the module exists to manage — the one whose ARM resource type appears in the module’s name (per RMNFR1). Every other resource declared by the module (locks, role assignments, diagnostic settings, private endpoints, private DNS zone groups, child / extension resources required by the primary resource, etc.) is a satellite resource and MUST NOT be named this; instead, satellites MUST be named after what they represent (for example azapi_resource.lock, azapi_resource.role_assignments, azapi_resource.diagnostic_settings, azapi_resource.private_endpoints).
Standardizing on this for the primary resource lets consumers, CI checks, and the AVM interface utility module reference it predictably — most notably as azapi_resource.this.id for downstream parent_id wiring, and azapi_resource.this.output for exported values.
Example
resource "azapi_resource" "this" {
type = var.resource_types.this
name = var.name
parent_id = var.parent_id
body = { /* ... */ }
}
resource "azapi_resource" "lock" {
count = var.lock != null ? 1 : 0
type = module.avm_interfaces.lock_azapi.type
name = module.avm_interfaces.lock_azapi.name
parent_id = module.avm_interfaces.lock_azapi.parent_id
body = module.avm_interfaces.lock_azapi.body
}
resource "azapi_resource" "role_assignments" {
for_each = module.avm_interfaces.role_assignments_azapi
type = each.value.type
name = each.value.name
parent_id = each.value.parent_id
body = each.value.body
}Exceptions
The this rule MAY be relaxed only when all of the following are true:
- The module is a utility module (per Module Classifications) OR the module’s primary functionality is implemented by two or more
azapi_resourcedeclarations that are peers (no resource is the ARM parent of any other, and no resource depends on another resource’s ID for its own creation). - No single
azapi_resourcewould, on its own, be a meaningful handle for downstream consumers (i.e. there is no resource whoseidwould be the obvious value of a single canonicalresource_idoutput).
A module where one azapi_resource is the ARM parent of, or a hard dependency for, another azapi_resource is NOT exempted — the parent resource is the primary and MUST be named this.
Where this exception applies, each resource MUST be named after what it represents, and the module’s README.md MUST document why the this convention does not apply.
Notes
- This rule applies regardless of whether the primary resource uses
azapi_resource,azapi_resource_action,azapi_update_resource, or any other AzAPI resource type. - The rule applies independently to every submodule: each submodule has its own
this(the primary resource it manages) — that is the contract enabling the parent module to writemodule.<submodule>.resource_id. - The rule does not apply to data sources or to
azapi_resource_listlookups; those SHOULD still be named after what they represent.