Terraform
Timeouts
The framework can be used in conjunction with the terraform-plugin-framework-timeouts module in order to allow defining timeouts in configuration and have them be available in CRUD functions.
In framework providers, you can define timeouts using either nested blocks or nested attributes.
If you are writing a new provider using terraform-plugin-framework, then we recommend using nested attributes.
If you are already adding timeouts as part of your migration, you can either continue using block syntax or switch to nested attributes. However, practitioners that use your provider must update their Terraform configuration if you switch to nested attributes requires. You should only introduce breaking changes to your provider in major version updates.
If your provider uses timeouts in the Create
function or other function that unmarshals the configuration, state, or plan, then you must update your resource's model to include the timeout fields.
Once you have added timeouts to your resource's model, you can access them in
CRUD functions by using helper functions
provider by the timeouts
module.
Background
Operations such as booting operating systems, discovering services, and replicating state across network edges take time to complete. You should take the known delays in resource APIs into account when implementing CRUD functions for resources. Terraform supports configurable timeouts to assist in these situations.
Migrating timeouts in nested blocks
If your provider configuration uses a nested block to define timeouts, then you can use the timeouts
module to implement them. The module can also mutate your resource schema to add the timeout
block. The following example shows a configuration with timeout
block nested in the resource
block, which is an implementation suitable for using the module:
resource "timeouts_example" "example" {
/* ... */
timeouts {
create = "60m"
}
}
First add the timeouts module to your resource type:
Framework
import (
/* ... */
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
)
Then use this module to mutate your resource's
schema.Schema
as follows:
Framework
func (t *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
/* ... */
Blocks: map[string]schema.Block{
"timeouts": timeouts.Block(ctx, timeouts.Opts{
Create: true,
}),
},
Migrate timeouts in nested attributes
If your provider configuration uses nested attributes to define timeouts, then you can use the timeouts
module to implement them. The module can also mutate your resource schema to add the timeout attribute. The following example shows a timeout
attribute nested in the resource
block, which is an implementation suitable for the module:
resource "timeouts_example" "example" {
/* ... */
timeouts = {
create = "60m"
}
}
First add the timeouts module to your resource type:
Framework
import (
/* ... */
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
)
Then use this module to mutate the schema.Schema
as follows:
Framework
func (t *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
/* ... */
"timeouts": timeouts.Attributes(ctx, timeouts.Opts{
Create: true,
}),
},
Update models
If you use timeouts in the Create
function or other functions that unmarshal the configuration, state, or plan, then you must update your resource's model to include a field for timeouts.
Framework
func (e *exampleResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data exampleResourceData
diags := req.Plan.Get(ctx, &data)
resp.Diagnostics.Append(diags...)
Modify the exampleResourceData
model to include a field for timeouts using a
timeouts.Value
type.
Framework
type exampleResourceData struct {
/* ... */
Timeouts timeouts.Value `tfsdk:"timeouts"`
Access timeouts in CRUD functions
After populating the model with the configuration, state, or plan, Terraform can access the duration of the timeout by calling the appropriate helper function, such as timeouts.Create
, so that it can configure timeout behavior. For example:
Framework
func (e *exampleResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data exampleResourceData
diags := req.Plan.Get(ctx, &data)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
createTimeout, diags := data.Timeouts.Create(ctx, 20*time.Minute)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
ctx, cancel := context.WithTimeout(ctx, createTimeout)
defer cancel()
/* ... */
}