DEV Community

Devang Tomar
Devang Tomar

Posted on • Originally published at Medium on

How to Write Your Own Terraform Provider: A Step-by-Step Guide 🛠️ ️

Terraform has become the go-to tool for infrastructure as code (IaC), enabling developers to define and provision infrastructure using a declarative configuration language. While Terraform supports a wide range of cloud providers and services out of the box, there may come a time when you need to manage a custom resource or integrate with a proprietary API. That’s where writing your own Terraform provider comes in! 🌟

In this article, we’ll walk through the process of creating your very own Terraform provider from scratch. Whether you’re managing a niche cloud service or an internal tool, this guide will help you get started. Let’s dive in! 💻

🤔 Why Write a Custom Terraform Provider?

Before we jump into the *how*, let’s talk about the *why*. Here are a few reasons you might want to create your own Terraform provider:

  1. Custom Resources : You have a unique service or tool that isn’t supported by existing providers.
  2. Proprietary APIs : Your organization uses internal APIs that need to be managed as infrastructure.
  3. Extending Terraform : You want to add functionality to Terraform that aligns with your specific workflows.

If any of these resonate with you, it’s time to roll up your sleeves and start building! 🛠️

🧰 Prerequisites

Before we begin, make sure you have the following tools installed:

  1. Go (Golang): Terraform providers are written in Go. Install it from golang.org.
  2. Terraform : You’ll need Terraform installed to test your provider. Download it from terraform.io.
  3. Git : For version control and managing your provider’s code.

🚀 Step 1: Set Up Your Go Environment

First, let’s set up your Go workspace. Create a new directory for your provider and initialize a Go module:

mkdir terraform-provider-myprovider
cd terraform-provider-myprovider
go mod init github.com/yourusername/terraform-provider-myprovider
Enter fullscreen mode Exit fullscreen mode

This will create a go.mod file, which manages your project’s dependencies.

🛠️ Step 2: Create the Provider Skeleton

Terraform providers follow a specific structure. Start by creating the basic files and directories:

  1. Create the main.go file: This is the entry point for your provider.
package main

import (
    "github.com/hashicorp/terraform-plugin-sdk/v2/plugin"
    "github.com/yourusername/terraform-provider-myprovider/myprovider"
)

func main() {
    plugin.Serve(&plugin.ServeOpts{
        ProviderFunc: myprovider.Provider,
    })
}
Enter fullscreen mode Exit fullscreen mode
  1. Create the provider file: In a new directory called myprovider, create a file named provider.go.
package myprovider

import (
    "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func Provider() *schema.Provider {
    return &schema.Provider{
        ResourcesMap: map[string]*schema.Resource{},
        DataSourcesMap: map[string]*schema.Resource{},
    }
}
Enter fullscreen mode Exit fullscreen mode

This sets up the basic structure of your provider. Right now, it doesn’t do much, but we’ll add resources and data sources soon.

🔧 Step 3: Define Your First Resource

A Terraform provider is useless without resources. Let’s define a simple resource. For example, let’s say we’re creating a provider to manage “widgets” in a fictional API.

  1. Create a resource file: In the myprovider directory, create a file named resource_widget.go.
package myprovider

import (
    "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceWidget() *schema.Resource {
    return &schema.Resource{
        Create: resourceWidgetCreate,
        Read: resourceWidgetRead,
        Update: resourceWidgetUpdate,
        Delete: resourceWidgetDelete,

        Schema: map[string]*schema.Schema{
            "name": {
                Type: schema.TypeString,
                Required: true,
            },
            "description": {
                Type: schema.TypeString,
                Optional: true,
            },
        },
    }
}

func resourceWidgetCreate(d *schema.ResourceData, m interface{}) error {
    // Implement logic to create a widget.
    d.SetId("widget-id") // Set a dummy ID for now.
    return nil
}

func resourceWidgetRead(d *schema.ResourceData, m interface{}) error {
    // Implement logic to read a widget.
    return nil
}

func resourceWidgetUpdate(d *schema.ResourceData, m interface{}) error {
    // Implement logic to update a widget.
    return nil
}

func resourceWidgetDelete(d *schema.ResourceData, m interface{}) error {
    // Implement logic to delete a widget.
    return nil
}
Enter fullscreen mode Exit fullscreen mode
  1. Register the resource: Update the provider.go file to include the new resource.
func Provider() *schema.Provider {
    return &schema.Provider{
        ResourcesMap: map[string]*schema.Resource{
            "myprovider_widget": resourceWidget(),
        },
        DataSourcesMap: map[string]*schema.Resource{},
    }
}
Enter fullscreen mode Exit fullscreen mode

🧪 Step 4: Test Your Provider

Now that you’ve defined a resource, it’s time to test your provider. First, build the provider:

go build -o terraform-provider-myprovider
Enter fullscreen mode Exit fullscreen mode

Next, create a Terraform configuration file (main.tf) to test the provider:

provider "myprovider" {}

resource "myprovider_widget" "example" {
  name = "example-widget"
  description = "This is an example widget."
}
Enter fullscreen mode Exit fullscreen mode

Finally, initialize and apply your Terraform configuration:

terraform init
terraform apply
Enter fullscreen mode Exit fullscreen mode

🚀 Step 5: Publish and Share Your Provider

Once your provider is working, you can publish it to the Terraform Registry or share it with your team. To publish it:

  1. Tag your release: Use Git to tag your release.
git tag v1.0.0
git push origin v1.0.0
Enter fullscreen mode Exit fullscreen mode
  1. Submit to the Terraform Registry: Follow the Terraform Registry documentation to publish your provider.

🎉 Congratulations! You’ve Built a Terraform Provider!

Writing a custom Terraform provider might seem daunting at first, but once you break it down into steps, it’s entirely manageable. By following this guide, you’ve learned how to:

  • Set up a Go project for your provider.
  • Define resources and data sources.
  • Test and publish your provider.

Top comments (0)