import-infrastructure-as-code

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Import Infrastructure as Code (Azure -> Terraform with AVM)

基础设施即代码导入(Azure -> 基于AVM的Terraform)

Convert existing Azure infrastructure into maintainable Terraform code using discovery data and Azure Verified Modules.
通过发现数据和Azure Verified Modules,将现有Azure基础设施转换为可维护的Terraform代码。

When to Use This Skill

何时使用本技能

Use this skill when the user asks to:
  • Import existing Azure resources into Terraform
  • Generate IaC from live Azure environments
  • Handle any Azure resource type supported by AVM (and document justified non-AVM fallbacks)
  • Recreate infrastructure from a subscription or resource group
  • Map dependencies between discovered Azure resources
  • Use AVM modules instead of handwritten
    azurerm_*
    resources
当用户提出以下需求时使用本技能:
  • 将现有Azure资源导入Terraform
  • 从运行中的Azure环境生成IaC
  • 处理所有AVM支持的Azure资源类型(并记录合理的非AVM降级方案)
  • 从订阅或资源组重建基础设施
  • 映射已发现Azure资源之间的依赖关系
  • 使用AVM模块而非手写的
    azurerm_*
    资源

Prerequisites

前置要求

  • Azure CLI installed and authenticated (
    az login
    )
  • Access to the target subscription or resource group
  • Terraform CLI installed
  • Network access to Terraform Registry and AVM index sources
  • 已安装Azure CLI并完成身份验证(
    az login
  • 对目标订阅或资源组拥有访问权限
  • 已安装Terraform CLI
  • 可访问Terraform Registry和AVM索引源

Inputs

输入参数

ParameterRequiredDefaultDescription
subscription-id
NoActive CLI contextAzure subscription used for subscription-scope discovery and context setting
resource-group-name
NoNoneAzure resource group used for resource-group-scope discovery
resource-id
NoNoneOne or more Azure ARM resource IDs used for specific-resource-scope discovery
At least one of
subscription-id
,
resource-group-name
, or
resource-id
is required.
参数必填默认值描述
subscription-id
活跃CLI上下文用于订阅级别的资源发现和上下文设置的Azure订阅
resource-group-name
用于资源组级别资源发现的Azure资源组
resource-id
用于特定资源级别发现的一个或多个Azure ARM资源ID
至少需要提供
subscription-id
resource-group-name
resource-id
中的一项。

Step-by-Step Workflows

分步工作流

1) Collect Required Scope (Mandatory)

1) 收集必填作用域(强制步骤)

Request one of these scopes before running discovery commands:
  • Subscription scope:
    <subscription-id>
  • Resource group scope:
    <resource-group-name>
  • Specific resources scope: one or more
    <resource-id>
    values
Scope handling rules:
  • Treat Azure ARM resource IDs (for example
    /subscriptions/.../providers/...
    ) as cloud resource identifiers, not local file system paths.
  • Use resource IDs only with Azure CLI
    --ids
    arguments (for example
    az resource show --ids <resource-id>
    ).
  • Never pass resource IDs to file-reading commands (
    cat
    ,
    ls
    ,
    read_file
    , glob searches) unless the user explicitly says they are local file paths.
  • If the user already provided one valid scope, do not ask for additional scope inputs unless required by a failing command.
  • Do not ask follow-up questions that can be answered from already-provided scope values.
If scope is missing, ask for it explicitly and stop.
运行发现命令前,先请求以下作用域之一:
  • 订阅作用域:
    <subscription-id>
  • 资源组作用域:
    <resource-group-name>
  • 特定资源作用域:一个或多个
    <resource-id>
作用域处理规则:
  • 将Azure ARM资源ID(例如
    /subscriptions/.../providers/...
    )视为云资源标识符,而非本地文件系统路径。
  • 仅在Azure CLI的
    --ids
    参数中使用资源ID(例如
    az resource show --ids <resource-id>
    )。
  • 除非用户明确说明是本地文件路径,否则不要将资源ID传递给文件读取命令(
    cat
    ls
    read_file
    、通配符搜索)。
  • 如果用户已经提供了一个有效的作用域,除非命令失败需要,否则不要请求额外的作用域输入。
  • 不要询问可以通过已提供的作用域值回答的后续问题。
如果缺少作用域,明确向用户请求后停止后续操作。

2) Authenticate and Set Context

2) 身份验证与上下文设置

Run only the commands required for the selected scope.
For subscription scope:
bash
az login
az account set --subscription <subscription-id>
az account show --query "{subscriptionId:id, name:name, tenantId:tenantId}" -o json
Expected output: JSON object with
subscriptionId
,
name
, and
tenantId
.
For resource group or specific resource scope,
az login
is still required but
az account set
is optional if the active context is already correct.
When using specific resource scope, prefer direct
--ids
-based commands first and avoid extra discovery prompts for subscription or resource group unless needed for a concrete command.
仅运行所选作用域所需的命令。
订阅作用域:
bash
az login
az account set --subscription <subscription-id>
az account show --query "{subscriptionId:id, name:name, tenantId:tenantId}" -o json
预期输出:包含
subscriptionId
name
tenantId
的JSON对象。
对于资源组或特定资源作用域,仍需运行
az login
,但如果活跃上下文已经正确,
az account set
为可选操作。
使用特定资源作用域时,优先使用基于
--ids
的直接命令,除非具体命令需要,否则避免额外请求订阅或资源组的发现提示。

3) Run Discovery Commands

3) 运行发现命令

Discover resources using the selected scopes. Ensure to fetch all necessary information for accurate Terraform generation.
bash
undefined
使用所选作用域发现资源。确保获取到生成准确Terraform代码所需的全部信息。
bash
undefined

Subscription scope

订阅作用域

az resource list --subscription <subscription-id> -o json
az resource list --subscription <subscription-id> -o json

Resource group scope

资源组作用域

az resource list --resource-group <resource-group-name> -o json
az resource list --resource-group <resource-group-name> -o json

Specific resource scope

特定资源作用域

az resource show --ids <resource-id-1> <resource-id-2> ... -o json

Expected output: JSON object or array containing Azure resource metadata (`id`, `type`, `name`, `location`, `tags`, `properties`).
az resource show --ids <resource-id-1> <resource-id-2> ... -o json

预期输出:包含Azure资源元数据(`id`、`type`、`name`、`location`、`tags`、`properties`)的JSON对象或数组。

4) Resolve Dependencies Before Code Generation

4) 代码生成前解析依赖关系

Parse exported JSON and map:
  • Parent-child relationships (for example: NIC -> Subnet -> VNet)
  • Cross-resource references in
    properties
  • Ordering for Terraform creation
IMPORTANT: Generate the following documentation and save it to a docs folder in the root of the project.
  • exported-resources.json
    with all discovered resources and their metadata, including dependencies and references.
  • EXPORTED-ARCHITECTURE.MD
    file with a human-readable architecture overview based on the discovered resources and their relationships.
解析导出的JSON并映射:
  • 父子关系(例如:网卡 -> 子网 -> 虚拟网络)
  • properties
    中的跨资源引用
  • Terraform创建顺序
重要提示:生成以下文档并保存到项目根目录的docs文件夹中。
  • exported-resources.json
    :包含所有已发现资源及其元数据,包括依赖和引用关系。
  • EXPORTED-ARCHITECTURE.MD
    :基于已发现资源及其关系生成的可读性架构概览文件。

5) Select Azure Verified Modules (Required)

5) 选择Azure Verified Modules(强制步骤)

Use the latest AVM version for each resource type.
为每个资源类型使用最新的AVM版本。

Terraform Registry

Terraform Registry

  • Search for "avm" + resource name
  • Filter by "Partner" tag to find official AVM modules
  • Example: Search "avm storage account" → filter by Partner
  • 搜索"avm" + 资源名称
  • 按"Partner"标签筛选以找到官方AVM模块
  • 示例:搜索"avm storage account" → 按Partner筛选

Official AVM Index

官方AVM索引

Note: The following links always point to the latest version of the CSV files on the main branch. As intended, this means the files may change over time. If you require a point-in-time version, consider using a specific release tag in the URL.
  • Terraform Resource Modules:
    https://raw.githubusercontent.com/Azure/Azure-Verified-Modules/refs/heads/main/docs/static/module-indexes/TerraformResourceModules.csv
  • Terraform Pattern Modules:
    https://raw.githubusercontent.com/Azure/Azure-Verified-Modules/refs/heads/main/docs/static/module-indexes/TerraformPatternModules.csv
  • Terraform Utility Modules:
    https://raw.githubusercontent.com/Azure/Azure-Verified-Modules/refs/heads/main/docs/static/module-indexes/TerraformUtilityModules.csv
注意: 以下链接始终指向主分支上CSV文件的最新版本。这意味着文件可能会随时间变化,符合设计预期。如果需要特定时间点的版本,可以在URL中使用特定的发布标签。
  • Terraform资源模块:
    https://raw.githubusercontent.com/Azure/Azure-Verified-Modules/refs/heads/main/docs/static/module-indexes/TerraformResourceModules.csv
  • Terraform模式模块:
    https://raw.githubusercontent.com/Azure/Azure-Verified-Modules/refs/heads/main/docs/static/module-indexes/TerraformPatternModules.csv
  • Terraform工具模块:
    https://raw.githubusercontent.com/Azure/Azure-Verified-Modules/refs/heads/main/docs/static/module-indexes/TerraformUtilityModules.csv

Individual Module information

单个模块信息

Use the
web
tool or another suitable MCP method to get module information if not available locally in the
.terraform
folder.
Use AVM sources:
  • Registry:
    https://registry.terraform.io/modules/Azure/<module>/azurerm/latest
  • GitHub:
    https://github.com/Azure/terraform-azurerm-avm-res-<service>-<resource>
Prefer AVM modules over handwritten
azurerm_*
resources when an AVM module exists.
When fetching module information from GitHub repositories, the README.md file in the root of the repository typically contains all detailed information about the module, for example: https://raw.githubusercontent.com/Azure/terraform-azurerm-avm-res-<service>-<resource>/refs/heads/main/README.md
如果
.terraform
文件夹中没有本地模块信息,可以使用
web
工具或其他合适的MCP方法获取模块信息。
使用AVM源:
  • Registry:
    https://registry.terraform.io/modules/Azure/<module>/azurerm/latest
  • GitHub:
    https://github.com/Azure/terraform-azurerm-avm-res-<service>-<resource>
当存在对应AVM模块时,优先使用AVM模块而非手写的
azurerm_*
资源。
从GitHub仓库获取模块信息时,仓库根目录下的README.md文件通常包含模块的所有详细信息,例如:https://raw.githubusercontent.com/Azure/terraform-azurerm-avm-res-<service>-<resource>/refs/heads/main/README.md

5a) Read the Module README Before Writing Any Code (Mandatory)

5a) 编写代码前必须阅读模块README(强制步骤)

This step is not optional. Before writing a single line of HCL for a module, fetch and read the full README for that module. Do not rely on knowledge of the raw
azurerm
provider or prior experience with other AVM modules.
For each selected AVM module, fetch its README:
text
https://raw.githubusercontent.com/Azure/terraform-azurerm-avm-res-<service>-<resource>/refs/heads/main/README.md
Or if the module is already downloaded after
terraform init
:
bash
cat .terraform/modules/<module_key>/README.md
From the README, extract and record before writing code:
  1. Required Inputs — every input the module requires. Any child resource listed here (NICs, extensions, subnets, public IPs) is managed inside the module. Do not create standalone module blocks for those resources.
  2. Optional Inputs — the exact Terraform variable names and their declared
    type
    . Do not assume they match the raw
    azurerm
    provider argument names or block shapes.
  3. Usage examples — check what resource group identifier is used (
    parent_id
    vs
    resource_group_name
    ), how child resources are expressed (inline map vs separate module), and what syntax each input expects.
此步骤不可跳过。 在为模块编写任何HCL代码前,先获取并完整阅读该模块的README。不要依赖对原生
azurerm
provider的了解或使用其他AVM模块的过往经验。
对每个选中的AVM模块,获取其README:
text
https://raw.githubusercontent.com/Azure/terraform-azurerm-avm-res-<service>-<resource>/refs/heads/main/README.md
如果
terraform init
后已经下载了模块,也可以通过以下方式查看:
bash
cat .terraform/modules/<module_key>/README.md
编写代码前,从README中提取并记录以下内容:
  1. 必填输入项 — 模块需要的所有输入项。此处列出的所有子资源(网卡、扩展、子网、公网IP)都由模块内部管理。不要为这些资源创建独立的模块块。
  2. 可选输入项 — 准确的Terraform变量名称及其声明的
    type
    。不要假设它们与原生
    azurerm
    provider的参数名称或块结构一致。
  3. 使用示例 — 检查使用的资源组标识符(
    parent_id
    还是
    resource_group_name
    )、子资源的表达形式(内联映射还是独立模块)、以及每个输入要求的语法。

Apply module rules as patterns, not assumptions

将模块规则作为模式使用,而非假设

Use the lessons below as examples of the type of mismatch that often causes imports to fail. Do not assume these exact names apply to every AVM module. Always verify each selected module's README and
variables.tf
.
avm-res-compute-virtualmachine
(any version)
  • network_interfaces
    is a Required Input. NICs are owned by the VM module. Never create standalone
    avm-res-network-networkinterface
    modules alongside a VM module — define every NIC inline under
    network_interfaces
    .
  • TrustedLaunch is expressed through the top-level booleans
    secure_boot_enabled = true
    and
    vtpm_enabled = true
    . The
    security_type
    argument exists only under
    os_disk
    for Confidential VM disk encryption and must not be used for TrustedLaunch.
  • boot_diagnostics
    is a
    bool
    , not an object. Use
    boot_diagnostics = true
    ; use the separate
    boot_diagnostics_storage_account_uri
    variable if a storage URI is needed.
  • Extensions are managed inside the module via the
    extensions
    map. Do not create standalone extension resources.
avm-res-network-virtualnetwork
(any version)
  • This module is backed by the AzAPI provider, not
    azurerm
    . Use
    parent_id
    (the full resource group resource ID string) to specify the resource group, not
    resource_group_name
    .
  • Every example in the README shows
    parent_id
    ; none show
    resource_group_name
    .
Generalized takeaway for all AVM modules:
  • Determine child resource ownership from Required Inputs before creating sibling modules.
  • Determine accepted variable names and types from Optional Inputs and
    variables.tf
    .
  • Determine identifier style and input shape from README usage examples.
  • Do not infer argument names from raw
    azurerm_*
    resources.
以下示例展示了经常导致导入失败的不匹配类型,不要假设这些确切的名称适用于所有AVM模块。始终验证每个所选模块的README和
variables.tf
avm-res-compute-virtualmachine
(任意版本)
  • network_interfaces
    必填输入项。网卡归VM模块所有。永远不要在VM模块旁创建独立的
    avm-res-network-networkinterface
    模块 — 在
    network_interfaces
    下内联定义所有网卡。
  • 可信启动通过顶层布尔值
    secure_boot_enabled = true
    vtpm_enabled = true
    配置。
    security_type
    参数仅存在于
    os_disk
    下,用于机密VM磁盘加密,不可用于可信启动配置。
  • boot_diagnostics
    bool
    类型,而非对象。使用
    boot_diagnostics = true
    ;如果需要存储URI,使用单独的
    boot_diagnostics_storage_account_uri
    变量。
  • 扩展通过
    extensions
    映射在模块内部管理。不要创建独立的扩展资源。
avm-res-network-virtualnetwork
(任意版本)
  • 该模块基于AzAPI provider开发,而非
    azurerm
    。使用
    parent_id
    (完整的资源组资源ID字符串)指定资源组,而非
    resource_group_name
  • README中的所有示例都使用
    parent_id
    ,没有使用
    resource_group_name
    的示例。
所有AVM模块的通用要点:
  • 创建同级模块前,通过必填输入项确定子资源的归属。
  • 通过可选输入项
    variables.tf
    确定可接受的变量名称和类型。
  • 通过README使用示例确定标识符风格和输入结构。
  • 不要从原生
    azurerm_*
    资源推断参数名称。

6) Generate Terraform Files

6) 生成Terraform文件

Before Writing Import Blocks — Inspect Module Source (Mandatory)

编写导入块前检查模块源码(强制步骤)

After
terraform init
downloads the modules, inspect each module's source files to determine the exact Terraform resource addresses before writing any
import {}
blocks. Never write import addresses from memory.
terraform init
下载模块后,检查每个模块的源文件,确定准确的Terraform资源地址,再编写
import {}
块。永远不要凭记忆编写导入地址。

Step A — Identify the provider and resource label

步骤A — 确定provider和资源标签

bash
grep "^resource" .terraform/modules/<module_key>/main*.tf
This reveals whether the module uses
azurerm_*
or
azapi_resource
labels. For example,
avm-res-network-virtualnetwork
exposes
azapi_resource "vnet"
, not
azurerm_virtual_network "this"
.
bash
grep "^resource" .terraform/modules/<module_key>/main*.tf
该命令可以显示模块使用的是
azurerm_*
还是
azapi_resource
标签。例如,
avm-res-network-virtualnetwork
暴露的是
azapi_resource "vnet"
,而非
azurerm_virtual_network "this"

Step B — Identify child modules and nested paths

步骤B — 确定子模块和嵌套路径

bash
grep "^module" .terraform/modules/<module_key>/main*.tf
If child resources are managed in a sub-module (subnets, extensions, etc.), the import address must include every intermediate module label:
text
module.<root_module_key>.module.<child_module_key>["<map_key>"].<resource_type>.<label>[<index>]
bash
grep "^module" .terraform/modules/<module_key>/main*.tf
如果子资源在子模块中管理(子网、扩展等),导入地址必须包含所有中间模块标签:
text
module.<root_module_key>.module.<child_module_key>["<map_key>"].<resource_type>.<label>[<index>]

Step C — Check for
count
vs
for_each

步骤C — 检查
count
for_each

bash
grep -n "count\|for_each" .terraform/modules/<module_key>/main*.tf
Any resource using
count
requires an index in the import address. When
count = 1
(e.g., conditional Linux vs Windows selection), the address must end with
[0]
. Resources using
for_each
use string keys, not numeric indexes.
bash
grep -n "count\|for_each" .terraform/modules/<module_key>/main*.tf
任何使用
count
的资源在导入地址中都需要索引。当
count = 1
时(例如Linux与Windows的条件选择),地址必须以
[0]
结尾。使用
for_each
的资源使用字符串键,而非数字索引。

Known import address patterns (examples from lessons learned)

已知导入地址模式(经验示例)

These are examples only. Use them as templates for reasoning, then derive the exact addresses from the downloaded source code for the modules in your current import.
ResourceCorrect import
to
address pattern
AzAPI-backed VNet
module.<vnet_key>.azapi_resource.vnet
Subnet (nested, count-based)
module.<vnet_key>.module.subnet["<subnet_name>"].azapi_resource.subnet[0]
Linux VM (count-based)
module.<vm_key>.azurerm_linux_virtual_machine.this[0]
VM NIC
module.<vm_key>.azurerm_network_interface.virtualmachine_network_interfaces["<nic_key>"]
VM extension (default deploy_sequence=5)
module.<vm_key>.module.extension["<ext_name>"].azurerm_virtual_machine_extension.this
VM extension (deploy_sequence=1–4)
module.<vm_key>.module.extension_<n>["<ext_name>"].azurerm_virtual_machine_extension.this
NSG-NIC association
module.<vm_key>.azurerm_network_interface_security_group_association.this["<nic_key>-<nsg_key>"]
Produce:
  • providers.tf
    with
    azurerm
    provider and required version constraints
  • main.tf
    with AVM module blocks and explicit dependencies
  • variables.tf
    for environment-specific values
  • outputs.tf
    for key IDs and endpoints
  • terraform.tfvars.example
    with placeholder values
这些仅为示例,可作为推理模板。你需要为当前导入任务从下载的模块源码中导出确切的地址。
资源正确的导入
to
地址模式
AzAPI实现的VNet
module.<vnet_key>.azapi_resource.vnet
子网(嵌套,基于count)
module.<vnet_key>.module.subnet["<subnet_name>"].azapi_resource.subnet[0]
Linux VM(基于count)
module.<vm_key>.azurerm_linux_virtual_machine.this[0]
VM网卡
module.<vm_key>.azurerm_network_interface.virtualmachine_network_interfaces["<nic_key>"]
VM扩展(默认deploy_sequence=5)
module.<vm_key>.module.extension["<ext_name>"].azurerm_virtual_machine_extension.this
VM扩展(deploy_sequence=1–4)
module.<vm_key>.module.extension_<n>["<ext_name>"].azurerm_virtual_machine_extension.this
NSG-网卡关联
module.<vm_key>.azurerm_network_interface_security_group_association.this["<nic_key>-<nsg_key>"]
生成以下文件:
  • providers.tf
    :包含
    azurerm
    provider和所需的版本约束
  • main.tf
    :包含AVM模块块和显式依赖关系
  • variables.tf
    :用于存储环境特定值
  • outputs.tf
    :用于输出关键ID和端点
  • terraform.tfvars.example
    :带占位符值的示例变量文件

Diff Live Properties Against Module Defaults (Mandatory)

对比运行中属性与模块默认值(强制步骤)

After writing the initial configuration, compare every non-zero property of each discovered live resource against the default value declared in the corresponding AVM module's
variables.tf
. Any property where the live value differs from the module default must be set explicitly in the Terraform configuration.
Pay particular attention to the following property categories, which are common sources of silent configuration drift:
  • Timeout values (e.g., Public IP
    idle_timeout_in_minutes
    defaults to
    4
    ; live deployments often use
    30
    )
  • Network policy flags (e.g., subnet
    private_endpoint_network_policies
    defaults to
    "Enabled"
    ; existing subnets often have
    "Disabled"
    )
  • SKU and allocation (e.g., Public IP
    sku
    ,
    allocation_method
    )
  • Availability zones (e.g., VM zone, Public IP zone)
  • Redundancy and replication settings on storage and database resources
Retrieve full live properties with explicit
az
commands, for example:
bash
az network public-ip show --ids <resource_id> --query "{idleTimeout:idleTimeoutInMinutes, sku:sku.name, zones:zones}" -o json
az network vnet subnet show --ids <resource_id> --query "{privateEndpointPolicies:privateEndpointNetworkPolicies, delegation:delegations}" -o json
Do not rely solely on
az resource list
output, which may omit nested or computed properties.
Pin module versions explicitly:
hcl
module "example" {
	source  = "Azure/<module>/azurerm"
	version = "<latest-compatible-version>"
}
编写初始配置后,将每个已发现运行中资源的所有非零属性与对应AVM模块
variables.tf
中声明的默认值进行对比。任何运行值与模块默认值不同的属性都必须在Terraform配置中显式设置。
特别注意以下属性类别,这些是静默配置漂移的常见来源:
  • 超时值(例如公网IP的
    idle_timeout_in_minutes
    默认值为
    4
    ;运行环境中通常使用
    30
  • 网络策略标志(例如子网的
    private_endpoint_network_policies
    默认值为
    "Enabled"
    ;现有子网通常设置为
    "Disabled"
  • SKU和分配方式(例如公网IP的
    sku
    allocation_method
  • 可用区(例如VM可用区、公网IP可用区)
  • 存储和数据库资源的冗余与复制设置
使用显式的
az
命令获取完整的运行属性,例如:
bash
az network public-ip show --ids <resource_id> --query "{idleTimeout:idleTimeoutInMinutes, sku:sku.name, zones:zones}" -o json
az network vnet subnet show --ids <resource_id> --query "{privateEndpointPolicies:privateEndpointNetworkPolicies, delegation:delegations}" -o json
不要仅依赖
az resource list
的输出,它可能会遗漏嵌套或计算属性。
显式固定模块版本:
hcl
module "example" {
	source  = "Azure/<module>/azurerm"
	version = "<latest-compatible-version>"
}

7) Validate Generated Code

7) 验证生成的代码

Run:
bash
terraform init
terraform fmt -recursive
terraform validate
terraform plan
Expected output: no syntax errors, no validation errors, and a plan that matches discovered infrastructure intent.
运行:
bash
terraform init
terraform fmt -recursive
terraform validate
terraform plan
预期输出:无语法错误、无验证错误、生成的执行计划与已发现基础设施的预期一致。

Troubleshooting

故障排查

ProblemLikely CauseAction
az
command fails with authorization errors
Wrong tenant/subscription or missing RBAC roleRe-run
az login
, verify subscription context, confirm required permissions
Discovery output is emptyIncorrect scope or no resources in scopeRe-check scope input and run scoped list/show command again
No AVM module found for a resource typeResource type not yet covered by AVMUse native
azurerm_*
resource for that type and document the gap
terraform validate
fails
Missing variables or unresolved dependenciesAdd required variables and explicit dependencies, then re-run validation
Unknown argument or variable not found in moduleAVM variable name differs from
azurerm
provider argument name
Read the module README
variables.tf
or Optional Inputs section for the correct name
Import block fails — resource not found at addressWrong provider label (
azurerm_
vs
azapi_
), missing sub-module path, or missing
[0]
index
Run
grep "^resource" .terraform/modules/<key>/main*.tf
and
grep "^module"
to find exact address
terraform plan
shows unexpected
~ update
on imported resource
Live value differs from AVM module defaultFetch live property with
az <resource> show
, compare to module default, add explicit value
Child-resource module gives "provider configuration not present"Child resources declared as standalone modules even though parent module owns themCheck Required Inputs in README, remove incorrect standalone modules, and model child resources using the parent module's documented input structure
Nested child resource import fails with "resource not found"Missing intermediate module path, wrong map key, or missing indexInspect module blocks and
count
/
for_each
in source; build full nested import address including all module segments and required key/index
Tool tries to read ARM resource ID as file path or asks repeated scope questionsResource ID not treated as
--ids
input, or agent did not trust already-provided scope
Treat ARM IDs strictly as cloud identifiers, use
az ... --ids ...
, and stop re-prompting once one valid scope is present
问题可能原因解决方案
az
命令执行失败,提示授权错误
租户/订阅错误或缺少RBAC角色重新运行
az login
,验证订阅上下文,确认拥有所需权限
发现输出为空作用域错误或作用域内无资源重新检查作用域输入,再次运行对应作用域的list/show命令
未找到对应资源类型的AVM模块AVM暂未覆盖该资源类型使用原生
azurerm_*
资源实现该类型,并记录该缺口
terraform validate
执行失败
缺少变量或依赖未解析添加必填变量和显式依赖,重新运行验证
未知参数或模块中不存在对应变量AVM变量名称与
azurerm
provider参数名称不同
查看模块README的
variables.tf
或可选输入部分获取正确名称
导入块失败 — 对应地址未找到资源provider标签错误(
azurerm_
vs
azapi_
)、缺少子模块路径或缺少
[0]
索引
运行
grep "^resource" .terraform/modules/<key>/main*.tf
grep "^module"
查找准确地址
terraform plan
显示导入的资源存在意外的
~ update
操作
运行值与AVM模块默认值不同
az <resource> show
获取运行属性,与模块默认值对比,添加显式赋值
子资源模块提示"provider configuration not present"子资源被声明为独立模块,但实际归父模块所有查看README中的必填输入项,删除错误的独立模块,使用父模块文档中记录的输入结构定义子资源
嵌套子资源导入失败,提示"resource not found"缺少中间模块路径、映射键错误或缺少索引检查源文件中的模块块和
count
/
for_each
配置;构建包含所有模块段和必填键/索引的完整嵌套导入地址
工具尝试将ARM资源ID作为文件路径读取,或重复询问作用域问题资源ID未被作为
--ids
输入处理,或Agent未信任已提供的作用域
严格将ARM ID视为云标识符,使用
az ... --ids ...
命令,获得一个有效作用域后停止重复询问

Response Contract

响应约定

When returning results, provide:
  1. Scope used (subscription, resource group, or resource IDs)
  2. Discovery files created
  3. Resource types detected
  4. AVM modules selected with versions
  5. Terraform files generated or updated
  6. Validation command results
  7. Open gaps requiring user input (if any)
返回结果时,需提供以下内容:
  1. 使用的作用域(订阅、资源组或资源ID)
  2. 创建的发现文件
  3. 检测到的资源类型
  4. 选中的AVM模块及版本
  5. 生成或更新的Terraform文件
  6. 验证命令的执行结果
  7. 需要用户输入的未解决缺口(如有)

Execution Rules for the Agent

Agent执行规则

  • Do not continue if scope is missing.
  • Do not claim successful import without listing discovered files and validation output.
  • Do not skip dependency mapping before generating Terraform.
  • Prefer AVM modules first; justify each non-AVM fallback explicitly.
  • Read the README for every AVM module before writing code. Required Inputs identify which child resources the module owns. Optional Inputs document exact variable names and types. Usage examples show provider-specific conventions (
    parent_id
    vs
    resource_group_name
    ). Skipping the README is the single most common cause of code errors in AVM-based imports.
  • Never assume NIC, extension, or public IP resources are standalone. For any AVM module, treat child resources as parent-owned unless the README explicitly indicates a separate module is required. Check Required Inputs before creating sibling modules.
  • Never write import addresses from memory. After
    terraform init
    , grep the downloaded module source to discover the actual provider (
    azurerm
    vs
    azapi
    ), resource labels, sub-module nesting, and
    count
    vs
    for_each
    usage before writing any
    import {}
    block.
  • Never treat ARM resource IDs as file paths. Resource IDs belong in Azure CLI
    --ids
    arguments and API queries, not file IO tools. Only read local files when a real workspace path is provided.
  • Minimize prompts when scope is already known. If subscription, resource group, or specific resource IDs are already provided, proceed with commands directly and only ask a follow-up when a command fails due to missing required context.
  • Do not declare the import complete until
    terraform plan
    shows 0 destroys and 0 unwanted changes.
    Telemetry
    + create
    resources are acceptable. Any
    ~ update
    or
    - destroy
    on real infrastructure resources must be resolved.
  • 缺少作用域时不要继续执行。
  • 未列出已发现的文件和验证输出前,不要声明导入成功。
  • 生成Terraform前不要跳过依赖映射步骤。
  • 优先使用AVM模块;每个非AVM降级方案都需要明确说明理由。
  • 编写代码前阅读所有AVM模块的README。 必填输入项会说明模块拥有哪些子资源。可选输入项会记录准确的变量名称和类型。使用示例会展示provider特有的约定(
    parent_id
    vs
    resource_group_name
    )。跳过README是基于AVM的导入中代码错误的最常见原因。
  • 永远不要假设网卡、扩展或公网IP资源是独立的。 对于任何AVM模块,除非README明确说明需要使用独立模块,否则将子资源视为归父模块所有。创建同级模块前先检查必填输入项。
  • 永远不要凭记忆编写导入地址。
    terraform init
    后,先grep已下载的模块源码,确定实际的provider(
    azurerm
    vs
    azapi
    )、资源标签、子模块嵌套、以及
    count
    vs
    for_each
    的使用方式,再编写
    import {}
    块。
  • 永远不要将ARM资源ID视为文件路径。 资源ID应该用于Azure CLI的
    --ids
    参数和API查询,而非文件IO工具。仅当提供了真实的工作区路径时才读取本地文件。
  • 作用域已知时尽量减少提示。 如果已经提供了订阅、资源组或特定资源ID,直接运行命令,仅当命令因缺少必填上下文失败时再询问后续问题。
  • terraform plan
    显示0次销毁和0次非预期变更前,不要声明导入完成。
    遥测类
    + create
    资源是可接受的。任何真实基础设施资源的
    ~ update
    - destroy
    操作都必须先解决。

References

参考资料