Skip to content

Latest commit

 

History

History
145 lines (106 loc) · 7.49 KB

File metadata and controls

145 lines (106 loc) · 7.49 KB
page_title description
Plugin Development - Framework: Data Sources
How to build data sources in the provider development framework. Data sources allow Terraform to reference external data.

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 implementation
func (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 implementation
func (p *ExampleCloudProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) {
	resp.TypeName = "examplecloud"
}

// With the datasource.DataSource implementation
func (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.

Implement the Read method by:

  1. Accessing configuration data from the datasource.ReadRequest.Config field.
  2. Retriving any additional data, such as remote system information.
  3. 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 implementation
func (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 implementation
func (p *ExampleCloudProvider) DataSources(_ context.Context) []func() datasource.DataSource {
	return []func() datasource.DataSource{
		NewThingDataSource,
	}
}

// With the datasource.DataSource implementation
func NewThingDataSource() datasource.DataSource {
	return &ThingDataSource{}
}