Create Your Terraform Provider From OpenAPI / Swagger

Introduction

Terraform is an infrastructure-as-code tool that manages cloud infrastructure via API calls using providers. Creating and maintaining these providers, typically written in Go, requires specialized skills and frequent updates to accommodate API changes.

Speakeasy simplifies this process by generating Terraform providers directly from OpenAPI specifications. This eliminates the need for Go expertise, ensures providers remain up-to-date, and reduces the complexity of developing and maintaining providers for cloud environments.

For more details refer to the Terraform support matrix.

1. Prerequisites

To get started with creating the Speakeasy Terraform provider, you need:

Spec FormatSupported
OpenAPI 3.0
OpenAPI 3.1
JSON Schema
Postman Collection🔜
Success Icon

TIP

If you are using an unsupported spec format, use these tools to help you convert to a supported format:

2. Add Annotations

Annotate objects representing Terraform entities with x-speakeasy-entity to determine their inclusion in the Terraform provider.

paths:
/pet:
post:
...
x-speakeasy-entity-operation: Pet#create
...
Pet:
x-speakeasy-entity: Pet
...

Terraform Usage:

resource "petstore_pet" "myPet" {
...
}

Speakeasy infers Terraform types from your JSON schema, focusing on the semantics of the CREATE and UPDATE requests and responses. You don’t need to define any specific Terraform types in your OpenAPI spec.

  1. Required vs. Optional: If a property is required in the CREATE request body, it’s marked as Required: true; otherwise, it’s Optional: true.
  2. Computed Properties: Properties that appear in a response body but are absent from the CREATE request are marked as Computed: true. This indicates that Terraform will compute the properties’ values.
  3. The ForceNew Property: If a property exists in the CREATE request but is not present in the UPDATE request, it’s labeled ForceNew.
  4. Enum Validation: When an attribute is defined as an enum, Speakeasy configures a Validator for runtime type checks. This ensures that all request properties precisely match one of the enumerated values.
  5. READ, UPDATE, and DELETE Dependencies: Every parameter essential for READ, UPDATE, or DELETE operations must either be part of the CREATE API response body or be consistently required in the CREATE API request. This ensures that all necessary parameters are available for these operations.
Success Icon

TIP

Use additional x-speakeasy annotations to customize your provider as necessary.

4. Enhance Generated Documentation

Speakeasy helps you autogenerate documentation using the HashiCorp terraform-plugin-docs tools and packages. For best results, we recommend:

  1. Include Descriptions: Ensure your OpenAPI spec contains detailed descriptions of resources, attributes, and operations. Clear and concise descriptions help users understand the purpose and use of each component.
  2. Provide Examples: Use examples in your OpenAPI spec to illustrate how resources and attributes should be configured. Speakeasy leverages these examples to generate usage snippets that users can refer to when starting with your provider.

The Swagger Pet Store generates a usage snippet for the pet resource like the following:

"petstore_pet" "my_pet" {
id = 10
name = "doggie"
photo_urls = [
"...",
]
}.

5. Generate Terraform

  • Run the Speakeasy quickstart command:
speakeasy quickstart
  • Follow the interactive guide and provide the necessary information when prompted, including the path to spec. Make sure to choose terraform as the language of choice. Once you’ve finished the quickstart, you can regenerate the Terraform provider at any point by running speakeasy run.

Frequently Asked Questions

Do the generated Terraform providers support the ability to import resources?

Yes, generated Terraform providers do support the ability to import resources. However, there are specific prerequisites and considerations to keep in mind:

Prerequisites

  1. API Specification: It is essential to have an annotated and type-complete API operation defined for reading each resource in the OpenAPI specification. Tag the operation with x-speakeasy-entity-operation: MyEntity#read.

  2. Comprehensive READ Operation: If any attribute of a resource is not defined in the READ API, Terraform will set that attribute to null during the import process.

Simple Keys

A simple key is a single required ID field and is directly exposed to terraform import operations. For example, if the pet resource has a single id field, the import command will look like this: terraform import petstore_pet.my_pet my_pet_id.

Handling Composite Keys

Speakeasy natively supports direct import for resources with multiple ID fields. Speakeasy generates code that supports import syntax through a user providing a JSON-encoded object with all required parameters defined. Documentation, and appropriate error messages if this syntax isn’t followed will also be generated.

Import Composite Keys by block

An import block is a way to import a resource into the Terraform state by generating a Terraform specification. Using a composite key, the import block will look like this:

test.tf
import {
id = jsonencode({
primary_key_one: "9cedad30-2a8a-40f7-9d65-4fabb04e54ff"
primary_key_two: "e20c40a0-40e8-49ac-b5d0-6e2f41f9e66f"
})
to = my_test_resource.my_example
}
terraform plan -generate-config-out=generated.tf

Import composite keys by CLI

To import a resource with composite keys using the Terraform CLI, you can use the terraform import command:

terraform import my_test_resource.my_example '{ "primary_key_one": "9cedad30-2a8a-40f7-9d65-4fabb04e54ff", "primary_key_two": "e20c40a0-40e8-49ac-b5d0-6e2f41f9e66f" }'