Use when generating a Terraform provider from an OpenAPI spec with Speakeasy. Covers entity annotations, CRUD mapping, type inference, workflow configuration, and publishing. Triggers on "terraform provider", "generate terraform", "create terraform provider", "CRUD mapping", "x-speakeasy-entity", "terraform resource", "terraform registry".
Use when generating a Terraform provider from an OpenAPI spec with Speakeasy. Covers entity annotations, CRUD mapping, type inference, workflow configuration, and publishing. Triggers on "terraform provider", "generate terraform", "create terraform provider", "CRUD mapping", "x-speakeasy-entity", "terraform resource", "terraform registry".
license
Apache-2.0
generate-terraform-provider
Generate a Terraform provider from an OpenAPI specification using the Speakeasy CLI. This skill covers the full lifecycle: annotating your spec with entity metadata, mapping CRUD operations, generating the provider, configuring workflows, and publishing to the Terraform Registry.
The customization guide covers entity mapping placement, multi-operation resources, async polling, property customization, plan modification, validation, and state upgraders.
When to Use
Generating a new Terraform provider from an OpenAPI spec
Annotating an OpenAPI spec with x-speakeasy-entity and x-speakeasy-entity-operation
Mapping API operations to Terraform CRUD methods
Understanding Terraform type inference from OpenAPI schemas
Configuring workflow.yaml for Terraform provider generation
Data sources (list): For list endpoints (GET /resources), use a separate plural entity name with #read (e.g., Pets#read). Do NOT use #list -- it is not a valid operation type.
Terraform Type Inference
Speakeasy infers Terraform schema types from the OpenAPI spec automatically:
Rule
Condition
Terraform Attribute
Required
Property is required in CREATE request body
Required: true
Optional
Property is not required in CREATE request body
Optional: true
Computed
Property appears in response but not in CREATE request
Computed: true
ForceNew
Property exists in CREATE request but not in UPDATE request
ForceNew (forces resource recreation)
Enum validation
Property defined as enum
Validator added for runtime checks
Every parameter needed for READ, UPDATE, or DELETE must either appear in the CREATE response or be required in the CREATE request.
Example
Full workflow: Petstore provider
# 1. Ensure your spec has entity annotations (see above)# 2. Generate the provider
speakeasy quickstart --skip-interactive --output console \
-s ./openapi.yaml \
-t terraform \
-n Petstore \
-p petstore
# 3. Build and testcd terraform-provider-petstore
go build ./...
go test ./...
# 4. After spec changes, regenerate
speakeasy run --output console
Name the repository terraform-provider-XXX, where XXX is the provider type name. The provider type name should be lowercase alphanumeric ([a-z][a-z0-9]), though hyphens and underscores are permitted.
Entity naming
Use PascalCase for entity names so they translate correctly to Terraform's underscore naming:
Entity Name
Terraform Resource
Pet
petstore_pet
GatewayControlPlane
konnect_gateway_control_plane
MeshControlPlane
konnect_mesh_control_plane
For list data sources, use the plural PascalCase form (e.g., Pets).
Resource Importing
Generated providers support importing existing resources into Terraform state.
Simple keys
For resources with a single ID field:
terraform import petstore_pet.my_pet my_pet_id
Composite keys
For resources with multiple ID fields, pass a JSON-encoded object:
After registration, releases auto-publish when tags are pushed.
Beta Provider Pattern
For large APIs, maintain separate stable and beta providers:
Stable: terraform-provider-{name} with semver (x.y.z)
Beta: terraform-provider-{name}-beta with 0.x versioning
Users can install both simultaneously. When beta features mature, graduate them to the stable provider. To set up a beta provider, create a separate terraform-provider-{name}-beta repository with its own gen.yaml using 0.x versioning, and publish it alongside the stable provider.