github.com/hugorut/terraform@v1.1.3/src/backend/local/backend_refresh.go (about) 1 package local 2 3 import ( 4 "context" 5 "fmt" 6 "log" 7 "os" 8 9 "github.com/hugorut/terraform/src/backend" 10 "github.com/hugorut/terraform/src/logging" 11 "github.com/hugorut/terraform/src/states" 12 "github.com/hugorut/terraform/src/states/statemgr" 13 "github.com/hugorut/terraform/src/tfdiags" 14 ) 15 16 func (b *Local) opRefresh( 17 stopCtx context.Context, 18 cancelCtx context.Context, 19 op *backend.Operation, 20 runningOp *backend.RunningOperation) { 21 22 var diags tfdiags.Diagnostics 23 24 // Check if our state exists if we're performing a refresh operation. We 25 // only do this if we're managing state with this backend. 26 if b.Backend == nil { 27 if _, err := os.Stat(b.StatePath); err != nil { 28 if os.IsNotExist(err) { 29 err = nil 30 } 31 32 if err != nil { 33 diags = diags.Append(tfdiags.Sourceless( 34 tfdiags.Error, 35 "Cannot read state file", 36 fmt.Sprintf("Failed to read %s: %s", b.StatePath, err), 37 )) 38 op.ReportResult(runningOp, diags) 39 return 40 } 41 } 42 } 43 44 // Refresh now happens via a plan, so we need to ensure this is enabled 45 op.PlanRefresh = true 46 47 // Get our context 48 lr, _, opState, contextDiags := b.localRun(op) 49 diags = diags.Append(contextDiags) 50 if contextDiags.HasErrors() { 51 op.ReportResult(runningOp, diags) 52 return 53 } 54 55 // the state was locked during succesfull context creation; unlock the state 56 // when the operation completes 57 defer func() { 58 diags := op.StateLocker.Unlock() 59 if diags.HasErrors() { 60 op.View.Diagnostics(diags) 61 runningOp.Result = backend.OperationFailure 62 } 63 }() 64 65 // If we succeed then we'll overwrite this with the resulting state below, 66 // but otherwise the resulting state is just the input state. 67 runningOp.State = lr.InputState 68 if !runningOp.State.HasManagedResourceInstanceObjects() { 69 diags = diags.Append(tfdiags.Sourceless( 70 tfdiags.Warning, 71 "Empty or non-existent state", 72 "There are currently no remote objects tracked in the state, so there is nothing to refresh.", 73 )) 74 } 75 76 // Perform the refresh in a goroutine so we can be interrupted 77 var newState *states.State 78 var refreshDiags tfdiags.Diagnostics 79 doneCh := make(chan struct{}) 80 go func() { 81 defer logging.PanicHandler() 82 defer close(doneCh) 83 newState, refreshDiags = lr.Core.Refresh(lr.Config, lr.InputState, lr.PlanOpts) 84 log.Printf("[INFO] backend/local: refresh calling Refresh") 85 }() 86 87 if b.opWait(doneCh, stopCtx, cancelCtx, lr.Core, opState, op.View) { 88 return 89 } 90 91 // Write the resulting state to the running op 92 runningOp.State = newState 93 diags = diags.Append(refreshDiags) 94 if refreshDiags.HasErrors() { 95 op.ReportResult(runningOp, diags) 96 return 97 } 98 99 err := statemgr.WriteAndPersist(opState, newState) 100 if err != nil { 101 diags = diags.Append(fmt.Errorf("failed to write state: %w", err)) 102 op.ReportResult(runningOp, diags) 103 return 104 } 105 106 // Show any remaining warnings before exiting 107 op.ReportResult(runningOp, diags) 108 }