A new platform for documentation and tutorials is launching soon.
We are migrating Terraform documentation into HashiCorp Developer, our new developer experience.
»Resources
Resources are an abstraction that allow Terraform to manage infrastructure objects, such as a compute instance, an access policy, or disk. Terraform assumes that every resource:
- operates as a pure key/value store, with values getting returned exactly as they were written.
- needs only one API call to update or return its state.
- can be be created, read, updated, and deleted.
This page describes the basic implementation details required for supporting a resource within the provider. Further documentation is available for deeper resource concepts:
- Configure resources with provider-level data types or clients.
- Import state so practitioners can bring existing resources under Terraform lifecycle management.
- Manage private state to store additional data in resource state that is not shown in plans.
- Modify plans to enrich the output for expected resource behaviors during changes, such as including default values for missing configurations or marking a resource for replacement if an in-place update cannot occur.
- Upgrade state to transparently update state data outside plans.
- Validate practitioner configuration against acceptable values.
»Define Resource Type
Implement the resource.Resource
interface. Each of the methods is described in more detail below.
In this example, a resource named examplecloud_thing
with sample lifecycle management behavior is defined:
»Metadata Method
The resource.Resource
interface Metadata
method defines the resource name as it would appear in Terraform configurations. This name should include the provider type prefix, an underscore, then the resource specific name. For example, a provider named examplecloud
and a resource that reads "thing" resources would be named examplecloud_thing
. Ensure the Add Data Source To Provider documentation is followed so the resource becomes part of the provider implementation, and therefore available to practitioners.
In this example, the resource name in an examplecloud
provider that reads "thing" resources is hardcoded to examplecloud_thing
:
To simplify resource implementations, the provider.MetadataResponse.TypeName
field from the provider.ProviderWithMetadata
interface Metadata
method can set the provider name so it is available in the resource.MetadataRequest.ProviderTypeName
field.
In this example, the provider defines the examplecloud
name for itself, and the data source is named examplecloud_thing
:
»GetSchema Method
The resource.Resource
interface GetSchema
method defines a schema describing what data is available in the resource's configuration, plan, and state.
»Create
The resource.Resource
interface Create
method makes the necessary API calls to create the resource and then persist that resource's data into the Terraform state.
Implement the Create
method by:
- Accessing the data from the
resource.CreateRequest
type. Most use cases should access the plan data in theresource.CreateRequest.Plan
field. - Performing logic or external calls to create and/or run the resource.
- Writing state data into the
resource.CreateResponse.State
field.
It is very important that every known value in the plan ends up in state as a byte-for-byte match, or Terraform will throw errors. The plan is the provider's contract with Terraform: the provider can only change values that are unknown in the plan. It's also very important that every unknown value in the plan gets a known, concrete value when it's set in the state; the state can never hold any unknown values.
If the logic needs to return warning or error diagnostics, they can added into the resource.CreateResponse.Diagnostics
field. Any errors will trigger Terraform to mark the resource as tainted for recreation on the next Terraform plan.
»Read
The resource.Resource
interface Read
method makes the necessary calls to retrieve the latest resource state and then persist that updated state into the Terraform state. There is no plan or configuration data in Read
.
Implement the Read
method by:
- Accessing prior state data from the
resource.ReadRequest.State
field. - Retriving updated resource state, such as remote system information.
- Writing state data into the
resource.ReadResponse.State
field.
The provider can set any value in state, but you should be mindful of values that:
- represent "drift," or instances when the API's state has deviated from the source of truth defined in the configuration file. This is usually (but not always) the result of someone or something other than Terraform modifying a resource Terraform "owns". When this happens, the value should always be updated in state to reflect the drifted value.
- are semantically equivalent with values currently in state. Some values are semantically the same even if they are not a byte-for-byte match. JSON strings that change the order of keys or change the semantically-insignificant whitespace, for example, may not represent drift but are just different representations of the same value. When this happens, the existing value should always be maintained in state and should not be replaced with the new representation that the API is returning.
If the logic needs to return warning or error diagnostics, they can added into the resource.ReadResponse.Diagnostics
field.
If the logic needs to signal that the resource no longer exists and should be recreated, call the RemoveResource
method on the resource.ReadResponse.State
field.
In this example, the Read
function catches a HTTP 404 Not Found status and returns early to signal resource recreation:
»Update
The resource.Resource
interface Update
method makes the necessary calls to modify the existing resource to match the configuration and then persist the updated state.
If the resource does not support modification and should always be recreated on configuration value updates, this method logic can be left empty and ensure all configurable schema attributes implement the resource.RequiresReplace
plan modifier.
Implement the Update
method by:
- Accessing the data from the
resource.UpdateRequest
type. Most use cases should access the plan data in theresource.UpdateRequest.Plan
field. - Performing logic or external calls to modify the resource.
- Writing state data into the
resource.UpdateResponse.State
field.
It is very important that every known value in the plan ends up in state as a byte-for-byte match, or Terraform will throw errors. The plan is the provider's contract with Terraform: the provider can only change values that are unknown in the plan. It's also very important that every unknown value in the plan gets a known, concrete value when it's set in the state; the state can never hold any unknown values.
If the logic needs to return warning or error diagnostics, they can added into the resource.UpdateResponse.Diagnostics
field. Only successfully modified parts of the resource should be return updated data in the state response.
»Delete
The resource.Resource
interface Delete
method makes the necessary API calls to destroy a resource and then to remove that resource from the Terraform state.
Implement the Delete
method by:
- Accessing prior state data from the
resource.DeleteRequest.State
field. - Performing logic or external calls to destroy the resource.
Terraform 1.3 and later enables deletion planning, which resources can implement to return warning and error diagnostics. For additional information, refer to the resource plan modification documentation.
If the logic needs to return warning or error diagnostics, they can added into the resource.DeleteResponse.Diagnostics
field. Any errors will prevent the framework from automatically calling the RemoveResource
method on the resource.DeleteResponse.State
field. If the resource should still be removed from state, call the RemoveResource
method manually.
If the logic needs to skip a condition, such as an API error, where the resource no longer exists then the logic can return early.
In this example, the Delete
function allows HTTP 200 OK and 404 Not Found statuses to complete successfully without raising any errors:
»Add Resource to Provider
Resources become available to practitioners when they are included in the provider implementation via the provider.ProviderWithResources
interface Resources
method.
In this example, the ThingResource
type, which implements the resource.Resource
interface, is added to the provider implementation:
To simplify provider implementations, a named function can be created with the resource implementation.
In this example, the ThingResource
code includes an additional NewThingResource
function, which simplifies the provider implementation: