Resource Import
Practitioners can use the terraform import
command to let Terraform begin managing existing infrastructure resources. Resources can implement the ImportState
method, which must either specify enough Terraform state for the Read
method to refresh resource.Resource
or return an error.
Define Resource ImportState Method
The resource.ResourceWithImportState
interface on the resource.Resource
interface implementation will enable practitioner support for importing an existing resource.
Implement the ImportState
method by:
- Accessing the import identifier from the
resource.ImportStateRequest.ID
field - Writing state data into the
resource.ImportStateResponse.State
field.
In this example, the resource state has the id
attribute set to the value passed into the terraform import
command using the resource.ImportStatePassthroughID
function:
func (r *ThingResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)}
Multiple Attributes
When the Read
method requires multiple attributes to refresh, you must write custom logic in the ImportState
method.
Implement the ImportState
method by:
- Accessing the import identifier from the
resource.ImportStateRequest.ID
field - Performing the custom logic.
- Writing state data into the
resource.ImportStateResponse.State
field.
The terraform import
command will need to accept the multiple attribute values as a single import identifier string. A typical convention is to use a separator character, such as a comma (,
), between the values. The ImportState
method will then need to parse the import identifier string into the multiple separate values and save them appropriately into the Terraform state.
In this example, the resource requires two attributes to refresh state and accepts them as an import identifier of attr_one,attr_two
:
func (r *ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ "attr_one": schema.StringAttribute{ Required: true, }, "attr_two": schema.StringAttribute{ Required: true, }, /* ... */ }, }} func (r *ThingResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { var attrOne, attrTwo string resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("attr_one"), &attrOne)...) resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("attr_two"), &attrTwo)...) if resp.Diagnostics.HasError() { return } // API call using attrOne and attrTwo} func (r *ThingResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { idParts := strings.Split(req.ID, ",") if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" { resp.Diagnostics.AddError( "Unexpected Import Identifier", fmt.Sprintf("Expected import identifier with format: attr_one,attr_two. Got: %q", req.ID), ) return } resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("attr_one"), idParts[0])...) resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("attr_two"), idParts[1])...)}
Not Implemented
If the resource does not support terraform import
, skip the ImportState
method implementation.
When a practitioner runs terraform import
, Terraform CLI will return:
$ terraform import example_resource.example some-identifierexample_resource.example: Importing from ID "some-identifier"...╷│ Error: Resource Import Not Implemented│ │ This resource does not support import. Please contact the provider developer for additional information.╵