github.com/sixgill/terraform@v0.9.0-beta2.0.20170316214032-033f6226ae50/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 clistate "github.com/hashicorp/terraform/command/state" 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 lockInfo := state.NewLockInfo() 55 lockInfo.Operation = op.Type.String() 56 lockID, err := clistate.Lock(opState, lockInfo, b.CLI, b.Colorize()) 57 if err != nil { 58 runningOp.Err = errwrap.Wrapf("Error locking state: {{err}}", err) 59 return 60 } 61 62 defer func() { 63 if err := clistate.Unlock(opState, lockID, b.CLI, b.Colorize()); err != nil { 64 runningOp.Err = multierror.Append(runningOp.Err, err) 65 } 66 }() 67 } 68 69 // Set our state 70 runningOp.State = opState.State() 71 if runningOp.State.Empty() || !runningOp.State.HasResources() { 72 if b.CLI != nil { 73 b.CLI.Output(b.Colorize().Color( 74 strings.TrimSpace(refreshNoState) + "\n")) 75 } 76 } 77 78 // Perform operation and write the resulting state to the running op 79 newState, err := tfCtx.Refresh() 80 runningOp.State = newState 81 if err != nil { 82 runningOp.Err = errwrap.Wrapf("Error refreshing state: {{err}}", err) 83 return 84 } 85 86 // Write and persist the state 87 if err := opState.WriteState(newState); err != nil { 88 runningOp.Err = errwrap.Wrapf("Error writing state: {{err}}", err) 89 return 90 } 91 if err := opState.PersistState(); err != nil { 92 runningOp.Err = errwrap.Wrapf("Error saving state: {{err}}", err) 93 return 94 } 95 } 96 97 const refreshNoState = ` 98 [reset][bold][yellow]Empty or non-existent state file.[reset][yellow] 99 100 Refresh will do nothing. Refresh does not error or return an erroneous 101 exit status because many automation scripts use refresh, plan, then apply 102 and may not have a state file yet for the first run. 103 `