github.com/pdecat/terraform@v0.11.9-beta1/backend/local/backend_refresh.go (about) 1 package local 2 3 import ( 4 "context" 5 "fmt" 6 "log" 7 "os" 8 "strings" 9 10 "github.com/hashicorp/errwrap" 11 "github.com/hashicorp/terraform/backend" 12 "github.com/hashicorp/terraform/config/module" 13 "github.com/hashicorp/terraform/terraform" 14 ) 15 16 func (b *Local) opRefresh( 17 stopCtx context.Context, 18 cancelCtx context.Context, 19 op *backend.Operation, 20 runningOp *backend.RunningOperation) { 21 // Check if our state exists if we're performing a refresh operation. We 22 // only do this if we're managing state with this backend. 23 if b.Backend == nil { 24 if _, err := os.Stat(b.StatePath); err != nil { 25 if os.IsNotExist(err) { 26 err = nil 27 } 28 29 if err != nil { 30 runningOp.Err = fmt.Errorf( 31 "There was an error reading the Terraform state that is needed\n"+ 32 "for refreshing. The path and error are shown below.\n\n"+ 33 "Path: %s\n\nError: %s", 34 b.StatePath, err) 35 return 36 } 37 } 38 } 39 40 // If we have no config module given to use, create an empty tree to 41 // avoid crashes when Terraform.Context is initialized. 42 if op.Module == nil { 43 op.Module = module.NewEmptyTree() 44 } 45 46 // Get our context 47 tfCtx, opState, err := b.context(op) 48 if err != nil { 49 runningOp.Err = err 50 return 51 } 52 53 // Set our state 54 runningOp.State = opState.State() 55 if runningOp.State.Empty() || !runningOp.State.HasResources() { 56 if b.CLI != nil { 57 b.CLI.Output(b.Colorize().Color( 58 strings.TrimSpace(refreshNoState) + "\n")) 59 } 60 } 61 62 // Perform the refresh in a goroutine so we can be interrupted 63 var newState *terraform.State 64 var refreshErr error 65 doneCh := make(chan struct{}) 66 go func() { 67 defer close(doneCh) 68 newState, refreshErr = tfCtx.Refresh() 69 log.Printf("[INFO] backend/local: refresh calling Refresh") 70 }() 71 72 if b.opWait(doneCh, stopCtx, cancelCtx, tfCtx, opState) { 73 return 74 } 75 76 // write the resulting state to the running op 77 runningOp.State = newState 78 if refreshErr != nil { 79 runningOp.Err = errwrap.Wrapf("Error refreshing state: {{err}}", refreshErr) 80 return 81 } 82 83 // Write and persist the state 84 if err := opState.WriteState(newState); err != nil { 85 runningOp.Err = errwrap.Wrapf("Error writing state: {{err}}", err) 86 return 87 } 88 if err := opState.PersistState(); err != nil { 89 runningOp.Err = errwrap.Wrapf("Error saving state: {{err}}", err) 90 return 91 } 92 } 93 94 const refreshNoState = ` 95 [reset][bold][yellow]Empty or non-existent state file.[reset][yellow] 96 97 Refresh will do nothing. Refresh does not error or return an erroneous 98 exit status because many automation scripts use refresh, plan, then apply 99 and may not have a state file yet for the first run. 100 `