20 skills · 53 min
Terraform
Skill 11 of 20
Migrate Terraform provider resources and data sources from Plugin SDKv2 to the Plugin Framework: muxing both plugins in one provider (terraform-plugin-mux, tf5to6server)…
4 minutes · 850 words · 9 sections
Install
npx skills add hashicorp/agent-skills --skill provider-framework-migrationnpx skills add hashicorp/agent-skills/plugin marketplace add hashicorp/agent-skillsThe first command installs just this skill, by the name in its SKILL.md; the second installs the whole repository.
The Plugin Framework is required for net-new resources and data sources; SDKv2 is maintenance-only. Migration is per-resource and incremental: a muxed provider serves SDKv2 and Framework implementations side by side, so you never need a big-bang rewrite. This skill covers the mux setup, the per-resource workflow, and the behavioral traps that turn a mechanical translation into a silent breaking change.
Reference (load when needed):
references/schema-mapping.md — the full SDKv2 → Framework translation
table with code pairsOfficial guide: Framework migration (opens in a new tab).
Migration has real risk and little user-visible payoff, so triage first:
DiffSuppressFunc,
no CustomizeDiff, no StateFunc, no complex nested blocks.To tell what mode a provider is in, check go.mod: terraform-plugin-mux
present means it already serves both; only terraform-plugin-sdk/v2 means
SDKv2-only (mux setup is your first step); only
terraform-plugin-framework means the migration is done.
Combine both plugin servers in main.go. Serving protocol version 6
requires upgrading the SDKv2 server with tf5to6server (protocol 6 needs
Terraform CLI >= 1.0; if you must support 0.12+, mux at protocol 5 with
tf6to5server/tf5muxserver instead — but the Framework provider then
cannot use protocol-6-only features like nested attributes):
package main
import (
"context"
"flag"
"log"
"github.com/hashicorp/terraform-plugin-framework/providerserver"
"
Mux requirements that bite in practice:
"metadata": {"protocol_versions": ["6.0"]} in
terraform-registry-manifest.json.The migrated resource must be indistinguishable to users. Prove it with tests that exist before the migration:
_basic with an
import step (ImportStateVerify: true), _disappears, and per-attribute
update tests. If coverage is missing, write it against the SDKv2
implementation first — these tests are the migration’s acceptance
criteria and must pass unchanged afterward.""/0/false is about
to matter), and any DiffSuppressFunc/StateFunc normalization.Translate schema and CRUD using the mapping table in
references/schema-mapping.md. The rules that prevent breaking changes:
Elem: &schema.Resource{...} written as
block { ... } syntax in user configs must become a Framework Block
(schema.ListNestedBlock/SetNestedBlock) — converting it to a nested
attribute changes the HCL syntax users must write, which is a breaking
change. Nested attributes are for new schema only.d.Get("name") returned "" for unset;
the Framework model gives you types.String that distinguishes null,
unknown, and "". Everywhere the old code checked == "" or relied on
GetOk, decide explicitly what null means, and make sure you send the
API the same thing SDKv2 sent (usually: omit the field when null).id attribute. Net-new Framework resources may omit a
redundant id, but a migrated resource must keep its exact schema —
removing or renaming attributes breaks existing state and configs.StateUpgrader — treat that as a signal the
resource may be in the do-not-migrate bucket.Register the resource in the Framework provider’s Resources() and delete
it from the SDKv2 provider’s ResourcesMap in the same commit — mux errors
on duplicates.
ImportStateVerify, which diffs imported state against
stored state and catches most null-vs-zero regressions.terraform-plugin-testing this is a two-step test
using ExternalProviders for the old version, then
ProtoV6ProviderFactories with ConfigPlanChecks asserting an empty
plan. The provider-test-patterns skill (if available) documents the
pattern.terraform plan against a real pre-migration state file shows no diff.id keptUse the provider-resources skill (if available) for Framework CRUD,
finder, and waiter patterns in the ported code, and provider-test-patterns
for the regression and version-upgrade test patterns.
Migrate Terraform provider resources and data sources from Plugin SDKv2 to the Plugin Framework: muxing both plugins in one provider (terraform-plugin-mux, tf5to6server), per-resource migration workflow, SDKv2-to-Framework schema mapping (ForceNew, ValidateFunc, DiffSuppressFunc, Default, Timeouts, blocks), null-vs-zero-value behavioral traps, and state-compatibility verification. Use when converting or translating SDKv2 resources to the Framework, setting up a muxed provider server, deciding whether a resource should be migrated at all, or debugging plan diffs and state errors that appeared after a migration.
The verbatim description from this skill’s front matter — the string an agent matches on to decide whether to load it.
plugins/terraform/skills/provider-framework-migration/SKILL.mdmain, last pushed 21 September 2026.SKILL.md, not by matching a directory convention. 2 distinct layouts observed: plugins/packer/skills/*/SKILL.md, plugins/terraform/skills/*/SKILL.md.h1 and no skipped levels:.claude-plugin/marketplace.json by HashiCorp, declaring 2 plugins. It is read for editorial metadata only — never as the skill index, which is always the repository tree./hashicorp/agent-skills.md, and each skill at its own .md URL.1 file · 6 KB
Everything this skill ships beside its prose. All of it is set here, as a subchapter of skill 11.
Documentation the agent loads on demand, rather than up front.