Plugin Basics

This page documents the basics of how the plugin system in Terraform works, and how to setup a basic development environment for plugin development if you're writing a Terraform plugin.

How it Works

Terraform providers and provisioners are provided via plugins. Each plugin exposes an implementation for a specific service, such as AWS, or provisioner, such as bash. Plugins are executed as a separate process and communicate with the main Terraform binary over an RPC interface.

More details are available in Plugin Internals.

The code within the binaries must adhere to certain interfaces. The network communication and RPC is handled automatically by higher-level Terraform libraries. The exact interface to implement is documented in its respective documentation section.

Installing a Plugin

To install a plugin distributed by a third party developer, place the binary (extracted from any containing zip file) in the third-party plugins directory.

Provider plugin binaries are named with the prefix terraform-provider-, while provisioner plugins have the prefix terraform-provisioner-. Both are placed in the same directory.

Developing a Plugin

Developing a plugin is simple. The only knowledge necessary to write a plugin is basic command-line skills and basic knowledge of the Go programming language.

Create a new Go project somewhere in your $GOPATH. If you're a GitHub user, we recommend creating the project in the directory $GOPATH/src/github.com/USERNAME/terraform-NAME, where USERNAME is your GitHub username and NAME is the name of the plugin you're developing. This structure is what Go expects and simplifies things down the road.

The NAME should either begin with provider- or provisioner-, depending on what kind of plugin it will be. The repository name will, by default, be the name of the binary produced by go install for your plugin package.

With the package directory made, create a main.go file. This project will be a binary so the package is "main":

package main

import (
    "github.com/hashicorp/terraform/plugin"
)

func main() {
    plugin.Serve(new(MyPlugin))
}

The name MyPlugin is a placeholder for the struct type that represents your plugin's implementation. This must implement either terraform.ResourceProvider or terraform.ResourceProvisioner, depending on the plugin type.

To test your plugin, the easiest method is to copy your terraform binary to $GOPATH/bin and ensure that this copy is the one being used for testing. terraform init will search for plugins within the same directory as the terraform binary, and $GOPATH/bin is the directory into which go install will place the plugin executable.

© 2018 HashiCorp
Licensed under the MPL 2.0 License.
https://www.terraform.io/docs/plugins/basics.html