github.com/loicalbertin/terraform@v0.6.15-0.20170626182346-8e2583055467/backend/local/backend_local.go (about)

     1  package local
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"log"
     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/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(op.Workspace)
    28  	if err != nil {
    29  		return nil, nil, errwrap.Wrapf("Error loading state: {{err}}", err)
    30  	}
    31  
    32  	if err := s.RefreshState(); err != nil {
    33  		return nil, nil, errwrap.Wrapf("Error loading state: {{err}}", err)
    34  	}
    35  
    36  	// Initialize our context options
    37  	var opts terraform.ContextOpts
    38  	if v := b.ContextOpts; v != nil {
    39  		opts = *v
    40  	}
    41  
    42  	// Copy set options from the operation
    43  	opts.Destroy = op.Destroy
    44  	opts.Module = op.Module
    45  	opts.Targets = op.Targets
    46  	opts.UIInput = op.UIIn
    47  	if op.Variables != nil {
    48  		opts.Variables = op.Variables
    49  	}
    50  
    51  	// Load our state
    52  	opts.State = s.State()
    53  
    54  	// Build the context
    55  	var tfCtx *terraform.Context
    56  	if op.Plan != nil {
    57  		tfCtx, err = op.Plan.Context(&opts)
    58  	} else {
    59  		tfCtx, err = terraform.NewContext(&opts)
    60  	}
    61  
    62  	// any errors resolving plugins returns this
    63  	if rpe, ok := err.(*terraform.ResourceProviderError); ok {
    64  		b.pluginInitRequired(rpe)
    65  		// we wrote the full UI error here, so return a generic error for flow
    66  		// control in the command.
    67  		return nil, nil, errors.New("error satisfying plugin requirements")
    68  	}
    69  
    70  	if err != nil {
    71  		return nil, nil, err
    72  	}
    73  
    74  	// If we have an operation, then we automatically do the input/validate
    75  	// here since every option requires this.
    76  	if op.Type != backend.OperationTypeInvalid {
    77  		// If input asking is enabled, then do that
    78  		if op.Plan == nil && b.OpInput {
    79  			mode := terraform.InputModeProvider
    80  			mode |= terraform.InputModeVar
    81  			mode |= terraform.InputModeVarUnset
    82  
    83  			if err := tfCtx.Input(mode); err != nil {
    84  				return nil, nil, errwrap.Wrapf("Error asking for user input: {{err}}", err)
    85  			}
    86  		}
    87  
    88  		// If validation is enabled, validate
    89  		if b.OpValidation {
    90  			// We ignore warnings here on purpose. We expect users to be listening
    91  			// to the terraform.Hook called after a validation.
    92  			ws, es := tfCtx.Validate()
    93  			if len(ws) > 0 {
    94  				// Log just in case the CLI isn't enabled
    95  				log.Printf("[WARN] backend/local: %d warnings: %v", len(ws), ws)
    96  
    97  				// If we have a CLI, output the warnings
    98  				if b.CLI != nil {
    99  					b.CLI.Warn(strings.TrimSpace(validateWarnHeader) + "\n")
   100  					for _, w := range ws {
   101  						b.CLI.Warn(fmt.Sprintf("  * %s", w))
   102  					}
   103  
   104  					// Make a newline before continuing
   105  					b.CLI.Output("")
   106  				}
   107  			}
   108  
   109  			if len(es) > 0 {
   110  				return nil, nil, multierror.Append(nil, es...)
   111  			}
   112  		}
   113  	}
   114  
   115  	return tfCtx, s, nil
   116  }
   117  
   118  const validateWarnHeader = `
   119  There are warnings related to your configuration. If no errors occurred,
   120  Terraform will continue despite these warnings. It is a good idea to resolve
   121  these warnings in the near future.
   122  
   123  Warnings:
   124  `