github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/backend/local/backend_refresh.go (about) 1 package local 2 3 import ( 4 "context" 5 "fmt" 6 "log" 7 "os" 8 9 "github.com/hashicorp/terraform/internal/backend" 10 "github.com/hashicorp/terraform/internal/logging" 11 "github.com/hashicorp/terraform/internal/states" 12 "github.com/hashicorp/terraform/internal/states/statemgr" 13 "github.com/hashicorp/terraform/internal/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 successful 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 // get schemas before writing state 77 schemas, moreDiags := lr.Core.Schemas(lr.Config, lr.InputState) 78 diags = diags.Append(moreDiags) 79 if moreDiags.HasErrors() { 80 op.ReportResult(runningOp, diags) 81 return 82 } 83 84 // Perform the refresh in a goroutine so we can be interrupted 85 var newState *states.State 86 var refreshDiags tfdiags.Diagnostics 87 doneCh := make(chan struct{}) 88 go func() { 89 defer logging.PanicHandler() 90 defer close(doneCh) 91 newState, refreshDiags = lr.Core.Refresh(lr.Config, lr.InputState, lr.PlanOpts) 92 log.Printf("[INFO] backend/local: refresh calling Refresh") 93 }() 94 95 if b.opWait(doneCh, stopCtx, cancelCtx, lr.Core, opState, op.View) { 96 return 97 } 98 99 // Write the resulting state to the running op 100 runningOp.State = newState 101 diags = diags.Append(refreshDiags) 102 if refreshDiags.HasErrors() { 103 op.ReportResult(runningOp, diags) 104 return 105 } 106 107 err := statemgr.WriteAndPersist(opState, newState, schemas) 108 if err != nil { 109 diags = diags.Append(fmt.Errorf("failed to write state: %w", err)) 110 op.ReportResult(runningOp, diags) 111 return 112 } 113 114 // Show any remaining warnings before exiting 115 op.ReportResult(runningOp, diags) 116 }