

Something that has helped me to better understand the plugin protocol and how the SDK works, is to set a breakpoint in the plugin SDK’s implementation of the GRPC interface (eg. If you make some changes to the plugin code, be sure to kill the running instance with Ctrl-C or a stop button in your debugger, recompile, rerun, and reset the environment variable to ensure the new changes have an effect. This instance will be reused for all subsequent Terraform commands which have the environment variable set. When the Terraform command completes, you will notice that the plugin stays running. Consult the documentation for your debugger for more details on what you can do. You can then step through line by line, see the value of variables, and evaluate expressions. If you set a breakpoint in resourceOrderRead, then run terraform apply, you will see the breakpoint being triggered in the debugger. The command below shows the required compiler options if invoking the Go compiler directly. Depending on your debugging tool, you might be able to do this and run it in one command automatically, for example delve has a dlv debug command, and IDEs such as GoLand have a Debug button which takes care of this. This ensures that the debugger can properly map between the compiled instructions and the source code. Secondly, we need to make sure that the plugin is compiled in “debug mode” or without optimisations enabled. "/hashicorp/terraform-provider-hashicups/hashicups"įlag.BoolVar(&debugMode, "debug", false, "set to true to run the provider with support for debuggers like delve")Įrr := plugin.Debug(context.Background(), "/edu/hashicups", opts) "/hashicorp/terraform-plugin-sdk/v2/plugin" "/hashicorp/terraform-plugin-sdk/v2/helper/schema" Your provider may already have this support, but if not, here is an example main.go that can be adapted:

This will start up the gRPC server without expecting the data to be passed immediately and print out information needed to tell Terraform to use this instance instead. To avoid this, we need to be able to pass a -debug flag and run plugin.Debug instead. Please execute the program that consumes these plugins, which will load any plugins automatically These are not meant to be executed directly. This is what plugin.Serve expects, and it will fail if run directly: $. It will pass it some data when it starts up to allow communication with TLS. When a Terraform command is run normally, Terraform Core will run the plugin in a subprocess and communicate with it via gRPC, where Terraform Core is a client and the plugin is a server. This means that in the main function, you can use a flag to optionally call plugin.Debug instead of plugin.Serve. The main functionįirstly, we need to make sure that the provider is set up for debugging. To demonstrate the process, I will use the HashiCups demo provider that HashiCorp use in their tutorials, but it should be easy to adapt this to any other provider using the Terraform plugin SDK.

Run the plugin directly inside the debugger as if it were any other Go program.Compile the plugin without optimisations.Make sure the main.go supports running the plugin in debug mode.I also went through this quick tip in a recent video, if you prefer to watch things instead of reading. This can also be beneficial if you are unfamiliar with the provider or the Terraform plugin SDK in general, as it will essentially take you on a guided tour of the code. However, using a debugger can give the best visibility into what’s happening in the provider and allow you to precisely trace the execution of the provider. Using the logs is probably the quickest of the three methods and can be sufficient for simpler issues. For example, using acceptance tests has the benefit of being able to commit the tests afterwards with little extra effort and having the assurance that there’s a test case to catch the bug in future. Which one of these to use depends on the situation, and each has its benefits. a debugger such as Delve either directly or via an IDE (I use Jetbrains’s GoLand but there are many options).logs to trace the behaviour (something that has become much easier in Terraform v0.15, thanks to being able to separate core vs provider logs).acceptance tests to exercise the provider and observe the results both through the test outcomes and outside of terraform.There are a few things you can use for debugging when working with Terraform providers: In doing so, I came across a quick tip for debugging that I’d like to share. Recently, we have been working with a large CDN and edge cloud platform, on improving and upgrading their Terraform provider.
