feat(fwprovider): export the provider implementation for embedding - #434
feat(fwprovider): export the provider implementation for embedding#434michvllni wants to merge 1 commit into
Conversation
The provider lives in internal/provider, so consumers outside this module cannot obtain a provider.Provider value. That blocks embedding it in-process and forces downstreams to fork this repo just to add the export. Add a public fwprovider package that delegates to the existing constructor, following the terraform-provider-google precedent. No new dependencies, no behaviour change, and the rest of internal/ stays internal. Refs coder#354
ethanndickson
left a comment
There was a problem hiding this comment.
fwprovider as a name is fine with me, and I don't have any objections with the export.
I'm not able to say if we'll have resources for any maintenance work this introduces, i.e. reviewing fixes for bugs only present downstream, but if this alone is useful I suppose it's fine?
I think that's fair. In the end this is an extension that allows extended usage. If there is something missing or issues, it would be the job of said extensions to handle it or open PRs to mitigate |
Adds a public
fwproviderpackage that hands out the provider implementation, so Go programs can embed the provider in-process instead of running it as a plugin binary.Motivation
In #354 I asked for a Crossplane provider for Coder. Crossplane's Upjet generates one directly from a Terraform provider's schema, and it can drive that provider two ways:
terraformbinary and the provider binary into its controller image, then runsterraformagainst a workspace per managed resource, which in turn launches the provider plugin. It works against any provider and needs no cooperation from upstream.provider.Providerimplementation directly through its plugin-framework client. Noterraformbinary, no provider binary, no subprocess per reconcile.In-process mode needs an importable
provider.Provider.internal/provideris unimportable outside this module, so today the only route is to fork this repo and add the export in the fork. That is exactly what Upbound does for the providers that keep theirs internal —terraform-provider-aws/xpproviderandterraform-provider-azurerm/xpprovider, both wired in through areplacedirective. Providers that expose theirs upstream need no fork at all:terraform-provider-googlehasgoogle/fwprovider,terraform-provider-keycloakhasprovider.I would rather not maintain a fork of this repo that has to be re-synced on every release, and I doubt you want one circulating either.
What changed
A single public package delegating to the existing constructor:
Returning the factory rather than an instance keeps the signature identical to
provider.New, so it still drops straight intoproviderserver.Serve; embedders call it to get an instance.Kept deliberately small:
terraform-plugin-frameworkis already required.provider.Newbreaks the build here too.internal/stays internal. This exports the provider surface only, not resource implementations,codersdkplumbing, or helpers.main.gois untouched.main.goserves, withTypeName, version, resources and data sources all wired.I named it
fwproviderafter theterraform-provider-googleprecedent rather than Upbound's Crossplane-specificxpprovider, on the grounds that this is an export you own rather than one living in a downstream fork. Happy to rename it, relocate it, or narrow the signature.Context
I have built an Upjet-based Crossplane provider covering all 15 resources, exposing both cluster-scoped and namespaced Crossplane v2 APIs, with a scheduled job that regenerates and opens a PR when a release lands here. It runs in Terraform CLI mode today, because that is the only mode available without forking this repo.
I took the liberty of starting the implementation rather than just filing the request, so there is something concrete to react to. If you would like the Crossplane provider itself to live under the Coder org, I am happy to donate it; equally happy to keep maintaining it out-of-tree if you would rather not adopt another repo. Either way this export stands on its own for anyone embedding the provider.
Refs #354