Repository navigation
Evaluate the no-fork architecture (drop the embedded Terraform CLI) #55
Description
Follow-up to #50 and #31. Other maintainers suggested moving to Upjet's no-fork architecture: the Terraform provider's Go code is compiled into the Crossplane provider and called in-process, so there is no terraform CLI subprocess or binary. ("Fork" here means process forking, not a repository fork.)
Why
- Removes the Terraform 1.5.7 binary from the image, and with it the findings reported in Bump embedded Terraform CLI version to fix stdlib/go-getter CVEs (currently pinned to v1.5.7) #50 (go1.20.7 stdlib, go-getter v1.7.0). Terraform 1.5.7 is the last MPL-licensed release and 1.6+ is BSL, so bumping the CLI is not an option (see build: guard against BSL-licensed Terraform versions #54).
- Better performance: no process spawn per reconcile and no Terraform workspace on disk.
Reference
upbound/provider-upjet-civo: config/provider.go calls civo.Provider() and passes it to Upjet with WithTerraformProvider and WithTerraformPluginSDKIncludeList. The Dockerfile is distroless/static plus the provider binary; Terraform is only used at build time to produce config/schema.json. It runs Upjet v2.5.1 and crossplane-runtime v2.
Obstacle
The Confluent Terraform provider keeps its code in internal/provider, which other Go modules cannot import. It is Apache-2.0 and uses plugin SDK v2 only (no plugin framework).
AWS and Azure solve this with a replace in go.mod pointing at a fork of the Terraform provider that adds a public xpprovider package re-exporting the internal provider (AWS: xpprovider.GetProvider(ctx)); the fork is rebased on each upstream release. I found no existing Confluent fork.
Options
- Ask Confluent to add a public package upstream: Export a public package exposing the provider constructor (for Crossplane / Upjet) confluentinc/terraform-provider-confluent#1311.
- A small crossplane-contrib fork that only adds an
xpproviderpackage. - Vendor a copy of the provider code (not recommended).
Other work this implies
- Upgrade Upjet: this repo is on
v0.11.0-rc(Oct 2023) and crossplane-runtime v1.14. I have not verified whether that pin supports no-fork. See Upjet'sdocs/upjet-v2-upgrade.md. - Combine with Upgrade upstream Confluent Terraform provider from v2.25.0 to v2.76.0 #49 (Terraform provider 2.25.0 to 2.76.0), since it decides which provider code gets embedded.
- Migrate resources one by one (believed to be supported through the include lists; not verified).
- End-to-end testing needs a Confluent account.
Open questions
- Which route do the maintainers prefer for
internal/provider? - Who would host a fork if we need one?
- Can anyone help test against a real Confluent account?
Activity
bisbeb commentedon Oct 23, 2026
Adding the license reasoning, so we don't need to look for an OpenTofu-based solution for the runtime image:
hashicorp/terraform-plugin-sdkis MPL-2.0 (so isterraform-plugin-framework), andconfluentinc/terraform-provider-confluentis Apache-2.0. Both are permissive licenses. The BSL change (Terraform 1.6+) affects the CLI/core, which we would no longer embed.config/schema.json. The 1.5.7 pin and the guard in build: guard against BSL-licensed Terraform versions #54 cover that; OpenTofu could do that job later if needed, but it is not required for the runtime image.Caveats: this does not cover the licenses of every transitive dependency, so a license scan of the full dependency tree should be part of the migration. The generated findings from #50 would also come from our own dependency versions after the change, which we can bump ourselves, unlike the prebuilt CLI binary.