Terraform
Listing resources
List is called when a terraform query is executed, the ListResource RPC is called which in turn calls the list.ListResource interface List method. The request contains the configuration supplied to Terraform by the list block and the response contains a stream of the list results.
Define List Method
Implement the List method by:
- Accessing the
Configdata from thelist.ListRequesttype. - Performing external calls and logic for the list operation.
- For each list result instantiate a new result object using the
list.ListRequest.NewListResultmethod. - Return an iterator function that pushes list results into the response stream.
If the logic needs to return warning or error diagnostics, they can be added into the list.ListResult.Diagnostics field of an empty list result and pushed into the stream.
In this example, the list method on the resource examplecloud_thing is defined:
// ThingListResource defines the list implementation.
// Some list.ListResource interface methods are omitted for brevity.
type ThingListResource struct{}
type ThingListResourceModel struct {
ResourceGroupName types.String `tfsdk:"resource_group_name"`
}
func (r *ThingListResource) ListResourceConfigSchema(_ context.Context, _ list.ListResourceConfigSchemaRequest, resp *list.ListResourceConfigSchemaResponse) {
resp.Schema = listschema.Schema{
Attributes: map[string]listschema.Attribute{
"resource_group_name": listschema.StringAttribute{
Description: "Name of the resource group to list things in.",
Required: true,
},
},
}
}
func (r *ThingListResource) List(ctx context.Context, req list.ListRequest, stream *list.ListResultsStream) {
var data ThingListResourceModel
// Read list config data into the model
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
// Typically lists will make external calls here using data from the config
// as input. For brevity, we assume the `things` slice below was returned by an
// API call here
// Define the function that will push results into the stream
stream.Results = func(push func(list.ListResult) bool) {
for _, thing := range things {
// Initialize a new result object for each thing
result := req.NewListResult(ctx)
// Set the user-friendly name of this thing
result.DisplayName = thing.Name
// Set resource identity data on the result
resp.Diagnostics.Append(result.Identity.Set(ctx, thing.ID))
if resp.Diagnostics.HasError() {
return
}
// Set the resource information on the result
resp.Diagnostics.Append(result.Resource.Set(ctx, thing.Resource))
if resp.Diagnostics.HasError() {
return
}
// Send the result to the stream.
if !push(result) {
return
}
}
}
}
Caveats
- An error is returned if a list result in the stream contains a null identity unless it contains a warning in the diagnostics.
- An error is returned if
include_resourceis set totrueand a list result in the stream has a null resource.