---
page_title: 'Resources: Migrating from SDKv2 to the Framework'
description: >-
  Migrate a resource from SDKv2 to the plugin Framework.
---

# 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](/terraform/plugin/framework/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](/terraform/plugin/framework/migrating/resources/crud): The resource defines the logic to manage resources with Terraform.
- [Default](/terraform/plugin/framework/migrating/attributes-blocks/default-values): The resource specifies default values for attributes that are null within the configuration.
- [Import](/terraform/plugin/framework/migrating/resources/import): The resource defines the logic to add a resource to Terraform's state.
- [Plan modification](/terraform/plugin/framework/migrating/resources/plan-modification): The resource customizes the Terraform plan for known values or behaviors outside the practitioner's configuration.
- [State upgrade](/terraform/plugin/framework/migrating/resources/state-upgrade): The resource updates Terraform state information in advanced use cases.
- [Timeouts](/terraform/plugin/framework/migrating/resources/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 `Schema` field, which defines resource attributes
- Fields for resource lifecycle functions such as `Create` and `CreateContext`
- 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.

```go
func New() *schema.Provider {
    return &schema.Provider{
        ResourcesMap:   map[string]*schema.Resource {
            "resource_example": resourceExample(),
            /* ... */
        },
        /* ... */
    }
}
```

SDKv2 defines the `schema.Resource` struct as follows.

```go
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.

```go
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.

```go
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](/terraform/plugin/framework/migrating/resources/crud) 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.Resource` structs to define resources. These structs have a `Schema` field which holds a
`schema.Schema` to define the resource's attributes and behavior. In the Framework, you define a type that implements
the `resource.Resource` interface, which includes a `Schema` method 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 the `resource.Resource` interface. The resource interface contains the functions that define your resource's
CRUD operations.
- SDKv2 by default demotes certain resource schema definition and data consistency errors to only be visible as Terraform warning logs. After migration, these errors will always be visible to practitioners and prevent further Terraform operations. The [SDKv2 resource data consistency errors documentation](/terraform/plugin/sdkv2/resources/data-consistency-errors) discusses how to find these errors in SDKv2 resources and potential solutions **prior** to migrating. See the [CRUD - Resolving Data Consistency Errors](/terraform/plugin/framework/migrating/resources/crud#resolving-data-consistency-errors) section for Plugin Framework solutions **during** migration.

## 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`.

```go
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.

```go
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.

```go
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`.

```go
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"}...),
                },
            },
            /* ... */
        },
    }
}
```
