diff --git a/internal/services/msgraph_resource.go b/internal/services/msgraph_resource.go index e3fc5b7..7d66471 100644 --- a/internal/services/msgraph_resource.go +++ b/internal/services/msgraph_resource.go @@ -30,7 +30,10 @@ import ( "github.com/microsoft/terraform-provider-msgraph/internal/utils/consistency" ) -const FlagMoveState = "move_state" +const ( + FlagMoveState = "move_state" + RemoteBody = "remote_body" +) // Ensure provider defined types fully satisfy framework interfaces. var ( @@ -342,9 +345,18 @@ func (r *MSGraphResource) Update(ctx context.Context, req resource.UpdateRequest } } else { var previousBody interface{} - if err := unmarshalBody(state.Body, &previousBody); err != nil { - resp.Diagnostics.AddError("Invalid body in prior state", fmt.Sprintf(`The state "body" is invalid: %s`, err.Error())) - return + if remoteBytes, _ := req.Private.GetKey(ctx, RemoteBody); len(remoteBytes) > 0 && string(remoteBytes) != "null" { + if err := json.Unmarshal(remoteBytes, &previousBody); err != nil { + tflog.Warn(ctx, fmt.Sprintf("Invalid %q value in private state; falling back to state body: %s", RemoteBody, err.Error())) + previousBody = nil + } + } + + if previousBody == nil { + if err := unmarshalBody(state.Body, &previousBody); err != nil { + resp.Diagnostics.AddError("Invalid body in prior state", fmt.Sprintf(`The state "body" is invalid: %s`, err.Error())) + return + } } diffOption := utils.UpdateJsonOption{ @@ -468,6 +480,15 @@ func (r *MSGraphResource) Read(ctx context.Context, req resource.ReadRequest, re return } state.Output = types.DynamicValue(buildOutputFromBody(responseBody, model.ResponseExportValues)) + remoteBytes, marshalErr := json.Marshal(responseBody) + if marshalErr != nil { + tflog.Warn(ctx, fmt.Sprintf("Failed to marshal remote response for private state: %s", marshalErr.Error())) + } else { + resp.Diagnostics.Append(resp.Private.SetKey(ctx, RemoteBody, remoteBytes)...) + if resp.Diagnostics.HasError() { + return + } + } if v, _ := req.Private.GetKey(ctx, FlagMoveState); v != nil && string(v) == "true" { data, err := json.Marshal(responseBody)