What is a Terraform Provider

A Terraform provider is a plugin that extends Terraform, allowing it to manage external resources such as cloud services. It serves as a mediator between Terraform and external APIs, using the Terraform Plugin Protocol (opens in a new tab) for communication.

Terraform providers, built with the terraform-plugin-framework (opens in a new tab), include:

  1. Resources and Data Sources: described using a Terraform Type Schema, which is a map[string]Attribute, where an Attribute could be Primitive, Composite, or List.
  2. Create, Read, Update and Delete methods: the interface through which the provider interacts with an external resource (usually an API) to reconcile a desired terraform specification with the actual state of the resource.
  3. Plan Validators: defined to enable the validation of a desired specification at Plan-time, without making API calls to the external resource.
  4. Plan Modifiers: defined to enable custom semantics around the Terraform Type Schema, and how it is reconciled with the external state to make a Plan.
  5. Resource imports: defined to enable Terraform Specifications to be generated from existing resources.

A simple CRUD example

Let’s explore how to define a resource and map API operations to Terraform methods using annotations for CRUD actions.

Defining a Resource

Use x-speakeasy-entity to define a resource that you want to use terraform to manage.


Mapping API Operations to Resources Methods

An OpenAPI specification tracks a large list of Operation objects (opens in a new tab).

For a Terraform Provider generated by Speakeasy, the key element is the the x-speakeasy-entity-operation annotation. This annotation clarifies the purpose of each operation in terms of how it affects the associated remote entity.

openapi.yaml
/drinks:
post:
x-speakeasy-entity-operation: Drink#create
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/Drink"
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/Drink"
/drinks/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: string
get:
x-speakeasy-entity-operation: Drink#read
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/Drink"
post:
x-speakeasy-entity-operation: Drink#update
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/Drink"
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/Drink"
delete:
x-speakeasy-entity-operation: Drink#delete
responses:
"202":
description: OK
components:
schemas:
Drink:
x-speakeasy-entity: Drink
type: object
properties:
name:
description: The name of the drink.
type: string
examples:
- Old Fashioned
- Manhattan
- Negroni
type:
$ref: "#/components/schemas/DrinkType"
price:
description: The price of one unit of the drink in US cents.
type: number
examples:
- 1000 # $10.00
- 1200 # $12.00
- 1500 # $15.00
required:
- name
- price

Managing Complex API Semantics with Speakeasy

APIs can have unique semantics not fully described by OpenAPI specs. To address this we have:

  1. Inference Rules: Automatically derive most API semantics from the OpenAPI spec, with the exception of the x-speakeasy-entity-operation annotation.
  2. OpenAPI Extensions: For more complex cases, use extensions to provide detailed configurations. These extensions are documented in the Terraform Extensions section of this documentation.
  3. Support: Our engineering team continually updates inference rules and extensions to accommodate new API patterns.

Read more in our documentation here, or view more examples here.