Skip to content

Target upstream terraform-plugin-sdk/v2 instead of the Pulumi fork - #3496

Draft
iwahbe wants to merge 1 commit into
mainfrom
remove-sdk-fork
Draft

Target upstream terraform-plugin-sdk/v2 instead of the Pulumi fork#3496
iwahbe wants to merge 1 commit into
mainfrom
remove-sdk-fork

Conversation

@iwahbe

@iwahbe iwahbe commented Jun 24, 2026

Copy link
Copy Markdown
Member

Goal

Remove the replace github.com/hashicorp/terraform-plugin-sdk/v2 => github.com/pulumi/terraform-plugin-sdk/v2 directive and depend on the upstream SDK directly.

This is a feasibility spike / proof of concept opened as a draft to confirm the approach builds and passes tests in CI.

What the fork provided

Diffing the fork against its upstream base (~v2.40.0), it carried exactly three patches:

  1. PlanResourceChangeExtra — a variant of PlanResourceChange that surfaces the computed *terraform.InstanceDiff (upstream discards it) and adds a TransformInstanceDiff hook to mutate the diff before it becomes planned state. The bridge needs the InstanceDiff to drive its own diff, and uses the hook to apply ignoreChanges.
  2. exports.go — re-exported HCL2ValueFromConfigValue (and NormalizeObjectFromLegacySDK, unused by the bridge) from the SDK's internal/ packages.
  3. RunProviderInternalValidation — gated Provider.Validate's call to the slow InternalValidate, defaulting to skip it at runtime.

How this PR replaces them

  • plan_resource_change.go reimplements the planning half of PlanResourceChange using the public Resource.SimpleDiff to obtain the InstanceDiff, applies ignoreChanges to that diff, then turns it into planned state. Branches the bridge never exercises (provider deferral, resource identity, RequiresReplace) are intentionally omitted.
  • linkname.go recovers the SDK's unexported / internal-only state-shaping helpers (HCL2ValueFromConfigValue, HCL2ValueFromFlatmap, ValuesSDKEquivalent, normalizeNullValues, copyTimeoutValues, setWriteOnlyNullValues, validateConfigNulls) via //go:linkname. setWriteOnlyNullValues takes an internal *configschema.Block, passed as unsafe.Pointer.
  • Provider.Validate now calls schema.InternalMap(p.tf.Schema).Validate(...) directly (InternalMap is a type alias for the unexported schemaMap), running the same validation without InternalValidate. The toggle and its test are removed.
  • Bumped the SDK require to v2.40.1 (the fork's base), so runtime behavior is unchanged.

A guard test (linkname_test.go) exercises every linked symbol, so an SDK upgrade that renames one fails as a test rather than at runtime.

Dropping the fork also shifts the module graph to newer, pruned dependency versions, removing ~365 stale transitive go.sum entries (mostly cloud.google.com/go/*).

Local validation

  • go build ./..., go vet ./..., golangci-lint — clean
  • go mod tidy idempotent, go mod verify passes
  • pkg/tfshim/sdk-v2/... — 186 passed (incl. linkname guard)
  • pkg/internal/tests/cross-tests/... — 252 passed (Pulumi/TF diff parity)
  • pkg/tfbridge/ — passed

Tradeoffs to discuss

This relocates the fork's ~120-line plan logic into the bridge plus a //go:linkname coupling to SDK internals. It removes the fork-publishing workflow at the cost of linkname brittleness across SDK upgrades (guarded by the test) and a hand-maintained copy of the plan path. Whether this is a net win over rebasing the fork is the open question this draft is meant to surface.

The bridge depended on github.com/pulumi/terraform-plugin-sdk/v2 via a
`replace` directive. The fork carried three patches over upstream:

  1. `PlanResourceChangeExtra`, a variant of `PlanResourceChange` that
     exposes the computed `*terraform.InstanceDiff` and lets the caller
     transform that diff before it is applied to produce the planned
     state.
  2. `exports.go`, which re-exported `HCL2ValueFromConfigValue` from the
     SDK's internal `hcl2shim` package.
  3. A `RunProviderInternalValidation` gate that let `Provider.Validate`
     skip the slow `InternalValidate` walk at runtime.

This change removes the fork and targets upstream v2.40.1 (the version
the fork was based on, so runtime behavior is unchanged) directly:

  * `planResourceChange` reimplements the planning half of
    `PlanResourceChange` using the public `Resource.SimpleDiff` API to
    obtain the `InstanceDiff`, applying ignoreChanges to the diff before
    turning it into the planned state. Branches the bridge never
    exercises (provider deferral, resource identity, RequiresReplace)
    are omitted.
  * `linkname.go` recovers the SDK's unexported and internal-only state
    shaping helpers via `//go:linkname`. `linkname_test.go` exercises
    every linked symbol so an SDK upgrade that renames one fails as a
    test rather than at runtime.
  * `Provider.Validate` is replaced with a direct call to
    `schema.InternalMap(...).Validate`, which runs the same schema
    validation without `InternalValidate`. The
    `RunProviderInternalValidation` toggle and its test are removed.

Dropping the fork replace also shifts the module graph to newer,
properly pruned dependency versions, which removes ~365 stale
transitive go.sum entries.
@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 66.23377% with 26 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.21%. Comparing base (db089ba) to head (15e56cc).

Files with missing lines Patch % Lines
pkg/tfshim/sdk-v2/plan_resource_change.go 64.51% 11 Missing and 11 partials ⚠️
pkg/tfshim/sdk-v2/provider2.go 72.72% 2 Missing and 1 partial ⚠️
pkg/tfshim/sdk-v2/cty.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3496   +/-   ##
=======================================
  Coverage   70.20%   70.21%           
=======================================
  Files         350      351    +1     
  Lines       38524    38553   +29     
=======================================
+ Hits        27047    27069   +22     
- Misses       9616     9618    +2     
- Partials     1861     1866    +5     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant