import-infrastructure-as-code
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseImport 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 resources
azurerm_*
当用户提出以下需求时使用本技能:
- 将现有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
输入参数
| Parameter | Required | Default | Description |
|---|---|---|---|
| No | Active CLI context | Azure subscription used for subscription-scope discovery and context setting |
| No | None | Azure resource group used for resource-group-scope discovery |
| No | None | One or more Azure ARM resource IDs used for specific-resource-scope discovery |
At least one of , , or is required.
subscription-idresource-group-nameresource-id| 参数 | 必填 | 默认值 | 描述 |
|---|---|---|---|
| 否 | 活跃CLI上下文 | 用于订阅级别的资源发现和上下文设置的Azure订阅 |
| 否 | 无 | 用于资源组级别资源发现的Azure资源组 |
| 否 | 无 | 用于特定资源级别发现的一个或多个Azure ARM资源ID |
至少需要提供、或中的一项。
subscription-idresource-group-nameresource-idStep-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 values
<resource-id>
Scope handling rules:
- Treat Azure ARM resource IDs (for example ) as cloud resource identifiers, not local file system paths.
/subscriptions/.../providers/... - Use resource IDs only with Azure CLI arguments (for example
--ids).az resource show --ids <resource-id> - Never pass resource IDs to file-reading commands (,
cat,ls, glob searches) unless the user explicitly says they are local file paths.read_file - 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的参数中使用资源ID(例如
--ids)。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 jsonExpected output: JSON object with , , and .
subscriptionIdnametenantIdFor resource group or specific resource scope, is still required but is optional if the active context is already correct.
az loginaz account setWhen using specific resource scope, prefer direct -based commands first and avoid extra discovery prompts for subscription or resource group unless needed for a concrete command.
--ids仅运行所选作用域所需的命令。
订阅作用域:
bash
az login
az account set --subscription <subscription-id>
az account show --query "{subscriptionId:id, name:name, tenantId:tenantId}" -o json预期输出:包含、和的JSON对象。
subscriptionIdnametenantId对于资源组或特定资源作用域,仍需运行,但如果活跃上下文已经正确,为可选操作。
az loginaz account set使用特定资源作用域时,优先使用基于的直接命令,除非具体命令需要,否则避免额外请求订阅或资源组的发现提示。
--ids3) Run Discovery Commands
3) 运行发现命令
Discover resources using the selected scopes. Ensure to fetch all necessary information for accurate Terraform generation.
bash
undefined使用所选作用域发现资源。确保获取到生成准确Terraform代码所需的全部信息。
bash
undefinedSubscription 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.
- with all discovered resources and their metadata, including dependencies and references.
exported-resources.json - file with a human-readable architecture overview based on the discovered resources and their relationships.
EXPORTED-ARCHITECTURE.MD
解析导出的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 tool or another suitable MCP method to get module information if not available locally in the folder.
web.terraformUse 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 resources when an AVM module exists.
azurerm_*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
如果文件夹中没有本地模块信息,可以使用工具或其他合适的MCP方法获取模块信息。
.terraformweb使用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 provider
or prior experience with other AVM modules.
azurermFor each selected AVM module, fetch its README:
text
https://raw.githubusercontent.com/Azure/terraform-azurerm-avm-res-<service>-<resource>/refs/heads/main/README.mdOr if the module is already downloaded after :
terraform initbash
cat .terraform/modules/<module_key>/README.mdFrom the README, extract and record before writing code:
- 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.
- Optional Inputs — the exact Terraform variable names and their declared . Do not assume they match the raw
typeprovider argument names or block shapes.azurerm - Usage examples — check what resource group identifier is used (vs
parent_id), how child resources are expressed (inline map vs separate module), and what syntax each input expects.resource_group_name
此步骤不可跳过。 在为模块编写任何HCL代码前,先获取并完整阅读该模块的README。不要依赖对原生 provider的了解或使用其他AVM模块的过往经验。
azurerm对每个选中的AVM模块,获取其README:
text
https://raw.githubusercontent.com/Azure/terraform-azurerm-avm-res-<service>-<resource>/refs/heads/main/README.md如果后已经下载了模块,也可以通过以下方式查看:
terraform initbash
cat .terraform/modules/<module_key>/README.md编写代码前,从README中提取并记录以下内容:
- 必填输入项 — 模块需要的所有输入项。此处列出的所有子资源(网卡、扩展、子网、公网IP)都由模块内部管理。不要为这些资源创建独立的模块块。
- 可选输入项 — 准确的Terraform变量名称及其声明的。不要假设它们与原生
typeprovider的参数名称或块结构一致。azurerm - 使用示例 — 检查使用的资源组标识符(还是
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.tfavm-res-compute-virtualmachine- is a Required Input. NICs are owned by the VM module. Never create standalone
network_interfacesmodules alongside a VM module — define every NIC inline underavm-res-network-networkinterface.network_interfaces - TrustedLaunch is expressed through the top-level booleans and
secure_boot_enabled = true. Thevtpm_enabled = trueargument exists only undersecurity_typefor Confidential VM disk encryption and must not be used for TrustedLaunch.os_disk - is a
boot_diagnostics, not an object. Usebool; use the separateboot_diagnostics = truevariable if a storage URI is needed.boot_diagnostics_storage_account_uri - Extensions are managed inside the module via the map. Do not create standalone extension resources.
extensions
avm-res-network-virtualnetwork- This module is backed by the AzAPI provider, not . Use
azurerm(the full resource group resource ID string) to specify the resource group, notparent_id.resource_group_name - Every example in the README shows ; none show
parent_id.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 resources.
azurerm_*
以下示例展示了经常导致导入失败的不匹配类型,不要假设这些确切的名称适用于所有AVM模块。始终验证每个所选模块的README和。
variables.tfavm-res-compute-virtualmachine- 是必填输入项。网卡归VM模块所有。永远不要在VM模块旁创建独立的
network_interfaces模块 — 在avm-res-network-networkinterface下内联定义所有网卡。network_interfaces - 可信启动通过顶层布尔值和
secure_boot_enabled = true配置。vtpm_enabled = true参数仅存在于security_type下,用于机密VM磁盘加密,不可用于可信启动配置。os_disk - 是
boot_diagnostics类型,而非对象。使用bool;如果需要存储URI,使用单独的boot_diagnostics = true变量。boot_diagnostics_storage_account_uri - 扩展通过映射在模块内部管理。不要创建独立的扩展资源。
extensions
avm-res-network-virtualnetwork- 该模块基于AzAPI provider开发,而非。使用
azurerm(完整的资源组资源ID字符串)指定资源组,而非parent_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 downloads the modules, inspect each module's source files to determine
the exact Terraform resource addresses before writing any blocks. Never write
import addresses from memory.
terraform initimport {}terraform initimport {}Step A — Identify the provider and resource label
步骤A — 确定provider和资源标签
bash
grep "^resource" .terraform/modules/<module_key>/main*.tfThis reveals whether the module uses or labels. For example,
exposes , not
.
azurerm_*azapi_resourceavm-res-network-virtualnetworkazapi_resource "vnet"azurerm_virtual_network "this"bash
grep "^resource" .terraform/modules/<module_key>/main*.tf该命令可以显示模块使用的是还是标签。例如,暴露的是,而非。
azurerm_*azapi_resourceavm-res-network-virtualnetworkazapi_resource "vnet"azurerm_virtual_network "this"Step B — Identify child modules and nested paths
步骤B — 确定子模块和嵌套路径
bash
grep "^module" .terraform/modules/<module_key>/main*.tfIf 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
countfor_each步骤C — 检查count
与for_each
countfor_eachbash
grep -n "count\|for_each" .terraform/modules/<module_key>/main*.tfAny resource using requires an index in the import address. When (e.g.,
conditional Linux vs Windows selection), the address must end with . Resources using
use string keys, not numeric indexes.
countcount = 1[0]for_eachbash
grep -n "count\|for_each" .terraform/modules/<module_key>/main*.tf任何使用的资源在导入地址中都需要索引。当时(例如Linux与Windows的条件选择),地址必须以结尾。使用的资源使用字符串键,而非数字索引。
countcount = 1[0]for_eachKnown 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.
| Resource | Correct import |
|---|---|
| AzAPI-backed VNet | |
| Subnet (nested, count-based) | |
| Linux VM (count-based) | |
| VM NIC | |
| VM extension (default deploy_sequence=5) | |
| VM extension (deploy_sequence=1–4) | |
| NSG-NIC association | |
Produce:
- with
providers.tfprovider and required version constraintsazurerm - with AVM module blocks and explicit dependencies
main.tf - for environment-specific values
variables.tf - for key IDs and endpoints
outputs.tf - with placeholder values
terraform.tfvars.example
这些仅为示例,可作为推理模板。你需要为当前导入任务从下载的模块源码中导出确切的地址。
| 资源 | 正确的导入 |
|---|---|
| AzAPI实现的VNet | |
| 子网(嵌套,基于count) | |
| Linux VM(基于count) | |
| VM网卡 | |
| VM扩展(默认deploy_sequence=5) | |
| VM扩展(deploy_sequence=1–4) | |
| NSG-网卡关联 | |
生成以下文件:
- :包含
providers.tfprovider和所需的版本约束azurerm - :包含AVM模块块和显式依赖关系
main.tf - :用于存储环境特定值
variables.tf - :用于输出关键ID和端点
outputs.tf - :带占位符值的示例变量文件
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
. Any property where the live value differs from the module default must be
set explicitly in the Terraform configuration.
variables.tfPay particular attention to the following property categories, which are common sources
of silent configuration drift:
- Timeout values (e.g., Public IP defaults to
idle_timeout_in_minutes; live deployments often use4)30 - Network policy flags (e.g., subnet defaults to
private_endpoint_network_policies; existing subnets often have"Enabled")"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 commands, for example:
azbash
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 jsonDo not rely solely on output, which may omit nested or computed properties.
az resource listPin module versions explicitly:
hcl
module "example" {
source = "Azure/<module>/azurerm"
version = "<latest-compatible-version>"
}编写初始配置后,将每个已发现运行中资源的所有非零属性与对应AVM模块中声明的默认值进行对比。任何运行值与模块默认值不同的属性都必须在Terraform配置中显式设置。
variables.tf特别注意以下属性类别,这些是静默配置漂移的常见来源:
- 超时值(例如公网IP的默认值为
idle_timeout_in_minutes;运行环境中通常使用4)30 - 网络策略标志(例如子网的默认值为
private_endpoint_network_policies;现有子网通常设置为"Enabled")"Disabled" - SKU和分配方式(例如公网IP的、
sku)allocation_method - 可用区(例如VM可用区、公网IP可用区)
- 存储和数据库资源的冗余与复制设置
使用显式的命令获取完整的运行属性,例如:
azbash
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 planExpected 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
故障排查
| Problem | Likely Cause | Action |
|---|---|---|
| Wrong tenant/subscription or missing RBAC role | Re-run |
| Discovery output is empty | Incorrect scope or no resources in scope | Re-check scope input and run scoped list/show command again |
| No AVM module found for a resource type | Resource type not yet covered by AVM | Use native |
| Missing variables or unresolved dependencies | Add required variables and explicit dependencies, then re-run validation |
| Unknown argument or variable not found in module | AVM variable name differs from | Read the module README |
| Import block fails — resource not found at address | Wrong provider label ( | Run |
| Live value differs from AVM module default | Fetch live property with |
| Child-resource module gives "provider configuration not present" | Child resources declared as standalone modules even though parent module owns them | Check 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 index | Inspect module blocks and |
| Tool tries to read ARM resource ID as file path or asks repeated scope questions | Resource ID not treated as | Treat ARM IDs strictly as cloud identifiers, use |
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 租户/订阅错误或缺少RBAC角色 | 重新运行 |
| 发现输出为空 | 作用域错误或作用域内无资源 | 重新检查作用域输入,再次运行对应作用域的list/show命令 |
| 未找到对应资源类型的AVM模块 | AVM暂未覆盖该资源类型 | 使用原生 |
| 缺少变量或依赖未解析 | 添加必填变量和显式依赖,重新运行验证 |
| 未知参数或模块中不存在对应变量 | AVM变量名称与 | 查看模块README的 |
| 导入块失败 — 对应地址未找到资源 | provider标签错误( | 运行 |
| 运行值与AVM模块默认值不同 | 用 |
| 子资源模块提示"provider configuration not present" | 子资源被声明为独立模块,但实际归父模块所有 | 查看README中的必填输入项,删除错误的独立模块,使用父模块文档中记录的输入结构定义子资源 |
| 嵌套子资源导入失败,提示"resource not found" | 缺少中间模块路径、映射键错误或缺少索引 | 检查源文件中的模块块和 |
| 工具尝试将ARM资源ID作为文件路径读取,或重复询问作用域问题 | 资源ID未被作为 | 严格将ARM ID视为云标识符,使用 |
Response Contract
响应约定
When returning results, provide:
- Scope used (subscription, resource group, or resource IDs)
- Discovery files created
- Resource types detected
- AVM modules selected with versions
- Terraform files generated or updated
- Validation command results
- Open gaps requiring user input (if any)
返回结果时,需提供以下内容:
- 使用的作用域(订阅、资源组或资源ID)
- 创建的发现文件
- 检测到的资源类型
- 选中的AVM模块及版本
- 生成或更新的Terraform文件
- 验证命令的执行结果
- 需要用户输入的未解决缺口(如有)
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 (vs
parent_id). Skipping the README is the single most common cause of code errors in AVM-based imports.resource_group_name - 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 , grep the downloaded module source to discover the actual provider (
terraform initvsazurerm), resource labels, sub-module nesting, andazapivscountusage before writing anyfor_eachblock.import {} - Never treat ARM resource IDs as file paths. Resource IDs belong in Azure CLI arguments and API queries, not file IO tools. Only read local files when a real workspace path is provided.
--ids - 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 shows 0 destroys and 0 unwanted changes. Telemetry
terraform planresources are acceptable. Any+ createor~ updateon real infrastructure resources must be resolved.- destroy
- 缺少作用域时不要继续执行。
- 未列出已发现的文件和验证输出前,不要声明导入成功。
- 生成Terraform前不要跳过依赖映射步骤。
- 优先使用AVM模块;每个非AVM降级方案都需要明确说明理由。
- 编写代码前阅读所有AVM模块的README。 必填输入项会说明模块拥有哪些子资源。可选输入项会记录准确的变量名称和类型。使用示例会展示provider特有的约定(vs
parent_id)。跳过README是基于AVM的导入中代码错误的最常见原因。resource_group_name - 永远不要假设网卡、扩展或公网IP资源是独立的。 对于任何AVM模块,除非README明确说明需要使用独立模块,否则将子资源视为归父模块所有。创建同级模块前先检查必填输入项。
- 永远不要凭记忆编写导入地址。 后,先grep已下载的模块源码,确定实际的provider(
terraform initvsazurerm)、资源标签、子模块嵌套、以及azapivscount的使用方式,再编写for_each块。import {} - 永远不要将ARM资源ID视为文件路径。 资源ID应该用于Azure CLI的参数和API查询,而非文件IO工具。仅当提供了真实的工作区路径时才读取本地文件。
--ids - 作用域已知时尽量减少提示。 如果已经提供了订阅、资源组或特定资源ID,直接运行命令,仅当命令因缺少必填上下文失败时再询问后续问题。
- 显示0次销毁和0次非预期变更前,不要声明导入完成。 遥测类
terraform plan资源是可接受的。任何真实基础设施资源的+ create或~ update操作都必须先解决。- destroy