Help us improve
Share bugs, ideas, or general feedback.
From terraform-migration
This skill should be used when migrating Terraform provider data sources or resources from hashicorp/terraform-plugin-sdk/v2 to hashicorp/terraform-plugin-framework. Trigger phrases include "migrate to plugin framework", "SDK v2 to plugin framework", "convert to plugin framework", "migrate data source", "migrate resource", "plugin framework migration", "move to framework", or "upgrade from SDK v2". Provides step-by-step migration workflow, code patterns, schema mapping, and common gotchas.
npx claudepluginhub burythehammer/claude-code-plugins --plugin terraform-migrationHow this skill is triggered — by the user, by Claude, or both
Slash command
/terraform-migration:migrate-to-plugin-frameworkThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Migrate Terraform provider data sources and resources from `terraform-plugin-sdk/v2` to
Generates Terraform providers from OpenAPI specs using Speakeasy CLI. Covers entity annotations, CRUD operation mapping, type inference, workflow configuration, and publishing to Terraform Registry.
Provides Terraform and OpenTofu best practices for modules, testing, CI/CD, multi-environment deployments, state management, and production patterns.
Develops Terraform Provider resources and data sources using Plugin Framework. Guides CRUD operations, schema design, state management, Go patterns, and acceptance tests.
Share bugs, ideas, or general feedback.
Migrate Terraform provider data sources and resources from terraform-plugin-sdk/v2 to
terraform-plugin-framework, following patterns established by completed migrations in the
target codebase.
Before writing any code, understand how the target provider is structured. This determines whether you follow existing conventions or fall back to the templates in references/.
terraform-plugin-framework to locate already-migrated data sources and resources. Note their file structure, naming conventions, and patterns.DataSources() and Resources() are returned from the framework provider, and where DataSourcesMap/ResourcesMap are defined in the SDK provider.tfplugindocs, custom generators). Look for go:generate directives, Makefile targets, or tools/ directories.protoV5ProviderFactories or equivalent. Note the test package conventions and any shared test helpers.tf5muxserver or tf6muxserver usage. This determines whether the protocol v5 block constraint applies (see references/gotchas.md #1).TypeSet/TypeList with Elem: &schema.Resource{})ForceNew, DiffSuppressFunc, or DefaultFunc usageIf Phase 0 found existing framework code: match those conventions exactly (directory layout, file naming, import organisation).
Otherwise, use the 3-file pattern as a fallback:
Data sources:
internal/<package>/
├── datasource_<name>.go # Schema, interfaces, Metadata, Configure
├── datasource_<name>_model.go # Model struct with tfsdk tags
├── datasource_<name>_read.go # Read implementation + helpers
└── helpers.go # Shared utilities (if needed)
Resources:
internal/<package>/
├── resource_<name>.go # Schema, interfaces, Metadata, Configure
├── resource_<name>_model.go # Model struct(s) with tfsdk tags
├── resource_<name>_crud.go # Create, Read, Update, Delete implementations
└── helpers.go # Shared utilities (if needed)
Create the model struct:
id is always types.String — even if SDK v2 used TypeInt (see references/gotchas.md #5)types.String, types.Bool, types.Int64, types.Float64 for scalarstypes.Set, types.List, types.Map for collectionstfsdk:"field_name" tag matching the schema attribute nameConsult references/schema-mapping.md for the full type mapping table.
Create the schema definition with: interface checks, struct, constructor, Metadata, Configure, and Schema methods.
Key rules:
tf5muxserver, SDK v2 TypeSet/TypeList with Elem: &schema.Resource{} MUST become blocks, not attributes. See references/gotchas.md #1.MaxItems: 1 nested objects become SingleNestedBlock. See references/gotchas.md #6.id — declare as schema.StringAttribute{Computed: true}. See references/gotchas.md #5.ForceNew becomes planmodifier.RequiresReplace().DefaultFunc becomes Default (e.g., stringdefault.StaticString("value")).DiffSuppressFunc becomes a custom planmodifier.CustomizeDiff becomes ModifyPlan (implement ResourceWithModifyPlan).For code templates, see references/data-source-template.md or references/resource-template.md.
Implement the operations following these patterns:
references/gotchas.md #4.req.Config.Get(ctx, &state) (data sources) or req.Plan.Get(ctx, &plan) (resources).references/gotchas.md #2.types.ObjectValueFrom with model structs. See references/gotchas.md #3.resp.State.Set(ctx, &state).Three changes required:
DataSources() or Resources() return slice.DataSourcesMap or ResourcesMap.Use the registration files identified in Phase 0. Look for how existing framework data sources/resources are registered.
Run the build and fix errors in a loop:
go build ./...go build ./... againgo vet ./... to catch additional issuesCommon build errors during migration:
Leverage the test infrastructure discovered in Phase 0:
protoV5ProviderFactories setuptestAccPreCheck patterngo test ./internal/<package>/... -v 2>&1 | tee test-output.log
Update the corresponding docs/data-sources/ or docs/resources/ markdown file if the schema changed (e.g., id type change from int to string).
| Need | File |
|---|---|
| Type mapping (SDK v2 → Framework) | references/schema-mapping.md |
| Common failure modes | references/gotchas.md |
| Data source code template | references/data-source-template.md |
| Resource code template | references/resource-template.md |