github.com/codeherentuk/terraform@v0.11.12-beta1/backend/local/backend_local.go (about) 1 package local 2 3 import ( 4 "context" 5 "errors" 6 "log" 7 8 "github.com/hashicorp/errwrap" 9 "github.com/hashicorp/terraform/backend" 10 "github.com/hashicorp/terraform/command/clistate" 11 "github.com/hashicorp/terraform/command/format" 12 "github.com/hashicorp/terraform/state" 13 "github.com/hashicorp/terraform/terraform" 14 "github.com/hashicorp/terraform/tfdiags" 15 ) 16 17 // backend.Local implementation. 18 func (b *Local) Context(op *backend.Operation) (*terraform.Context, state.State, error) { 19 // Make sure the type is invalid. We use this as a way to know not 20 // to ask for input/validate. 21 op.Type = backend.OperationTypeInvalid 22 23 if op.LockState { 24 op.StateLocker = clistate.NewLocker(context.Background(), op.StateLockTimeout, b.CLI, b.Colorize()) 25 } else { 26 op.StateLocker = clistate.NewNoopLocker() 27 } 28 29 return b.context(op) 30 } 31 32 func (b *Local) context(op *backend.Operation) (*terraform.Context, state.State, error) { 33 // Get the state. 34 s, err := b.State(op.Workspace) 35 if err != nil { 36 return nil, nil, errwrap.Wrapf("Error loading state: {{err}}", err) 37 } 38 39 if err := op.StateLocker.Lock(s, op.Type.String()); err != nil { 40 return nil, nil, errwrap.Wrapf("Error locking state: {{err}}", err) 41 } 42 43 if err := s.RefreshState(); err != nil { 44 return nil, nil, errwrap.Wrapf("Error loading state: {{err}}", err) 45 } 46 47 // Initialize our context options 48 var opts terraform.ContextOpts 49 if v := b.ContextOpts; v != nil { 50 opts = *v 51 } 52 53 // Copy set options from the operation 54 opts.Destroy = op.Destroy 55 opts.Module = op.Module 56 opts.Targets = op.Targets 57 opts.UIInput = op.UIIn 58 59 // Load our state 60 // By the time we get here, the backend creation code in "command" took 61 // care of making s.State() return a state compatible with our plan, 62 // if any, so we can safely pass this value in both the plan context 63 // and new context cases below. 64 opts.State = s.State() 65 66 // Build the context 67 var tfCtx *terraform.Context 68 if op.Plan != nil { 69 tfCtx, err = op.Plan.Context(&opts) 70 } else { 71 tfCtx, err = terraform.NewContext(&opts) 72 } 73 74 // any errors resolving plugins returns this 75 if rpe, ok := err.(*terraform.ResourceProviderError); ok { 76 b.pluginInitRequired(rpe) 77 // we wrote the full UI error here, so return a generic error for flow 78 // control in the command. 79 return nil, nil, errors.New("error satisfying plugin requirements") 80 } 81 82 if err != nil { 83 return nil, nil, err 84 } 85 86 // If we have an operation, then we automatically do the input/validate 87 // here since every option requires this. 88 if op.Type != backend.OperationTypeInvalid { 89 // If input asking is enabled, then do that 90 if op.Plan == nil && b.OpInput { 91 mode := terraform.InputModeProvider 92 mode |= terraform.InputModeVar 93 mode |= terraform.InputModeVarUnset 94 95 if err := tfCtx.Input(mode); err != nil { 96 return nil, nil, errwrap.Wrapf("Error asking for user input: {{err}}", err) 97 } 98 } 99 100 // If validation is enabled, validate 101 if b.OpValidation { 102 diags := tfCtx.Validate() 103 if len(diags) > 0 { 104 if diags.HasErrors() { 105 // If there are warnings _and_ errors then we'll take this 106 // path and return them all together in this error. 107 return nil, nil, diags.Err() 108 } 109 110 // For now we can't propagate warnings any further without 111 // printing them directly to the UI, so we'll need to 112 // format them here ourselves. 113 for _, diag := range diags { 114 if diag.Severity() != tfdiags.Warning { 115 continue 116 } 117 if b.CLI != nil { 118 b.CLI.Warn(format.Diagnostic(diag, b.Colorize(), 72)) 119 } else { 120 desc := diag.Description() 121 log.Printf("[WARN] backend/local: %s", desc.Summary) 122 } 123 } 124 125 // Make a newline before continuing 126 b.CLI.Output("") 127 } 128 } 129 } 130 131 return tfCtx, s, nil 132 } 133 134 const validateWarnHeader = ` 135 There are warnings related to your configuration. If no errors occurred, 136 Terraform will continue despite these warnings. It is a good idea to resolve 137 these warnings in the near future. 138 139 Warnings: 140 `