github.com/paybyphone/terraform@v0.9.5-0.20170613192930-9706042ddd51/backend/local/backend_refresh.go (about) 1 package local 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "strings" 8 9 "github.com/hashicorp/errwrap" 10 "github.com/hashicorp/go-multierror" 11 "github.com/hashicorp/terraform/backend" 12 "github.com/hashicorp/terraform/command/clistate" 13 "github.com/hashicorp/terraform/config/module" 14 "github.com/hashicorp/terraform/state" 15 ) 16 17 func (b *Local) opRefresh( 18 ctx 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 if op.LockState { 54 lockCtx, cancel := context.WithTimeout(ctx, op.StateLockTimeout) 55 defer cancel() 56 57 lockInfo := state.NewLockInfo() 58 lockInfo.Operation = op.Type.String() 59 lockID, err := clistate.Lock(lockCtx, opState, lockInfo, b.CLI, b.Colorize()) 60 if err != nil { 61 runningOp.Err = errwrap.Wrapf("Error locking state: {{err}}", err) 62 return 63 } 64 65 defer func() { 66 if err := clistate.Unlock(opState, lockID, b.CLI, b.Colorize()); err != nil { 67 runningOp.Err = multierror.Append(runningOp.Err, err) 68 } 69 }() 70 } 71 72 // Set our state 73 runningOp.State = opState.State() 74 if runningOp.State.Empty() || !runningOp.State.HasResources() { 75 if b.CLI != nil { 76 b.CLI.Output(b.Colorize().Color( 77 strings.TrimSpace(refreshNoState) + "\n")) 78 } 79 } 80 81 // Perform operation and write the resulting state to the running op 82 newState, err := tfCtx.Refresh() 83 runningOp.State = newState 84 if err != nil { 85 runningOp.Err = errwrap.Wrapf("Error refreshing state: {{err}}", err) 86 return 87 } 88 89 // Write and persist the state 90 if err := opState.WriteState(newState); err != nil { 91 runningOp.Err = errwrap.Wrapf("Error writing state: {{err}}", err) 92 return 93 } 94 if err := opState.PersistState(); err != nil { 95 runningOp.Err = errwrap.Wrapf("Error saving state: {{err}}", err) 96 return 97 } 98 } 99 100 const refreshNoState = ` 101 [reset][bold][yellow]Empty or non-existent state file.[reset][yellow] 102 103 Refresh will do nothing. Refresh does not error or return an erroneous 104 exit status because many automation scripts use refresh, plan, then apply 105 and may not have a state file yet for the first run. 106 `