Implement resource create and read
In this tutorial, you will add create and read capabilities to a new order
resource of a provider that interacts with the API of a fictional coffee-shop application called Hashicups. To do this, you will:
- Define the initial resource type.
This prepares the resource to be added to the provider. - Add the resource to the provider.
This enables the resource for testing and Terraform configuration usage. - Implement the HashiCups client in the resource.
This retrieves the configured HashiCups client from the provider and makes it available for resource operations. - Define the resource's schema.
This prepares the resource to accept data from the Terraform configuration and store order information in the Terraform state. - Define the resource's data model.
This models the resource schema as a Go type so the data is accessible for other Go code. - Define the resource's create logic.
This handles calling the HashiCups API to create an order using the configuration saving Terraform state with the data. - Define the resource's read logic.
This handles calling the HashiCups API using the configured client and refreshing the Terraform state with the data. - Verify the resource's behavior.
This verifies that the resource behaves as expected when you refer to it in Terraform configuration.
Prerequisites
For this tutorial, you will need:
- Go 1.21+ installed and configured.
- Terraform v1.8+ installed locally.
- Docker and Docker Compose to run an instance of HashiCups locally.
- jq installed.
Navigate to your terraform-provider-hashicups
directory.
Your code should match the 04-logging
directory
from the example repository.
Implement initial resource type
Providers use an implementation of the resource.Resource
interface type as the starting point for a resource implementation.
This interface requires the following:
- A Metadata method to define the resource type name, which is how the resource is used in Terraform configurations.
- A Schema method to define the schema for any resource configuration, plan, and state data.
- A Create method to define the logic which creates the resource and sets its initial Terraform state.
- A Read method to define the logic which refreshes the Terraform state for the resource.
- An Update method to define the logic which updates the resource and sets the updated Terraform state on success.
- A Delete method to define the logic which deletes the resource and removes the Terraform state on success.
Create a internal/provider/order_resource.go
file.
Add resource to provider
Providers return the resources they support from their Resources
method.
Open the internal/provider/provider.go
file.
Add the NewOrderResource
resource to your provider by replacing the Resources
method with the following.
Implement resource client functionality
Resources use the optional Configure
method to fetch configured clients from the provider. The provider already configures the HashiCups client and the resource can save a reference to that client for its operations.
Open the internal/provider/order_resource.go
file.
Allow your resource type to store a reference to the HashiCups client by
replacing the orderResource
type with the following.
Import the HashiCups client package your resource will require by replacing the import
statement at the beginning of the file with the following.
Ensure that your resource satisfies the Resource
and ResourceWithConfigure
interfaces defined by the Framework by replacing the var
statement with the following.
Add a Configure
method to retrieve the HashiCups client with the following.
Implement resource schema
The resource uses the Schema
method to define the supported configuration,
plan, and state attribute names and types. The order resource will need to save
a list of coffees with various attributes to Terraform's state.
Replace your order resource's Schema
method with the following.
Implement resource data models
Add the following data model types for your resource to order_resource.go
.
Implement create functionality
The provider uses the Create
method to create a new resource based on the schema data.
The create method follows these steps:
- Checks whether the API Client is configured. If not, the resource responds with an error.
- Retrieves values from the plan. The function will attempt to retrieve values from the plan and convert it to an
orderResourceModel
. - Generates an API request body from the plan values. The function loops through each plan item and maps it to a
hashicups.OrderItem
. This is what the API client needs to create a new order. - Creates a new order. The function invokes the API client's
CreateOrder
method. - Maps response body to resource schema attributes. After the function creates an order, it maps the
hashicups.Order
response to[]OrderItem
so the provider can update the Terraform state. - Sets Terraform's state with the new order's details.
Replace your resource's Create
method with the following.
Add the packages used in the Create
method by replacing the import
statement
with the following.
Implement read functionality
The provider uses the Read
function to retrieve the resource's information and update the Terraform state to reflect the resource's current state. The provider invokes this function before every plan to generate an accurate diff between the resource's current state and the configuration.
The read function follows these steps:
- Gets the current state. If it is unable to, the provider responds with an error.
- Retrieves the order ID from Terraform's state.
- Retrieves the order details from the client. The function invokes the API client's
GetOrder
method with the order ID. - Maps the response body to resource schema attributes. After the function
retrieves the order, it maps the
hashicups.Order
response to[]OrderItem
so the provider can update the Terraform state. - Set Terraform's state with the order's details.
Replace your provider's Read
method in order_resource.go
with the following:
Build and install the updated provider.
If you were stuck at any step, check out the
create-read-order
branch to see the changes implemented in this tutorial.
Verify resource
The Terraform provider you just modified is ready to communicate with your API endpoint to create an order.
Create an examples/order
directory and navigate to it.
Create a main.tf
Terraform configuration file in this directory that creates a new order.
Apply your configuration to create the order. Notice how the execution plan shows a proposed order, with additional information about the order. Remember to confirm the apply step with a yes
.
Once the apply completes, the provider saves the resource's details in
Terraform's state. View the state by running terraform state show
<resource_name>
.
The (known after apply)
values in the execution plan during the terraform apply state have all been populated, since the order was successfully created.
Navigate to the terraform-provider-hashicups
directory.
Verify order created
When you create an order in HashiCups using Terraform, the terminal containing your HashiCups logs will have recorded operations invoked by the HashiCups Provider. Switch to that terminal to review the log messages.
The provider invoked a total of 3 operations.
- The provider invoked the first
signin
operation when you ranterraform apply
to retrieve the current state of your resources. Because there are no resources, it only authenticates the user. - The provider invoked the second
signin
operation after you confirmed the apply run. The provider authenticated using the provided credentials to retrieve and save the JWT token. - The provider invoked the
CreateOrder
operation to create the order defined by the Terraform configuration. Since this is a protected endpoint, it used the saved JWT token from the priorsignin
operation.
Verify that Terraform created the order by retrieving the order details via the API.
The order's properties should be the same as that of your hashicups_order.edu
resource.
Next steps
Congratulations! You have implemented the order
resource with create and read
capabilities.
If you were stuck during this tutorial, checkout the
05-create-read-order
directory in the example repository to see the code implemented in this
tutorial.
- To learn more about the Terraform Plugin Framework, refer to the Terraform Plugin Framework documentation.
- For a full capability comparison between the SDKv2 and the Plugin Framework, refer to the Which SDK Should I Use? documentation.
- The example repository contains directories corresponding to each tutorial in this collection.
- Submit any Terraform Plugin Framework bug reports or feature requests to the development team in the Terraform Plugin Framework Github repository.
- Submit any Terraform Plugin Framework questions in the Terraform Plugin Framework Discuss forum.