Data Sources
Data sources are an abstraction that allow Terraform to reference external data. Unlike managed resources, Terraform does not manage the lifecycle of the resource or data. Data sources are intended to have no side-effects.
This page describes the basic implementation details required for supporting a data source within the provider. Further documentation is available for deeper data source concepts:
- Configure data sources with provider-level data types or clients.
- Validate practitioner configuration against acceptable values.
- Timeouts in practitioner configuration for use in a data source read function.
Define Data Source Type
Implement the datasource.DataSource
interface. Each of the methods is described in more detail below.
In this example, a data source named examplecloud_thing
with hardcoded behavior is defined:
// Ensure the implementation satisfies the desired interfaces.var _ datasource.DataSource = &ThingDataSource{} type ThingDataSource struct {} type ThingDataSourceModel struct { ExampleAttribute types.String `tfsdk:"example_attribute"` ID types.String `tfsdk:"id"`} func (d *ThingDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { resp.TypeName = "examplecloud_thing"} func (d *ThingDataSource) 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, }, "id": schema.StringAttribute{ Computed: true, }, }, }} func (d *ThingDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { var data ThingDataSourceModel // Read Terraform configuration data into the model resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) // Typically data sources will make external calls, however this example // hardcodes setting the id attribute to a specific value for brevity. data.ID = types.StringValue("example-id") // Save data into Terraform state resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)}
Metadata Method
The datasource.DataSource
interface Metadata
method defines the data source name as it would appear in Terraform configurations. This name should include the provider type prefix, an underscore, then the data source specific name. For example, a provider named examplecloud
and a data source that reads "thing" resources would be named examplecloud_thing
. Ensure the Add Data Source To Provider documentation is followed so the data source becomes part of the provider implementation, and therefore available to practitioners.
In this example, the data source name in an examplecloud
provider that reads "thing" resources is hardcoded to examplecloud_thing
:
// With the datasource.DataSource implementationfunc (d *ThingDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { resp.TypeName = "examplecloud_thing"}
To simplify data source implementations, the provider.MetadataResponse.TypeName
field from the provider.Provider
interface Metadata
method can set the provider name so it is available in the datasource.MetadataRequest.ProviderTypeName
field.
In this example, the provider defines the examplecloud
name for itself, and the data source is named examplecloud_thing
:
// With the provider.Provider implementationfunc (p *ExampleCloudProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) { resp.TypeName = "examplecloud"} // With the datasource.DataSource implementationfunc (d *ThingDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_thing"}
Schema Method
The datasource.DataSource
interface Schema
method defines a schema describing what data is available in the data source's configuration and state.
Read Method
The datasource.DataSource
interface Read
method defines how the data source updates Terraform's state to reflect the retrieved data. There is no plan or prior state to work with in Read
requests, only configuration.
During the terraform apply
, terraform plan
, and terraform refresh
commands, Terraform calls the provider ReadDataSource
RPC, in which the framework calls the datasource.DataSource
interface Read
method.
Implement the Read
method by:
- Accessing configuration data from the
datasource.ReadRequest.Config
field. - Retriving any additional data, such as remote system information.
- Writing state data into the
datasource.ReadResponse.State
field.
If the logic needs to return warning or error diagnostics, they can added into the datasource.ReadResponse.Diagnostics
field.
Add Data Source to Provider
Data sources become available to practitioners when they are included in the provider implementation via the provider.ProviderWithDataSources
interface DataSources
method.
In this example, the ThingDataSource
type, which implements the datasource.DataSource
interface, is added to the provider implementation:
// With the provider.Provider implementationfunc (p *ExampleCloudProvider) DataSources(_ context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{ func() datasource.DataSource { return &ThingDataSource{}, }, }}
To simplify provider implementations, a named function can be created with the data source implementation.
In this example, the ThingDataSource
code includes an additional NewThingDataSource
function, which simplifies the provider implementation:
// With the provider.Provider implementationfunc (p *ExampleCloudProvider) DataSources(_ context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{ NewThingDataSource, }} // With the datasource.DataSource implementationfunc NewThingDataSource() datasource.DataSource { return &ThingDataSource{}}