Terraform
Migrating data sources
This page explains how to migrate a data source from SDKv2 to the plugin framework.
Background
Data sources are read-only resource types that let Terraform reference external data. They do not create, update, or delete data and make no attempt to modify the underlying API. As a result, they implement a subset of the operations that resources do. Refer to Data sources in the framework documentation for details.
Some data sources implement a timeout for upstream API calls that take too long to respond. Refer to Timeouts in this guide to learn how to migrate data source timeouts to the framework.
Migrate a data source
In SDKv2, data sources are defined by the DataSourcesMap field on the
schema.Provider struct, which maps data source names (strings) to their
schema. Providers use the schema.Resource struct for resources and data
sources.
In the framework, you define data sources by adding them to the map returned by
your provider's DataSources method.
The DataSources method on your provider.Provider returns a slice of
functions that return types that implement the datasource.DataSource interface
for each data source your provider supports.
The following example shows a typical implementation of a data source in SDKv2.
SDKv2
func New() *schema.Provider {
    return &schema.Provider{
        DataSourcesMap:   map[string]*schema.Resource{
        /* ... */
},
In SDKv2, you define both resources and data sources with schema.Resource
structs. The following code shows a resource struct. For clarity, this example
omits fields that are not available for data sources.
SDKv2
schema.Resource {
    Schema:               map[string]*schema.Schema,
    Read:                 ReadFunc,
    ReadContext:          ReadContextFunc,
    ReadWithoutTimeout:   ReadContextFunc,
    DeprecationMessage:   string,
    Timeouts:             *ResourceTimeout,
    Description:          string,
}
The following code shows how you add a data source to your provider with the framework.
Framework
func (p *provider) DataSources(ctx context.Context) []func() datasource.DataSource {
    return []func() datasource.DataSource{
        /* ... */
    }
}
Like the resource.Resource interface,
datasource.DataSource
requires the Schema and Metadata methods. These methods work the same way
for data sources as they do for resources. The Read method is also required.
The Schema method returns a schema.Schema struct which defines your data
source's attributes.
The Metadata method returns a type name that you define.
The Read method implements the logic for writing into the Terraform state.
The following code shows how you define a datasource.DataSource which
implements these methods with the framework.
Framework
type dataSourceExample struct{}
func (d *dataSourceExample) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
    /* ... */
}
func (d *dataSourceExample) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
    /* ... */
}
func (d *dataSourceExample) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
    /* ... */
}
Migration notes
Because data sources are read-only, you only implement read functionality. Refer to the Read function documentation for details.
Examples
The following example shows an implementation of the DataSourcesMap field on
the provider schema with SDKv2.
SDKv2
func New() (*schema.Provider, error) {
    return &schema.Provider {
        DataSourcesMap: map[string]*schema.Resource {
            "example_datasource": exampleDataSource(),
            /* ... */
The following example shows how the ReadContext function and Schema are defined for
the exampleResource data source with SDKv2.
SDKv2
func exampleDataSource() *schema.Resource {
    return &schema.Resource{
        ReadContext: dataSourceRead,
        Schema: map[string]*schema.Schema{
            "example_attribute": {
                Type:        schema.TypeString,
                Required:    true,
            },
            /* ... */
        },
    }
}
The following example shows how the exampleDataSource data source is defined
with the framework after the migration.
Framework
func (p *provider) DataSources(context.Context) []func() datasource.DataSource {
    return []func() datasource.DataSource{
        func() datasource.DataSource {
            return &exampleDataSource{}
        },
    }
}
This code defines the methods for the exampleDataSource data source with the
framework.
Framework
func (d *exampleDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
    resp.TypeName = "example_datasource"
}
func (d *exampleDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
    resp.Schema = schema.Schema{
        Attributes: map[string]schema.Attribute{
            "example_attribute": schema.StringAttribute{
                Required:    true,
            },
            /* ... */
func (d *exampleDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
    /* ... */
}