Terraform
- Plugin Framework
- v1.16.x (latest)
- No versions of this document exist before v1.15.x. Click below to redirect to the version homepage.
- v1.15.x
- v1.14.x
- v1.13.x
- v1.12.x
- v1.11.x
- v1.10.x
- v1.9.x
- v1.8.x
- v1.7.x
- v1.6.x
- v1.5.x
- v1.4.x
- v1.3.x
- v1.2.x
- v1.1.x
- v0.17.x
- v0.16.x
- v0.15.x
- v0.14.x
- v0.13.x
- v0.12.x
- v0.11.x
- v0.10.x
- v0.9.x
- v0.8.x
- v0.7.x
Resources
Resources are an abstraction that allow Terraform to manage infrastructure objects by defining create, read, update, and delete functionality that maps onto API operations. Resource schemas define what fields a resource has, give Terraform metadata about those fields, and define how the resource behaves. Refer to Resources in the Framework documentation for details.
This page explains how to migrate a resource's schema from SDKv2 to the plugin Framework. We also recommend reviewing these additional guides for resources throughout the migration:
- Create, Read, Update, and Delete functions: The resource defines the logic to manage resources with Terraform.
- Import: The resource defines the logic to add a resource to Terraform's state.
- Plan modification: The resource customizes the Terraform plan for known values or behaviors outside the practitioner's configuration.
- State upgrade: The resource updates Terraform state information in advanced use cases.
- Timeouts: The resource uses timeouts during create, read, update or delete operations.
SDKv2
In SDKv2, resources are defined by the ResourcesMap field in the schema.Provider struct, which maps resource names
(strings) to their schema. Each schema is a schema.Resource struct that includes:
- A
Schemafield, which defines resource attributes - Fields for resource lifecycle functions such as
CreateandCreateContext - Fields for functions to implement state upgrade (
StateUpgraders), import (Importer), and customize diff (CustomizeDiff)
The following code shows a basic implementation of resource schema with SDKv2.
func New() *schema.Provider {
return &schema.Provider{
ResourcesMap: map[string]*schema.Resource {
"resource_example": resourceExample(),
/* ... */
},
/* ... */
}
}
SDKv2 defines the schema.Resource struct as follows.
schema.Resource{
Schema map[string]*Schema
SchemaVersion int
MigrateState StateMigrateFunc
StateUpgraders []StateUpgrader
Create CreateFunc
Read ReadFunc
Update UpdateFunc
Delete DeleteFunc
Exists ExistsFunc
CreateContext CreateContextFunc
ReadContext ReadContextFunc
UpdateContext UpdateContextFunc
DeleteContext DeleteContextFunc
CreateWithoutTimeout CreateContextFunc
ReadWithoutTimeout ReadContextFunc
UpdateWithoutTimeout UpdateContextFunc
DeleteWithoutTimeout DeleteContextFunc
CustomizeDiff CustomizeDiffFunc
Importer *ResourceImporter
DeprecationMessage string
Timeouts *ResourceTimeout
Description string
UseJSONNumber bool
}
Framework
In the Framework, you define your provider's resources by adding them to your provider's Resources method.
The Resources method on your provider.Provider returns a slice of functions that return types that
implement the resource.Resource interface for each resource your provider supports.
The following code shows how you add a resource to your provider with the Framework.
func (p *provider) Resources(ctx context.Context) []func() resource.Resource {
return []func() resource.Resource{
func() resource.Resource {
return resourceTypeExample{}
},
}
}
The resource.Resource interface requires Metadata, Schema, Create, Read, Update, and Delete methods.
The Schema method returns a schema.Schema struct which defines your resource's attributes.
The Metadata method returns a type name that you define.
The following code shows how you define a resource.Resource which implements these methods with the
Framework.
type resourceExample struct{}
func (r *resourceExample) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
/* ... */
}
func (r *resourceExample) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
/* ... */
}
func (r *resourceExample) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
/* ... */
}
func (r *resourceExample) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
/* ... */
}
func (r *resourceExample) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
/* ... */
}
func (r *resourceExample) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
/* ... */
}
Refer to the Resources - CRUD functions page in this guide to learn how to
implement the resource.Resource interface.
Migration Notes
Remember the following differences between SDKv2 and the Framework when completing the migration.
- SDKv2 uses
schema.Resourcestructs to define resources. These structs have aSchemafield which holds aschema.Schemato define the resource's attributes and behavior. In the Framework, you define a type that implements theresource.Resourceinterface, which includes aSchemamethod that returns your resource's schema. - SDKv2 implements a resource's CRUD operations as functions on the
schema.Resource. In the Framework, you define a type that implements theresource.Resourceinterface. The resource interface contains the functions that define your resource's CRUD operations.
Example
SDKv2
In SDKv2, the ResourcesMap field on the schema.Provider struct holds a map[string]*schemaResource. A typical
pattern is to implement a function that returns schema.Resource.
func New() (*schema.Provider, error) {
return &schema.Provider {
ResourcesMap: map[string]*schema.Resource {
"example_resource": exampleResource(),
/* ... */
This code defines the example_resource resource by mapping the resource name to the exampleResource struct.
func exampleResource() *schema.Resource {
return &schema.Resource{
CreateContext: createResource,
DeleteContext: deleteResource,
ReadContext: readResource,
Schema: map[string]*schema.Schema{
"attribute": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{'a', 'b'}, false)),
},
/* ... */
Framework
The following shows the same section of provider code after the migration.
func (p *exampleProvider) Resources(_ context.Context) []func() resource.Resource {
return []func() resource.Resource{
func() resource.Resource {
return &exampleResource{}
},
/* ... */
}
}
This code defines the Schema and Metadata methods for the Resource.
func (r *exampleResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = "example_resource"
}
func (r *exampleResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
// Required attributes
"attribute": schema.StringAttribute{
Required: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
Validators: []validator.String{
stringvalidator.OneOf([]string{'a', 'b'}...),
},
/* ... */
},
}
}