Terraform gRPC alternative client implementation

Hi!
I’m currently trying to understand the feasibility of create an alternative client
for communicate with the providers.
The main goal i’ am trying to achieve is using Nix as
the main language, instead of HCL/JSON for managing the plugins and the
infrastructure itself.

So having a bunch of nix files, and a new client gRPC for communicate with the
already created plugins (providers).

I don’t know if what i want to achieve is clear…
Thanks in advance :smiley:

Hi @mll,

It is possible in principle to write a “plugin client” (which is what we call the process that launches the plugins) in a language other than Go, but there are more parts to implement than just the gRPC client layer. For example:

  • gRPC only deals with the messages sent between client and server once the server is running. Terraform also has a specific protocol for launching the plugin process and negotiating a communication channel with it, which includes a TLS key exchange and selecting a network channel to communicate over.
  • The Terraform plugin protocol is defined in terms of gRPC, but there are higher-level behaviors you will also need to match in your own code in order to successfully interact with a provider. For example, you will need to be able to encode dynamically-specified values such as the resource configuration in the way that Terraform providers expect, which is just a byte array at the gRPC layer but of course that array must contain data in a suitable format that is not visible in the protobuf schema alone.
  • Terraform also includes functionality for interacting with a provider registry to automatically install providers, which may or may not be important to your particular goal.

Terraform currently interacts with its plugins using a Go-specific library that has no associated protocol specification. You’ll have the easiest time if you write your software also in Go and use go-plugin to implement the plugin handshake.

However, unofficially (which is to say: this is not a guarantee made by the Terraform team to remain true for all future protocol versions) the protocol is more-or-less compatible with the derived RPCPlugin Protocol that isn’t a HashiCorp project, and so with some care to review the appendix about HashiCorp go-plugin compatibility I have successfully written side-projects that interact with currently-published Terraform providers using implementations of the rpcplugin spec, and so it may be a useful starting point for implementations in other languages.

I will caution that the API offered by individual providers is lower-level than you might hope, and that the runtime engine in Terraform Core (built around HCL) is a large part of what makes the Terraform workflow work. It is of course possible to implement an alternative runtime around the same providers, but you should not expect that reusing the existing Terraform providers will make the implementation work trivial on your side.

So, in the meantime I thank you for the very comprehensive answer.
I probably didn’t explain myself correctly. The idea is to use go, and any terraform library that allows me to “ease” my work. What I’m interested in is to use Nix as language instead of HCL/JSON to interact with plugins and manage resources.

Currently, correct me if I’m wrong, when a plugin is developed, once defined the various “Resources”, we interface through the HCL in a file.tf

What I want is to replace the HCL from the equation, and interact with it using nix. How feasible is this?

HCL is a fundamental part of the Terraform runtime, rather than a layer on top of it, so I think the best you could do without reimplementing what Terraform does is to take a strategy similar to CDK for Terraform, which works by running a program in some other language to generate a data structure, then translating that data structure into an HCL-based Terraform configuration, and then finally running Terraform against that configuration.

If you wish to use the Nix language at the same position in the stack as Terraform uses HCL, I think you’ll need to fork Terraform and alter the runtime to call into the Nix evaluation engine in all the places where Terraform calls into HCL for configuration evaluation. The evaluation steps are intertwined with the other processing because the configuration for one resource can potentially depend on the dynamic results of another, and so Terraform must evaluate the configuration for the first resource, take actions based on that resource, and only then evaluate the configuration for the second.

HCL is purpose-built to include features that Terraform needs for its work, so how easy that would be will depend on whether the Nix language has comparable features. I’m not very familiar with Nix myself, so I don’t know what sort of API it has for integrating its language deeply into another execution engine. Out of curiosity I did a little research myself, but so far only found discussions about the opposite: using a different language frontend on top of the Nix package manager, instead of the Nix language.

Thanks for your reply!
I guess that the best bet is using something like CDK. Remove the entire HCL part is definitely harderd than “transpile” Nix in Json.

Thanks again :smiley: