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) {
/* ... */
}