mcpField
T
terraform-search-import

terraform-search-import

github.com/hashicorp云与 DevOps9094.9k 次安装今天更新
代码仓库

关于 terraform-search-import

Terraform Search and Bulk Import 技能指导用户发现现有云资源,并生成导入 Terraform state 的配置,适用于基础设施迁移、审计和资源接管。它先检查 Provider 对 list resource 的支持,再提供查询、生成配置及验证导入状态的流程。

主要功能

  1. 01查询已存在的云资源
  2. 02检查 Provider 的 list resource 支持
  3. 03按条件和区域筛选资源
  4. 04生成 resource 与 import 配置
  5. 05验证导入后的 Terraform state

适用场景

  1. 01将未纳管资源纳入 Terraform
  2. 02审计现有云基础设施
  3. 03从手动配置迁移到 IaC
  4. 04跨区域或账户发现资源

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/hashicorp/agent-skills --skill terraform-search-import

安装后在 Claude Code 中输入/terraform-search-import确认已加载。

附带文件references/MANUAL-IMPORT.mdscripts/list_resources.sh

详细介绍

Terraform 搜索和批量导入

使用声明式查询发现现有云资源,并生成配置以批量导入 Terraform 状态。

参考资料:

使用场景

  • 将未受管理的资源纳入 Terraform 管理
  • 审计现有云基础设施
  • 从手动预配迁移到 IaC
  • 跨多个区域/账户发现资源

重要:先检查 Provider 支持情况

开始之前,必须确认目标资源类型受支持:

# Check what list resources are available
./scripts/list_resources.sh aws      # Specific provider
./scripts/list_resources.sh          # All configured providers

决策树

  1. 确定目标资源类型(例如 aws_s3_bucket、aws_instance)

  2. 检查是否受支持:运行 ./scripts/list_resources.sh <provider>

  3. 选择工作流:

    • ** 如果受支持**:检查可用的 Terraform 版本。
    • ** 如果 Terraform 版本高于 1.14.0**:使用 Terraform Search 工作流(见下文)
    • ** 如果不受支持或 Terraform 版本低于 1.14.0 **:使用手动发现工作流(参见 references/MANUAL-IMPORT.md)

    注意:受支持资源的范围正在迅速扩大。使用手动导入前,务必确认当前支持情况。

先决条件

编写查询之前,请确认 Provider 支持针对目标资源类型列出资源。

发现可用的 List 资源

运行辅助脚本,从 Provider 中提取受支持的 List 资源:

# From a directory with provider configuration (runs terraform init if needed)
./scripts/list_resources.sh aws      # Specific provider
./scripts/list_resources.sh          # All configured providers

或者手动查询 Provider 架构:

terraform providers schema -json | jq '.provider_schemas | to_entries | map({key: (.key | split("/")[-1]), value: (.value.list_resource_schemas // {} | keys)})'

Terraform Search 需要已初始化的工作目录。运行查询前,请确保已配置所需 Provider:

# terraform.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

运行 terraform init 下载 Provider,然后继续执行查询。

Terraform Search 工作流(仅适用于受支持的资源)

  1. 创建 .tfquery.hcl 文件,并使用 list 块定义搜索查询
  2. 运行 terraform query 发现匹配的资源
  3. 使用 -generate-config-out=<file> 生成配置
  4. 检查并完善生成的 resource 和 import 块
  5. 运行 terraform plan 和 terraform apply 进行导入

查询文件结构

查询文件使用 .tfquery.hcl 扩展名,并支持:

  • 用于身份验证的 provider 块
  • 用于资源发现的 list 块
  • 用于参数化的 variable 和 locals 块
# discovery.tfquery.hcl
provider "aws" {
  region = "us-west-2"
}

list "aws_instance" "all" {
  provider = aws
}

List 块语法

list "<list_type>" "<symbolic_name>" {
  provider = <provider_reference>  # Required

  # Optional: filter configuration (provider-specific)
  # The `config` block schema is provider-specific. Discover available options using `terraform providers schema -json | jq '.provider_schemas."registry.terraform.io/hashicorp/<provider>".list_resource_schemas."<resource_type>"'`

  config {
    filter {
      name   = "<filter_name>"
      values = ["<value1>", "<value2>"]
    }
    region = "<region>"  # AWS-specific
  }
  # Optional: limit results
  limit = 100
}

受支持的 List 资源

各个版本对 Provider 的 List 资源支持情况各不相同。务必使用发现脚本检查特定 Provider 版本支持哪些资源。

查询示例

基本发现
# Find all EC2 instances in configured region
list "aws_instance" "all" {
  provider = aws
}
筛选发现
# Find instances by tag
list "aws_instance" "production" {
  provider = aws

  config {
    filter {
      name   = "tag:Environment"
      values = ["production"]
    }
  }
}

# Find instances by type
list "aws_instance" "large" {
  provider = aws

  config {
    filter {
      name   = "instance-type"
      values = ["t3.large", "t3.xlarge"]
    }
  }
}
多区域发现
provider "aws" {
  region = "us-west-2"
}

locals {
  regions = ["us-west-2", "us-east-1", "eu-west-1"]
}

list "aws_instance" "all_regions" {
  for_each = toset(local.regions)
  provider = aws

  config {
    region = each.value
  }
}
参数化查询
variable "target_environment" {
  type    = string
  default = "staging"
}

list "aws_instance" "by_env" {
  provider = aws

  config {
    filter {
      name   = "tag:Environment"
      values = [var.target_environment]
    }
  }
}

运行查询

# Execute queries and display results
terraform query

# Generate configuration file
terraform query -generate-config-out=imported.tf

# Pass variables
terraform query -var='target_environment=production'

查询输出格式

list.aws_instance.all   account_id=123456789012,id=i-0abc123,region=us-west-2   web-server

列:<query_address> <identity_attributes> <name_tag>

生成的配置

-generate-config-out 标志会创建:

# __generated__ by Terraform
resource "aws_instance" "all_0" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  # ... all attributes
}

import {
  to       = aws_instance.all_0
  provider = aws
  identity = {
    account_id = "123456789012"
    id         = "i-0abc123"
    region     = "us-west-2"
  }
}

生成后的清理

生成的配置包含所有属性。请按以下步骤清理:

  1. 移除计算得出的/只读属性
  2. 用变量替换硬编码值
  3. 添加恰当的资源命名
  4. 整理到适当的文件中
# Before: generated
resource "aws_instance" "all_0" {
  ami                    = "ami-0c55b159cbfafe1f0"
  instance_type          = "t2.micro"
  arn                    = "arn:aws:ec2:..."  # Remove - computed
  id                     = "i-0abc123"        # Remove - computed
  # ... many more attributes
}

# After: cleaned
resource "aws_instance" "web_server" {
  ami           = var.ami_id
  instance_type = var.instance_type
  subnet_id     = var.subnet_id

  tags = {
    Name        = "web-server"
    Environment = var.environment
  }
}

按标识导入

生成的导入使用基于标识的导入方式(Terraform 1.12+):

import {
  to       = aws_instance.web
  provider = aws
  identity = {
    account_id = "123456789012"
    id         = "i-0abc123"
    region     = "us-west-2"
  }
}

验证导入的状态

运行 terraform apply 导入资源后,请验证实际写入状态的内容。 优先使用有文档说明、稳定且更节省令牌的命令,而不是读取原始状态 文件:

# Confirm resources are now managed (also confirms addresses)
terraform state list

# Inspect resolved attribute values for imported resources
terraform show -json | jq '.values.root_module.resources[] | {address, type, name}'

terraform show -json 需要安装提供程序(terraform init),因为它会根据提供程序架构呈现值。仅在以下情况下才回退到原始状态 (terraform state pull / terraform.tfstate): 提供程序不可用且无法运行 init、你只需要粗略信息(地址、输出、serial/lineage),或 你必须避免执行 Terraform。不要将原始版本 4 状态格式解析为稳定的接口。注意: 状态在所有格式中都以明文包含敏感值 — 切勿将状态内容输出到日志或命令输出中。

最佳实践

查询设计
  • 先从宽泛查询开始,然后添加筛选条件以缩小结果范围
  • 使用 limit,避免输出内容过多
  • 生成配置前先测试查询
配置管理
  • 应用前检查所有生成的代码
  • 删除不必要的默认值
  • 使用一致的命名约定
  • 添加适当的变量抽象

故障排除

问题解决方案
"No list resources found"检查提供程序版本是否支持列表资源
查询返回空结果验证区域和筛选值
生成的配置有错误删除计算属性,修复已弃用的参数
导入失败确保资源尚未存在于状态中

完整示例

# main.tf - Initialize provider
terraform {
  required_version = ">= 1.14"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"  # Always use latest version
    }
  }
}

# discovery.tfquery.hcl - Define queries
provider "aws" {
  region = "us-west-2"
}

list "aws_instance" "team_instances" {
  provider = aws

  config {
    filter {
      name   = "tag:Owner"
      values = ["platform"]
    }
    filter {
      name   = "instance-state-name"
      values = ["running"]
    }
  }

  limit = 50
}
# Execute workflow
terraform init
terraform query
terraform query -generate-config-out=generated.tf
# Review and clean generated.tf
terraform plan
terraform apply

评论

支持 Markdown