|
| 1 | +package fwserver |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + |
| 6 | + "github.com/hashicorp/terraform-plugin-framework/diag" |
| 7 | + "github.com/hashicorp/terraform-plugin-framework/internal/logging" |
| 8 | + "github.com/hashicorp/terraform-plugin-framework/tfsdk" |
| 9 | +) |
| 10 | + |
| 11 | +// ImportedResource represents a resource that was imported. |
| 12 | +type ImportedResource struct { |
| 13 | + Private []byte |
| 14 | + State tfsdk.State |
| 15 | + TypeName string |
| 16 | +} |
| 17 | + |
| 18 | +// ImportResourceStateRequest is the framework server request for the |
| 19 | +// ImportResourceState RPC. |
| 20 | +type ImportResourceStateRequest struct { |
| 21 | + ID string |
| 22 | + ResourceType tfsdk.ResourceType |
| 23 | + |
| 24 | + // EmptyState is an empty State for the resource schema. This is used to |
| 25 | + // initialize the ImportedResource State of the ImportResourceStateResponse |
| 26 | + // and allow the framework server to verify that the provider updated the |
| 27 | + // state after the provider defined logic. |
| 28 | + EmptyState tfsdk.State |
| 29 | + |
| 30 | + // TypeName is the resource type name, which is necessary for populating |
| 31 | + // the ImportedResource TypeName of the ImportResourceStateResponse. |
| 32 | + TypeName string |
| 33 | +} |
| 34 | + |
| 35 | +// ImportResourceStateResponse is the framework server response for the |
| 36 | +// ImportResourceState RPC. |
| 37 | +type ImportResourceStateResponse struct { |
| 38 | + Diagnostics diag.Diagnostics |
| 39 | + ImportedResources []ImportedResource |
| 40 | +} |
| 41 | + |
| 42 | +// ImportResourceState implements the framework server ImportResourceState RPC. |
| 43 | +func (s *Server) ImportResourceState(ctx context.Context, req *ImportResourceStateRequest, resp *ImportResourceStateResponse) { |
| 44 | + if req == nil { |
| 45 | + return |
| 46 | + } |
| 47 | + |
| 48 | + // Always instantiate new Resource instances. |
| 49 | + logging.FrameworkDebug(ctx, "Calling provider defined ResourceType NewResource") |
| 50 | + resource, diags := req.ResourceType.NewResource(ctx, s.Provider) |
| 51 | + logging.FrameworkDebug(ctx, "Called provider defined ResourceType NewResource") |
| 52 | + |
| 53 | + resp.Diagnostics.Append(diags...) |
| 54 | + |
| 55 | + if resp.Diagnostics.HasError() { |
| 56 | + return |
| 57 | + } |
| 58 | + |
| 59 | + resourceWithImportState, ok := resource.(tfsdk.ResourceWithImportState) |
| 60 | + |
| 61 | + if !ok { |
| 62 | + // If there is a feature request for customizing this messaging, |
| 63 | + // provider developers can implement a ImportState method that |
| 64 | + // immediately returns a custom error diagnostic. |
| 65 | + // |
| 66 | + // However, implementing the ImportState method could cause issues |
| 67 | + // with automated documentation generation, which likely would check |
| 68 | + // if the resource implements the ResourceWithImportState interface. |
| 69 | + // Instead, a separate "ResourceWithoutImportState" interface could be |
| 70 | + // created with a method such as: |
| 71 | + // ImportNotImplementedMessage(context.Context) string. |
| 72 | + resp.Diagnostics.AddError( |
| 73 | + "Resource Import Not Implemented", |
| 74 | + "This resource does not support import. Please contact the provider developer for additional information.", |
| 75 | + ) |
| 76 | + return |
| 77 | + } |
| 78 | + |
| 79 | + importReq := tfsdk.ImportResourceStateRequest{ |
| 80 | + ID: req.ID, |
| 81 | + } |
| 82 | + importResp := tfsdk.ImportResourceStateResponse{ |
| 83 | + State: tfsdk.State{ |
| 84 | + Raw: req.EmptyState.Raw.Copy(), |
| 85 | + Schema: req.EmptyState.Schema, |
| 86 | + }, |
| 87 | + } |
| 88 | + |
| 89 | + logging.FrameworkDebug(ctx, "Calling provider defined Resource ImportState") |
| 90 | + resourceWithImportState.ImportState(ctx, importReq, &importResp) |
| 91 | + logging.FrameworkDebug(ctx, "Called provider defined Resource ImportState") |
| 92 | + |
| 93 | + resp.Diagnostics.Append(importResp.Diagnostics...) |
| 94 | + |
| 95 | + if resp.Diagnostics.HasError() { |
| 96 | + return |
| 97 | + } |
| 98 | + |
| 99 | + if importResp.State.Raw.Equal(req.EmptyState.Raw) { |
| 100 | + resp.Diagnostics.AddError( |
| 101 | + "Missing Resource Import State", |
| 102 | + "An unexpected error was encountered when importing the resource. This is always a problem with the provider. Please give the following information to the provider developer:\n\n"+ |
| 103 | + "Resource ImportState method returned no State in response. If import is intentionally not supported, remove the Resource type ImportState method or return an error.", |
| 104 | + ) |
| 105 | + return |
| 106 | + } |
| 107 | + |
| 108 | + resp.ImportedResources = []ImportedResource{ |
| 109 | + { |
| 110 | + State: importResp.State, |
| 111 | + TypeName: req.TypeName, |
| 112 | + }, |
| 113 | + } |
| 114 | +} |
0 commit comments