Comprehensive documentation and best practices for building Terraform providers with terraform-plugin-framework (v1.17.0). Covers providers, resources, schemas, types, validators, testing, and common pitfalls.
Overall
score
97%
Comprehensive documentation for building Terraform providers with github.com/hashicorp/terraform-plugin-framework (v1.17.0).
terraform-plugin-framework is the recommended Go SDK for building Terraform providers. It provides a structured, type-safe approach to implementing providers, resources, data sources, functions, and other Terraform capabilities.
Key Benefits:
When to Use:
When NOT to Use:
Provider (metadata, config, resources, data sources, functions)
├── Resources (CRUD operations, state management)
│ └── Schema (attributes, validators, plan modifiers)
├── Data Sources (read operations)
│ └── Schema (attributes, validators)
├── Functions (custom Terraform functions)
└── Actions & Ephemeral Resources (session-scoped operations)Protocol Flow:
This documentation is organized by framework capability:
The tile includes best practices rules (automatically loaded by agents):
// 1. Define resource type implementing resource.Resource
type PetResource struct {
client *api.Client
}
// 2. Implement required methods
func (r *PetResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_pet"
}
func (r *PetResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
// Define schema with attributes
}
func (r *PetResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
// Implement create logic
// ALWAYS check resp.Diagnostics.HasError()
}
// Similar for Read, Update, DeleteKey Points:
resp.Diagnostics.HasError() after operationstypes.String, types.Int64, etc.) for attributesreq.State.Get() and resp.State.Set()schema.Schema{
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"name": schema.StringAttribute{
Required: true,
Validators: []validator.String{
stringvalidator.LengthAtLeast(1),
},
},
},
}Key Points:
Required, Optional, Computed determine attribute behaviorUseStateForUnknown() for computed attributes in Create⚠️ Not Checking Diagnostics: Always check resp.Diagnostics.HasError() before proceeding. Continuing after errors leads to panics.
⚠️ Missing UseStateForUnknown: Computed attributes without UseStateForUnknown() in Create operations show as "known after apply" unnecessarily, causing unnecessary replaces.
⚠️ Type Conversion Errors: Framework types (types.String) are not Go primitives. Use .ValueString(), .ValueInt64(), etc. for conversion. Check .IsNull() and .IsUnknown() first.
⚠️ State Management: Forgetting to call resp.State.Set() at the end of CRUD operations means state isn't saved, causing Terraform to think resource doesn't exist.
⚠️ Null vs Unknown: Null = explicitly no value (set to null). Unknown = value not yet known (depends on another resource). Handle both cases.
See Rules directory for comprehensive pitfalls and best practices.
| Topic | Documentation |
|---|---|
| First Provider | Quick Start |
| Provider Setup | Provider |
| Resource CRUD | Resources |
| Schema Design | Schema System |
| Type System | Type System |
| Validation | Validators |
| Plan Modifiers | Plan Modifiers |
| Testing | Testing |
This documentation covers terraform-plugin-framework v1.17.0. For the latest version, see pkg.go.dev.