github.com/nevins-b/terraform@v0.3.8-0.20170215184714-bbae22007d5a/backend/local/backend_local.go (about)

     1  package local
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  
     8  	"github.com/hashicorp/errwrap"
     9  	"github.com/hashicorp/go-multierror"
    10  	"github.com/hashicorp/terraform/backend"
    11  	clistate "github.com/hashicorp/terraform/command/state"
    12  	"github.com/hashicorp/terraform/state"
    13  	"github.com/hashicorp/terraform/terraform"
    14  )
    15  
    16  // backend.Local implementation.
    17  func (b *Local) Context(op *backend.Operation) (*terraform.Context, state.State, error) {
    18  	// Make sure the type is invalid. We use this as a way to know not
    19  	// to ask for input/validate.
    20  	op.Type = backend.OperationTypeInvalid
    21  
    22  	return b.context(op)
    23  }
    24  
    25  func (b *Local) context(op *backend.Operation) (*terraform.Context, state.State, error) {
    26  	// Get the state.
    27  	s, err := b.State()
    28  	if err != nil {
    29  		return nil, nil, errwrap.Wrapf("Error loading state: {{err}}", err)
    30  	}
    31  
    32  	if op.LockState {
    33  		err := clistate.Lock(s, op.Type.String(), b.CLI, b.Colorize())
    34  		if err != nil {
    35  			return nil, nil, errwrap.Wrapf("Error locking state: {{err}}", err)
    36  		}
    37  	}
    38  
    39  	if err := s.RefreshState(); err != nil {
    40  		return nil, nil, errwrap.Wrapf("Error loading state: {{err}}", err)
    41  	}
    42  
    43  	// Initialize our context options
    44  	var opts terraform.ContextOpts
    45  	if v := b.ContextOpts; v != nil {
    46  		opts = *v
    47  	}
    48  
    49  	// Copy set options from the operation
    50  	opts.Destroy = op.Destroy
    51  	opts.Module = op.Module
    52  	opts.Targets = op.Targets
    53  	opts.UIInput = op.UIIn
    54  	if op.Variables != nil {
    55  		opts.Variables = op.Variables
    56  	}
    57  
    58  	// Load our state
    59  	opts.State = s.State()
    60  
    61  	// Build the context
    62  	var tfCtx *terraform.Context
    63  	if op.Plan != nil {
    64  		tfCtx, err = op.Plan.Context(&opts)
    65  	} else {
    66  		tfCtx, err = terraform.NewContext(&opts)
    67  	}
    68  	if err != nil {
    69  		return nil, nil, err
    70  	}
    71  
    72  	// If we have an operation, then we automatically do the input/validate
    73  	// here since every option requires this.
    74  	if op.Type != backend.OperationTypeInvalid {
    75  		// If input asking is enabled, then do that
    76  		if op.Plan == nil && b.OpInput {
    77  			mode := terraform.InputModeProvider
    78  			mode |= terraform.InputModeVar
    79  			mode |= terraform.InputModeVarUnset
    80  
    81  			if err := tfCtx.Input(mode); err != nil {
    82  				return nil, nil, errwrap.Wrapf("Error asking for user input: {{err}}", err)
    83  			}
    84  		}
    85  
    86  		// If validation is enabled, validate
    87  		if b.OpValidation {
    88  			// We ignore warnings here on purpose. We expect users to be listening
    89  			// to the terraform.Hook called after a validation.
    90  			ws, es := tfCtx.Validate()
    91  			if len(ws) > 0 {
    92  				// Log just in case the CLI isn't enabled
    93  				log.Printf("[WARN] backend/local: %d warnings: %v", len(ws), ws)
    94  
    95  				// If we have a CLI, output the warnings
    96  				if b.CLI != nil {
    97  					b.CLI.Warn(strings.TrimSpace(validateWarnHeader) + "\n")
    98  					for _, w := range ws {
    99  						b.CLI.Warn(fmt.Sprintf("  * %s", w))
   100  					}
   101  
   102  					// Make a newline before continuing
   103  					b.CLI.Output("")
   104  				}
   105  			}
   106  
   107  			if len(es) > 0 {
   108  				return nil, nil, multierror.Append(nil, es...)
   109  			}
   110  		}
   111  	}
   112  
   113  	return tfCtx, s, nil
   114  }
   115  
   116  const validateWarnHeader = `
   117  There are warnings related to your configuration. If no errors occurred,
   118  Terraform will continue despite these warnings. It is a good idea to resolve
   119  these warnings in the near future.
   120  
   121  Warnings:
   122  `