I have implemented a kubernetes terraform provider which applies manifest files to k8s cluster. I have created .tf files also but when I run terraform init
it downloads plugins from terraform registry.
How can I make my plugin to run for terraform apply.
Debugging a TerraForm provider
Understanding the design
In order to do it, you first have to understand how Go builds apps, and then how terraform works with it.
Every terraform provider is a sort of
module
. In order to support an open, modular system, in almost any language, you need to be able to dynamically load modules and interact with them. Terraform is no exception.However, the go lang team long ago decided to compile to statically linked applications; any dependencies you have will be compiled into 1 single binary. Unlike in other native languages (like C, or C++), a
.dll
or.so
is not used; there is no dynamic library to load at runtime and thus, modularity becomes a whole other trick. This is done to avoid the notorious dll hell that was so common up until most modern systems included some kind of dependency management. And yes, it can still be an issue.Every terraform provider is its own mini RPC server. When terraform runs your provider, it actually starts a new process that is your provider, and connects to it through this RPC channel. Compounding the problem is that the lifetime of your provider process is very much ephemeral; potentially lasting no more and a few seconds. It's this process you need to connect to with your debugger
Normal debugging
Normally, you would directly spin-up your app, and it would load modules into application memory. That's why you can actually debug it, because your debugger knows how to find the exact memory address for your provider. However, you don't have this arrangement, and you need to do a remote debug session.
The conundrum
So, you don't load terraform directly, and even if you did, your
module
(a.k.a your provider) is in the memory space of an entirely different process; and that lasts no more than a few seconds, potentially.The solution
This code effectively creates an infinite sleep loop; but that's actually essential to solving the problem.
delve
to connect to this remote process using it's PID. This isn't as hard as it seems. Run this commands:dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient attach $(pgrep terraform-provider-artifactory)
The last argument gets thePID
for your provider and supplies it todelve
to connect. Immediately upon running this command, you're going to hit your break point. Please make sure to substituteterraform-provider-artifactory
for your provider nameconnected
totrue
. By doing so you change the loop predicate and it will exit this loop on the next iteration.