Terraform
- Plugin Framework
- v1.16.x (latest)
- No versions of this document exist before v1.15.x. Click below to redirect to the version homepage.
- v1.15.x
- v1.14.x
- v1.13.x
- v1.12.x
- v1.11.x
- v1.10.x
- v1.9.x
- v1.8.x
- v1.7.x
- v1.6.x
- v1.5.x
- v1.4.x
- v1.3.x
- v1.2.x
- v1.1.x
- v1.0.x
- v0.17.x
- v0.16.x
- v0.15.x
- v0.14.x
- v0.13.x
- v0.11.x
- v0.10.x
- v0.9.x
- v0.8.x
- v0.7.x
Import
Practitioners can use the terraform import command to let Terraform
begin managing existing infrastructure by importing an existing resource into their Terraform project's state. A
resource's importer function implements the logic to add a resource to Terraform's state. Refer to
Resources - Import in the Framework documentation for details.
This page explains how to migrate import functions from SDKv2 to the plugin Framework.
SDKv2
In SDKv2, the Importer field on the schema.Resource defines how the provider imports resources to Terraform's
state. The following example implements resource import with SDKv2.
func resourceExample() *schema.Resource {
    return &schema.Resource{
        Importer: &schema.ResourceImporter{
            StateContext: StateContextFunc,
        },
        /* ... */
The StateContextFunc is the function called to import a resource into Terraform state. Any operations that
are needed to import the resource take place within this function and may result in the mutation of the ResourceData
that is passed into the function. The return value is a slice of schema.ResourceData. This slice might be as simple as returning the ResourceData that was passed into the function, or it may involve multiple fan out to multiple resources, such as AWS security groups.
Framework
In the Framework, you implement the ResourceWithImportState interface on your resource.Resource type to allow
users to import a given resource. This interface requires that your type implement a ImportState function.
The following code shows how you define an ImportState function with the Framework.
func (r *resourceExample) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
    /* ... */
}
The ImportState function includes a resource.ImportStateResponse, which you use to set your resource's state.
Migration Notes
Remember the following differences between SDKv2 and the Framework when completing the migration.
- In both SDKv2 and Framework, there is no access to the configuration, state, or plan during import. The import
functions can only access the value (e.g., the resource's ID) supplied to theterraform importcommand.
- In SDKv2, you implement resource importing by populating the Importerfield on theschema.Resourcestruct. In the Framework, you define anImportStatefunction on the type which implementsresource.Resource. This implementation satisfies thetfsdk.ResourceWithImportStateinterface.
Example
In the simple use case in which schema.ImportStatePassthroughContext has been used with SDKv2, migrating to the Framework involves using the resource.ImportStatePassthroughID function.
SDKv2
func resourceExample() *schema.Resource {
    return &schema.Resource{
        Importer: &schema.ResourceImporter{
            StateContext: schema.ImportStatePassthroughContext,
        },
        /* ... */
    }
}
Framework
func (r *resourceExample) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
    resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
}
The following examples show how to migrate portions of the random provider.
For a complete example, clone the
terraform-provider-random repository and compare the resource_password.go file in
v3.3.2
with v3.4.1.
This example also shows one way to handle populating attributes with their default values during import.
SDKv2
The following example from the resource_password.go file shows the import function for the random_password resource
with SDKv2.
func resourcePassword() *schema.Resource {
    return &schema.Resource{
        Importer: &schema.ResourceImporter{
            StateContext: importPasswordFunc,
        },
        /* ... */
    }
}
The following example shows the implementation of the importPasswordFunc function with SDKv2.
func importPasswordFunc(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
    for k, v := range passwordSchemaV2() {
        if v.Default == nil {
            continue
        }
        if err := d.Set(k, v.Default); err != nil {
            return nil, fmt.Errorf("error setting %s: %w", k, err)
        }
    }
    for _, key := range []string{"number", "numeric"} {
        if err := d.Set(key, true); err != nil {
            return nil, fmt.Errorf("error setting %s: %w", key, err)
        }
    }
    val := d.Id()
    d.SetId("none")
    if err := d.Set("result", val); err != nil {
        return nil, fmt.Errorf("resource password import failed, error setting result: %w", err)
    }
    if err := d.Set("length", len(val)); err != nil {
        return nil, fmt.Errorf("error setting length: %w", err)
    }
    hash, err := generateHash(val)
    if err != nil {
        return nil, fmt.Errorf("resource password import failed, generate hash error: %w", err)
    }
    if err := d.Set("bcrypt_hash", hash); err != nil {
        return nil, fmt.Errorf("resource password import failed, error setting bcrypt_hash: %w", err)
    }
    return []*schema.ResourceData{d}, nil
}
Framework
The following shows the same section of provider code after the migration.
This code implements the ResourceWithImportState interface on the passwordResource type by defining an ImportState
function.
func (r *passwordResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
    id := req.ID
    state := passwordModelV2{
        ID:         types.String{Value: "none"},
        Result:     types.String{Value: id},
        Length:     types.Int64{Value: int64(len(id))},
        Special:    types.Bool{Value: true},
        Upper:      types.Bool{Value: true},
        Lower:      types.Bool{Value: true},
        Numeric:    types.Bool{Value: true},
        MinSpecial: types.Int64{Value: 0},
        MinUpper:   types.Int64{Value: 0},
        MinLower:   types.Int64{Value: 0},
        MinNumeric: types.Int64{Value: 0},
    }
    state.Keepers.ElemType = types.StringType
    hash, err := generateHash(id)
    if err != nil {
        resp.Diagnostics.Append(diagnostics.HashGenerationError(err.Error())...)
    }
    state.BcryptHash = types.String{Value: hash}
    diags := resp.State.Set(ctx, &state)
    resp.Diagnostics.Append(diags...)
    if resp.Diagnostics.HasError() {
        return
    }
}