Implement complex read
Note: We recommend using the Terraform Plugin Framework for new provider development because it offers significant advantages compared to the SDKv2. Refer to the Plugin Framework tutorials to learn how to create providers using the framework.
In this tutorial, you will retrieve an order, a protected endpoint, to verify whether a Terraform provider that interacts with the API of a fictional coffee-shop application called Hashicups, has been authenticated to the API successfully. The order
schema contains nested objects, making it a more complicated data structure than the previously defined coffee
data source. To do this, you will:
- Create a new order via API
There must be an existing order for you to retrieve it. - Define
order
data source.
You will add a scaffold that defines an empty schema and functions to retrieve order information. - Define
order
schema.
The schema reflects the response from invoking the/order/{orderId}
endpoint. Theorder
schema is considered complex because it nests a list ofOrderItem
s. - Implement complex read.
This read functionality uses multiple nesting functions to flatten the response from/order/{orderId}
and map it to theorder
schema. - Add
order
data source to the provider schema.
This allows you to use the data source in your configuration.
Prerequisites
To follow this tutorial, you need:
- a Golang 1.15+ installed and configured.
- the Terraform 0.14+ CLI installed locally.
- Docker and Docker Compose to run an instance of HashiCups locally.
Navigate to your terraform-provider-hashicups
directory. Next, fetch new changes.
Then, checkout the auth-configuration
branch. This step is optional but recommended to ensure that your code matches the code from the previous tutorials.
Your directory should have the following structure.
If you're stuck at any point during this tutorial, refer to the implement-complex-read
branch to see the changes implemented in this tutorial.
Create an order
via API
Before you can query a user's order, you must first create an order. Replace the authorization token with the token you generated in the sign in step.
Query the order using the order ID you received in the response above as a HTML parameter (localhost:19090/orders/{orderID}
). The response should be the same as the response above.
Define order
data resource
Now, create a file named hashicups/data_source_order.go
in your hashicups
directory and add the following snippet.
Format your code.
Notice how the schema mirrors the JSON response — only id
and items
exist on the top level.
The
id
is required because an order ID must be set so the data source knows which order to retrieve.The
items
schema is a computed list (schema.TypeList
) of objects (schema.Resource
) containingcoffee
attributes andquantity
.The
coffee
attributes is flattened and mapped accordingly (coffee.id
is mapped tocoffee_id
, etc...)
You will learn an alternative method to nest maps in the Implement Create tutorial, when you create new orders.
Implement complex read
Now that you have defined the order
schema, add the dataSourceOrderRead
function to hashicups/data_source_order.go
. This function will retrieve the order and map its values to the order
schema defined above.
Format your code.
Notice the m
(meta) input parameter contains the HashiCups API Client set by the ConfigureContextFunc
defined above. If provider uses an unauthenticated API Client, this function will fail and return an error message.
The API Client's GetOrder
function returns an order object. However, you must flatten this response to accurately map the response to the order
schema. An order consists of an order ID and a list of coffee objects and their respective quantities. As a result, the order object must go through one flattening function to populate the list of coffee objects and their quantities.
Add the flattenOrderItemsData
function to your hashicups/data_source_order.go
file. This returns a list of order items.
Format your code.
The flattenOrderItemsData
function takes an *[]hc.OrderItem
as orderItems
. If orderItems
is not nil, it will iterate through the slice and map its values into a map[string]interface{}
. Notice how the function assigns the coffee
attributes directly to its corresponding flattened attribute (orderItem.Coffee.ID
-> coffee_id
).
Add data source to provider
Now that you've defined the order
data source, you can add it to your provider.
In your hashicups/provider.go
file, add the order
data source to the DataSourcesMap
of your Provider()
function. Resources and data sources names must follow the <provider>_<resource_name>
convention.
Test the provider
Now that you've implemented read and created the coffees
data source, verify that it works.
First, confirm that you are in the terraform-provider-hashicups
root directory.
Next, build the binary and move it into your user Terraform plugins directory. This allows you to sideload and test the custom provider. Select the tab for your operating system for specific instructions.
Tip
The Perform CRUD operations with Providers tutorial explains why and how to sideload custom providers. Refer to it to learn more about where to install custom providers and how to reference them in your configuration.
Navigate to the terraform-provider-hashicups/examples
directory. This contains a sample Terraform configuration for the Terraform HashiCups provider.
Add the following Terraform configuration to main.tf
.
Finally, initialize your workspace to refresh your HashiCups provider, then apply. This should return the first order in your output.
Notice how the coffee attributes are flattened.
Next steps
In this tutorial, you implemented a nested read function. This will be useful when you will create a resource using the HashiCups provider in the Implement Create tutorial.
If you were stuck during this tutorial, checkout the implement-complex-read
branch to see the changes implemented in this tutorial.
- The Terraform Provider Scaffold is a quick-start repository for creating a Terraform provider. Use this GitHub template when you're ready to create a custom provider.
- To learn more about the Terraform Plugin SDK, refer to the Terraform Plugin SDK Documentation.