Summary
This is a proposal to progressively migrate provider resources from SDKv2 to the Terraform Plugin Framework, resource by resource, submitted as individual PRs. The primary motivation is re-enabling moved block support broken since v3.0.0 (see #2812), and aligning with HashiCorp's standard migration path.
I've completed a pilot implementation for kubernetes_namespace_v1 to establish the patterns before starting the bulk migration. I'd like feedback from the maintainers before proceeding.
Problem
Since v3.0.0, moved blocks between cross-type resources (e.g. kubernetes_namespace → kubernetes_namespace_v1) raise:
Error: Move Resource State Not Supported
The "kubernetes_namespace_v1" resource type does not support moving resource
state across resource types.
Root cause: SDKv2 does not implement ResourceWithMoveState. This interface is only available in the Plugin Framework.
Proposed Strategy
One PR per resource, submitted in API group order:
- Phase 0 (pilot):
kubernetes_namespace_v1 ← establishes patterns for all subsequent migrations
- Phase 1: remaining
core/v1 resources
- Phase 2:
apps/v1
- Phase 3:
batch/v1, networking, RBAC
- Phases 4–6: storage, admission, miscellaneous + data sources
- Phase 7: cleanup (remove mux once all resources migrated)
Each PR:
- Implements
ResourceWithMoveState (for moved {} blocks, Terraform ≥ 1.8)
- Implements
ResourceWithUpgradeState (for terraform state mv / pre-1.8 workflows)
- Removes the resource from SDKv2
ResourcesMap in the same commit (mux constraint: a type cannot be registered in both providers simultaneously)
- Maintains strict functional parity with the SDKv2 implementation
Key Technical Patterns (established in pilot)
MoveState
SourceTypeName == "kubernetes_namespace" routes the deprecated alias to kubernetes_namespace_v1
req.SourceRawState.JSON used directly (no SourceSchema declared)
UpgradeState (v0 → v1)
- SDKv2 serializes
schema.TypeList metadata as [{...}] → PriorSchema must use schema.ListNestedAttribute
timeouts must be present in PriorSchema (users with custom timeout blocks have it in state)
- Handler uses
req.State.Get(ctx, &prior) since PriorSchema is provided
Schema.Version = 1 on the Framework resource to trigger the upgrade path
- Null normalization:
annotations: {} → nil, generate_name: "" → types.StringNull()
KubeClientsets interface extension
- Added
GetIgnoreAnnotations() []string and GetIgnoreLabels() []string to the exported interface (needed since providerMetadata is unexported)
JSON Patch for Update
patchMetadata() takes *schema.ResourceData and cannot be reused → DiffStringMap (exported from patch_operations.go) used directly
Acceptance criteria per PR
Questions for maintainers
- PR granularity: 1 PR per resource is my default; would you prefer a different boundary (e.g. 1 PR per API group)?
kubernetes_namespace removal: The deprecated alias is removed from ResourcesMap in the same PR as the _v1 migration. Is that the right approach, or should the deprecated type remain accessible via some backward-compat path?
- Schema parity: Should these PRs strictly maintain SDKv2 parity, or is there appetite for minor schema improvements (e.g. adding validators) in the same PR?
- Testing requirements: Are acceptance tests against a real cluster required in CI for these PRs, or is the unit test + existing SDKv2 acceptance test coverage sufficient initially?
Happy to adjust the approach based on your feedback before submitting the pilot PR.
/cc @hashicorp/terraform-provider-kubernetes-maintainers
Summary
This is a proposal to progressively migrate provider resources from SDKv2 to the Terraform Plugin Framework, resource by resource, submitted as individual PRs. The primary motivation is re-enabling
movedblock support broken since v3.0.0 (see #2812), and aligning with HashiCorp's standard migration path.I've completed a pilot implementation for
kubernetes_namespace_v1to establish the patterns before starting the bulk migration. I'd like feedback from the maintainers before proceeding.Problem
Since v3.0.0,
movedblocks between cross-type resources (e.g.kubernetes_namespace → kubernetes_namespace_v1) raise:Root cause: SDKv2 does not implement
ResourceWithMoveState. This interface is only available in the Plugin Framework.Proposed Strategy
One PR per resource, submitted in API group order:
kubernetes_namespace_v1← establishes patterns for all subsequent migrationscore/v1resourcesapps/v1batch/v1, networking, RBACEach PR:
ResourceWithMoveState(formoved {}blocks, Terraform ≥ 1.8)ResourceWithUpgradeState(forterraform state mv/ pre-1.8 workflows)ResourcesMapin the same commit (mux constraint: a type cannot be registered in both providers simultaneously)Key Technical Patterns (established in pilot)
MoveState
SourceTypeName == "kubernetes_namespace"routes the deprecated alias tokubernetes_namespace_v1req.SourceRawState.JSONused directly (noSourceSchemadeclared)UpgradeState (v0 → v1)
schema.TypeListmetadata as[{...}]→ PriorSchema must useschema.ListNestedAttributetimeoutsmust be present in PriorSchema (users with custom timeout blocks have it in state)req.State.Get(ctx, &prior)since PriorSchema is providedSchema.Version = 1on the Framework resource to trigger the upgrade pathannotations: {}→ nil,generate_name: ""→types.StringNull()KubeClientsets interface extension
GetIgnoreAnnotations() []stringandGetIgnoreLabels() []stringto the exported interface (needed sinceproviderMetadatais unexported)JSON Patch for Update
patchMetadata()takes*schema.ResourceDataand cannot be reused →DiffStringMap(exported frompatch_operations.go) used directlyAcceptance criteria per PR
ResourceWithMoveState+ResourceWithUpgradeStateboth implementedplancheck.ExpectEmptyPlan()moved {}block →plancheck.ExpectEmptyPlan()ImportStateVerify: truepassesmake build,make test,make fmtcheck,make go-lintpassQuestions for maintainers
kubernetes_namespaceremoval: The deprecated alias is removed fromResourcesMapin the same PR as the_v1migration. Is that the right approach, or should the deprecated type remain accessible via some backward-compat path?Happy to adjust the approach based on your feedback before submitting the pilot PR.
/cc @hashicorp/terraform-provider-kubernetes-maintainers