Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
helper/schema: Introduce context-aware resource CRUD functions withou…
…t default timeout Reference: #675 The Terraform Plugin SDK has always supported customizable timeouts, declared at the `helper/schema.Resource.Timeouts` level with the operation aware [`helper/schema.ResourceTimeout` type](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema#ResourceTimeout). These were designed to allow practitioners to implement a timeout per resource, e.g. ```terraform resource "example_thing" "example" { timeouts { create = "60m" } } ``` Where the resource logic could fetch the timeout value via [`(helper/schema.ResourceData).Timeout()` function](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema#ResourceData.Timeout). Recently, context-aware resource operation functions were introduced and the existing non-context-aware functions were deprecated. These new context-aware resource operations forcibly introduce an operation timeout (defaults to 20 minutes) for the called logic, e.g. https://github.com/hashicorp/terraform-plugin-sdk/blob/e21a5bbb73209dcb31f4c9dff3a8c0cec1ca65ac/helper/schema/resource.go#L283-L285 Previously, the non-context-aware resources could be implemented with `helper/schema.Resource.Timeouts.Create` defined and operation logic such as: ```go func resourceExampleThingCreate(d *schema.ResourceData, meta interface{}) error { mutexkv.Lock("somekey") defer mutexkv.Unlock("somekey") // ... reference to d.Timeout(schema.TimeoutCreate) ... } ``` Where in this case, the create timeout could be referenced in the code via `d.Timeout(schema.TimeoutCreate)` after the synchronization coordination. The creation timeout only affected this single operation, even if multiple operations were going to occur. In the case of the context-aware functionality however, the timeout is configured before the mutex. So when multiple operations are waiting on the mutex, they are now sharing the same resource operation timeout. Since the timeout cannot be extended within the resource logic, developers are stuck either setting an arbitrarily high timeout (losing its usefulness) or practitioners are arbitrarily hitting the timeout as they scale out their configuration. To characterize how some remote systems can require that operations must be serialized or otherwise synchronized: * Only 1 resource type can be created at a time * Only 1 child resource type can be created at a time per parent resource * Only 10 concurrent updates of a resource type can be performed at a time * Remote system may support configurable synchronization limits (either by the customer or remote system operators) This essentially means the semantics of the synchronization can be based off resource configuration, operation type, and potentially accordant to the limits set by a remote system. ### Attempted Solutions ```go &schema.Resource{ Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(3 * time.Hour), }, } ``` This introduces separate CRUD methods that are invoked before the context is set with the timeout, so as to not "force" the resource timeout. If timeout behavior is still desired, developers must manually implement timeout handling in the function logic when using these. Most developers should prefer the existing context-aware functions and this is documented as such. However, another minor side benefit of these functions is that it also allows developers to upgrade CRUD function signatures for context awareness without logically changing resource behavior, then slowly switch to the timeout functions over time.
- Loading branch information