---
page_title: 'Provider: Migrating from SDKv2 to the Framework'
description: >-
  Migrate a provider definition and schema from SDKv2 to the plugin Framework.
---

# Provider

Providers are Terraform plugins that define resources and data sources for practitioners to use. You serve your
providers with a provider server so they can interact with Terraform.

This page explains how to migrate a provider server, definition, and schema from SDKv2 to the plugin Framework.

## Serving the Provider

You must update your provider's `main.go` file to serve Framework providers. Refer to [Provider Servers](/terraform/plugin/framework/provider-servers) in the Framework documentation for details.

<Tip>

To iteratively migrate individual resources and data sources, refer to [muxing](/terraform/plugin/framework/migrating/muxing) for the `main.go` implementation instead. The latter [provider definition](#provider-definition) and [provider schema](#provider-schema) sections are still applicable when muxing.

</Tip>

### SDKv2

In SDKv2, the provider package's `main` function serves the provider by calling `plugin.Serve`.

The following code shows a basic implementation for serving an SDKv2 provider.

```go
func main() {
    plugin.Serve(
        &plugin.ServeOpts{
            ProviderFunc: provider.New,
            ProviderAddr: "registry.terraform.io/<namespace>/<provider_name>",
        },
    )
}
```

### Framework

In the Framework, you serve your provider by calling `providerserver.Serve` in your provider package's `main` function.
Refer to [Provider Servers](/terraform/plugin/framework/provider-servers) in the Framework documentation for details.

The following code shows an equivalent implementation for serving a provider in the Framework.

```go
func main() {
    err := providerserver.Serve(
        context.Background(),
        provider.New,
        providerserver.ServeOpts{
            Address: "registry.terraform.io/<namespace>/<provider_name>",
        },
    )

    if err != nil {
        log.Fatal(err)
    }
}
```

## Provider Definition

Providers built with SDKv2 use a `schema.Provider` struct to define their behavior, while Framework providers use a
type that implements the `provider.Provider` interface, which you must define.  Refer to [Providers](/terraform/plugin/framework/providers) in the Framework documentation for details.

### SDKv2

The [`ProviderFunc`](/terraform/plugin/framework/migrating/providers#serving-the-provider) field on
`plugin.ServeOpts` requires a pointer to `schema.Provider`. This is typically satisfied by calling a function that
returns a pointer to `schema.Provider`.

The `ResourcesMap` and `DataSourcesMap` fields each contain a map of strings to functions that each return a pointer
to a `schema.Resource` struct.

The following example shows a basic implementation of an SDKv2 provider.

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

### Framework

In the Framework, the second argument to your `provider.Serve` function requires a function that returns a type
satisfying the `provider.Provider` interface.

The following code shows a typical implementation. In this implementation, the `Resources` method returns a slice
of functions that return types that implement the `resource.Resource` interface. The `DataSources` method returns a
slice of functions that return types that implement the `datasource.DataSource` interface.
Refer to the [Resources](/terraform/plugin/framework/migrating/resources) and
[Data Sources](/terraform/plugin/framework/migrating/data-sources) pages in this guide to implement these functions for your
provider.

```go
type exampleCloudProvider struct {
}

func New() provider.Provider {
    return &exampleCloudProvider{}
}

func (p *exampleCloudProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) {
	resp.TypeName = "examplecloud"
}

func (p *exampleCloudProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) {
    resp.Schema = schema.Schema{}
}

func (p *exampleCloudProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
}

func (p *exampleCloudProvider) Resources(ctx context.Context) []func() resource.Resource {
    return []func() resource.Resource {
        func() resource.Resource {
            return resourceExample{}
        },
    }
}

func (p *exampleCloudProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
    return []func() datasource.DataSource {
        func() datasource.DataSource {
            return dataSourceExample{}
        },
    }
}
```

### Migration Notes

Remember the following differences between SDKv2 and the Framework when completing the migration.

- In SDKv2, your provider's `New` function returns a `schema.Provider` struct. In the Framework, `New` returns a type
that you define which satisfies the `provider.Provider` interface.
- In SDKv2, `Schema` is a field on `schema.Provider` that contains `map[string]*schema.Schema`, which maps attribute
names to `schema.Schema` structs. In the Framework, `Schema` is a method you define on your provider's
`provider.Provider` interface that returns your provider's `schema.Schema` struct.
- In SDKv2, `ConfigureContextFunc` is a field on `schema.Provider` containing a function that configures the provider.
In the Framework, `Configure` is a function you define on your provider that configures your provider.
- In SDKv2, `ResourcesMap` is a field on `schema.Provider` containing `map[string]*schema.Resource`, which maps resource
names to `schema.Resource` structs. In the Framework, `Resources` is a method you define on your provider that
returns `[]func() resource.Resource`, which creates resource types that you define, which satisfy the
`resource.Resource` interface.
- In SDKv2, `DataSourcesMap` is a field on `schema.Provider` containing  `map[string]*schema.Resource`, which maps data
source names to `schema.Resource` structs (data sources and resources both use `schema.Resource`). In the Framework,
`DataSources` is a method you define on your provider that returns `[]func() datasource.DataSource`, which
creates data source types that you define, which satisfy the `datasource.DataSource` interface.

### Example

#### SDKv2

The following example shows how to set up a provider schema, configuration, resources, and data sources using SDKv2.

```go
func New() (*schema.Provider, error) {
    return &schema.Provider{
        Schema: map[string]*schema.Schema{
            "attribute": {
                /* ... */
            },
        },
        ConfigureContextFunc: configureProvider,
        ResourcesMap: map[string]*schema.Resource{
            "exampleResource": exampleResource(),
            /* ... */
        },
        DataSourcesMap: map[string]*schema.Resource{
            "exampleDataSource": exampleDataSource(),
            /* ... */
        },
    }, nil
}
```

#### Framework

The following shows the same section of provider code after the migration.

```go
var _ provider.Provider = (*exampleProvider)(nil)

func New() provider.Provider {
    return &exampleProvider{}
}

func (p *exampleProvider) Resources(_ context.Context) []func() resource.Resource {
    return []func() resource.Resource{
        func() resource.Resource {
            return &exampleResource{}
        },
        /* ... */
    }
}

func (p *exampleProvider) DataSources(_ context.Context) []func() datasource.DataSource {
    return []func() datasource.DataSource{
        func() datasource.DataSource {
            return &exampleDataSource{}
        },
        /* ... */
    }
}

func (p *exampleProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {
    resp.Schema = schema.Schema{
        Attributes: map[string]schema.Attribute{
            "attribute": schema.SingleNestedBlock{
                /* ... */
            },
        },
    }
}

func (p *exampleProvider) Metadata(_ context.Context, _ provider.MetadataRequest, resp *provider.MetadataResponse) {
	resp.TypeName = "example"
}

func (p *exampleProvider) Configure(_ context.Context, _ provider.ConfigureRequest, resp *provider.ConfigureResponse) {
    /* ... */
}
```

## Provider Schema

A provider schema defines the attributes and behaviors of the provider itself. For example, a provider that connects to
a third-party API may define attributes for the base URL or a required authentication token.

### SDKv2

In SDKv2, you implement a provider Schema by populating the `Schema` field on the `schema.Provider` struct. The `Schema`
field contains a `map[string]*schema.Schema`. Each map entry represents the name of the attribute and pointer to a
`schema.Schema` struct that defines that attribute's behavior.

The following example defines the provider schema in the `Schema` field within the `schema.Provider` struct.

```go
func New() *schema.Provider {
    return &schema.Provider{
        Schema: map[string]*schema.Schema{
            /* ... */
        },
```

### Framework

In the Framework, the `Schema` method returns the provider schema. The `Schema` method is part of the
`provider.Provider` interface that your provider must implement. `Schema` returns a struct containing fields for
`Attributes` and `Blocks`. These `Attributes` and `Blocks` contain `map[string]schema.Attribute` and
`map[string]schema.Block`, respectively. Refer to [Providers - Schema](/terraform/plugin/framework/providers#schema) in the
Framework documentation for details.

The following code shows the `Schema` method, which returns the provider schema.

```go
func (p *ExampleCloudProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) {
    resp.Schema = schema.Schema{
        /* ... */
    }
}
```

Refer to the [Attributes](/terraform/plugin/framework/migrating/attributes-blocks/attribute-schema) and
[Blocks](/terraform/plugin/framework/migrating/attributes-blocks/blocks) pages in this migration guide to learn how to migrate
those fields to the Framework.

### Migration Notes

Remember the following differences between SDKv2 and the Framework when completing the migration.

- In SDKv2, `schema.Schema` is a struct that defines attributes and behaviors (e.g., `Type`, `Optional`). In the
Framework `schema.Schema` is a struct that includes attributes and blocks.

### Example

This example shows how to use a nested block and a nested attribute for the SDKv2 and Framework examples,
respectively. Refer to the
[Blocks with Computed Fields](/terraform/plugin/framework/migrating/attributes-blocks/blocks-computed) page in this guide for more
details.

#### SDKv2

The following example shows the configuration of the `example_attribute` attribute for the  provider's `example_block` configuration block.

```go
Schema: map[string]*schema.Schema{
    "example_block": {
        Type:     schema.TypeList,
        Optional: true,
        MaxItems: 1,
        Elem: &schema.Resource{
            Schema: map[string]*schema.Schema{
                "example_attribute": {
                    Type:             schema.TypeString,
                    Optional:         true,
                    ValidateDiagFunc: validation.ToDiagFunc(validation.IsURLWithScheme(SupportedProxySchemesStr())),
                    ConflictsWith:    []string{"example_block.0.another_attribute"},
                },
                /* ... */
```

#### Framework

The following shows the same section of provider code after the migration.

This code implements the `example_attribute` attribute for the `example_Block` block with the Framework.

```go
func (p *exampleProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {
    resp.Schema = schema.Schema{
    	/*...*/
        Blocks: map[string]schema.Block{
            "example_block": schema.ListNestedBlock{
                NestedObject: schema.NestedBlockObject{
			Attributes: map[string]schema.Attribute{
			    "example_attribute": schema.StringAttribute{
				Optional: true,
				Validators: []validator.String{
				    attribute_validator.UrlWithScheme(supportedProxySchemesStr()...),
				    stringvalidator.ConflictsWith(path.MatchRelative().AtParent().AtName("another_attribute")),
				},
			},
		},
		Validators: []validator.List{
			    listvalidator.SizeAtMost(1),
		},
```
