github.com/ns1/terraform@v0.7.10-0.20161109153551-8949419bef40/terraform/context.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"sort"
     7  	"strings"
     8  	"sync"
     9  
    10  	"github.com/hashicorp/go-multierror"
    11  	"github.com/hashicorp/hcl"
    12  	"github.com/hashicorp/terraform/config"
    13  	"github.com/hashicorp/terraform/config/module"
    14  	"github.com/hashicorp/terraform/helper/experiment"
    15  )
    16  
    17  // InputMode defines what sort of input will be asked for when Input
    18  // is called on Context.
    19  type InputMode byte
    20  
    21  const (
    22  	// InputModeVar asks for all variables
    23  	InputModeVar InputMode = 1 << iota
    24  
    25  	// InputModeVarUnset asks for variables which are not set yet.
    26  	// InputModeVar must be set for this to have an effect.
    27  	InputModeVarUnset
    28  
    29  	// InputModeProvider asks for provider variables
    30  	InputModeProvider
    31  
    32  	// InputModeStd is the standard operating mode and asks for both variables
    33  	// and providers.
    34  	InputModeStd = InputModeVar | InputModeProvider
    35  )
    36  
    37  var (
    38  	// contextFailOnShadowError will cause Context operations to return
    39  	// errors when shadow operations fail. This is only used for testing.
    40  	contextFailOnShadowError = false
    41  
    42  	// contextTestDeepCopyOnPlan will perform a Diff DeepCopy on every
    43  	// Plan operation, effectively testing the Diff DeepCopy whenever
    44  	// a Plan occurs. This is enabled for tests.
    45  	contextTestDeepCopyOnPlan = false
    46  )
    47  
    48  // ContextOpts are the user-configurable options to create a context with
    49  // NewContext.
    50  type ContextOpts struct {
    51  	Destroy            bool
    52  	Diff               *Diff
    53  	Hooks              []Hook
    54  	Module             *module.Tree
    55  	Parallelism        int
    56  	State              *State
    57  	StateFutureAllowed bool
    58  	Providers          map[string]ResourceProviderFactory
    59  	Provisioners       map[string]ResourceProvisionerFactory
    60  	Shadow             bool
    61  	Targets            []string
    62  	Variables          map[string]interface{}
    63  
    64  	UIInput UIInput
    65  }
    66  
    67  // Context represents all the context that Terraform needs in order to
    68  // perform operations on infrastructure. This structure is built using
    69  // NewContext. See the documentation for that.
    70  //
    71  // Extra functions on Context can be found in context_*.go files.
    72  type Context struct {
    73  	// Maintainer note: Anytime this struct is changed, please verify
    74  	// that newShadowContext still does the right thing. Tests should
    75  	// fail regardless but putting this note here as well.
    76  
    77  	components contextComponentFactory
    78  	destroy    bool
    79  	diff       *Diff
    80  	diffLock   sync.RWMutex
    81  	hooks      []Hook
    82  	module     *module.Tree
    83  	sh         *stopHook
    84  	shadow     bool
    85  	state      *State
    86  	stateLock  sync.RWMutex
    87  	targets    []string
    88  	uiInput    UIInput
    89  	variables  map[string]interface{}
    90  
    91  	l                   sync.Mutex // Lock acquired during any task
    92  	parallelSem         Semaphore
    93  	providerInputConfig map[string]map[string]interface{}
    94  	runCh               <-chan struct{}
    95  	stopCh              chan struct{}
    96  	shadowErr           error
    97  }
    98  
    99  // NewContext creates a new Context structure.
   100  //
   101  // Once a Context is creator, the pointer values within ContextOpts
   102  // should not be mutated in any way, since the pointers are copied, not
   103  // the values themselves.
   104  func NewContext(opts *ContextOpts) (*Context, error) {
   105  	// Copy all the hooks and add our stop hook. We don't append directly
   106  	// to the Config so that we're not modifying that in-place.
   107  	sh := new(stopHook)
   108  	hooks := make([]Hook, len(opts.Hooks)+1)
   109  	copy(hooks, opts.Hooks)
   110  	hooks[len(opts.Hooks)] = sh
   111  
   112  	state := opts.State
   113  	if state == nil {
   114  		state = new(State)
   115  		state.init()
   116  	}
   117  
   118  	// If our state is from the future, then error. Callers can avoid
   119  	// this error by explicitly setting `StateFutureAllowed`.
   120  	if !opts.StateFutureAllowed && state.FromFutureTerraform() {
   121  		return nil, fmt.Errorf(
   122  			"Terraform doesn't allow running any operations against a state\n"+
   123  				"that was written by a future Terraform version. The state is\n"+
   124  				"reporting it is written by Terraform '%s'.\n\n"+
   125  				"Please run at least that version of Terraform to continue.",
   126  			state.TFVersion)
   127  	}
   128  
   129  	// Explicitly reset our state version to our current version so that
   130  	// any operations we do will write out that our latest version
   131  	// has run.
   132  	state.TFVersion = Version
   133  
   134  	// Determine parallelism, default to 10. We do this both to limit
   135  	// CPU pressure but also to have an extra guard against rate throttling
   136  	// from providers.
   137  	par := opts.Parallelism
   138  	if par == 0 {
   139  		par = 10
   140  	}
   141  
   142  	// Set up the variables in the following sequence:
   143  	//    0 - Take default values from the configuration
   144  	//    1 - Take values from TF_VAR_x environment variables
   145  	//    2 - Take values specified in -var flags, overriding values
   146  	//        set by environment variables if necessary. This includes
   147  	//        values taken from -var-file in addition.
   148  	variables := make(map[string]interface{})
   149  
   150  	if opts.Module != nil {
   151  		var err error
   152  		variables, err = Variables(opts.Module, opts.Variables)
   153  		if err != nil {
   154  			return nil, err
   155  		}
   156  	}
   157  
   158  	return &Context{
   159  		components: &basicComponentFactory{
   160  			providers:    opts.Providers,
   161  			provisioners: opts.Provisioners,
   162  		},
   163  		destroy:   opts.Destroy,
   164  		diff:      opts.Diff,
   165  		hooks:     hooks,
   166  		module:    opts.Module,
   167  		shadow:    opts.Shadow,
   168  		state:     state,
   169  		targets:   opts.Targets,
   170  		uiInput:   opts.UIInput,
   171  		variables: variables,
   172  
   173  		parallelSem:         NewSemaphore(par),
   174  		providerInputConfig: make(map[string]map[string]interface{}),
   175  		sh:                  sh,
   176  	}, nil
   177  }
   178  
   179  type ContextGraphOpts struct {
   180  	Validate bool
   181  	Verbose  bool
   182  }
   183  
   184  // Graph returns the graph for this config.
   185  func (c *Context) Graph(g *ContextGraphOpts) (*Graph, error) {
   186  	return c.graphBuilder(g).Build(RootModulePath)
   187  }
   188  
   189  // GraphBuilder returns the GraphBuilder that will be used to create
   190  // the graphs for this context.
   191  func (c *Context) graphBuilder(g *ContextGraphOpts) GraphBuilder {
   192  	return &BuiltinGraphBuilder{
   193  		Root:         c.module,
   194  		Diff:         c.diff,
   195  		Providers:    c.components.ResourceProviders(),
   196  		Provisioners: c.components.ResourceProvisioners(),
   197  		State:        c.state,
   198  		Targets:      c.targets,
   199  		Destroy:      c.destroy,
   200  		Validate:     g.Validate,
   201  		Verbose:      g.Verbose,
   202  	}
   203  }
   204  
   205  // ShadowError returns any errors caught during a shadow operation.
   206  //
   207  // A shadow operation is an operation run in parallel to a real operation
   208  // that performs the same tasks using new logic on copied state. The results
   209  // are compared to ensure that the new logic works the same as the old logic.
   210  // The shadow never affects the real operation or return values.
   211  //
   212  // The result of the shadow operation are only available through this function
   213  // call after a real operation is complete.
   214  //
   215  // For API consumers of Context, you can safely ignore this function
   216  // completely if you have no interest in helping report experimental feature
   217  // errors to Terraform maintainers. Otherwise, please call this function
   218  // after every operation and report this to the user.
   219  //
   220  // IMPORTANT: Shadow errors are _never_ critical: they _never_ affect
   221  // the real state or result of a real operation. They are purely informational
   222  // to assist in future Terraform versions being more stable. Please message
   223  // this effectively to the end user.
   224  //
   225  // This must be called only when no other operation is running (refresh,
   226  // plan, etc.). The result can be used in parallel to any other operation
   227  // running.
   228  func (c *Context) ShadowError() error {
   229  	return c.shadowErr
   230  }
   231  
   232  // Input asks for input to fill variables and provider configurations.
   233  // This modifies the configuration in-place, so asking for Input twice
   234  // may result in different UI output showing different current values.
   235  func (c *Context) Input(mode InputMode) error {
   236  	v := c.acquireRun("input")
   237  	defer c.releaseRun(v)
   238  
   239  	if mode&InputModeVar != 0 {
   240  		// Walk the variables first for the root module. We walk them in
   241  		// alphabetical order for UX reasons.
   242  		rootConf := c.module.Config()
   243  		names := make([]string, len(rootConf.Variables))
   244  		m := make(map[string]*config.Variable)
   245  		for i, v := range rootConf.Variables {
   246  			names[i] = v.Name
   247  			m[v.Name] = v
   248  		}
   249  		sort.Strings(names)
   250  		for _, n := range names {
   251  			// If we only care about unset variables, then if the variable
   252  			// is set, continue on.
   253  			if mode&InputModeVarUnset != 0 {
   254  				if _, ok := c.variables[n]; ok {
   255  					continue
   256  				}
   257  			}
   258  
   259  			var valueType config.VariableType
   260  
   261  			v := m[n]
   262  			switch valueType = v.Type(); valueType {
   263  			case config.VariableTypeUnknown:
   264  				continue
   265  			case config.VariableTypeMap:
   266  				// OK
   267  			case config.VariableTypeList:
   268  				// OK
   269  			case config.VariableTypeString:
   270  				// OK
   271  			default:
   272  				panic(fmt.Sprintf("Unknown variable type: %#v", v.Type()))
   273  			}
   274  
   275  			// If the variable is not already set, and the variable defines a
   276  			// default, use that for the value.
   277  			if _, ok := c.variables[n]; !ok {
   278  				if v.Default != nil {
   279  					c.variables[n] = v.Default.(string)
   280  					continue
   281  				}
   282  			}
   283  
   284  			// this should only happen during tests
   285  			if c.uiInput == nil {
   286  				log.Println("[WARN] Content.uiInput is nil")
   287  				continue
   288  			}
   289  
   290  			// Ask the user for a value for this variable
   291  			var value string
   292  			retry := 0
   293  			for {
   294  				var err error
   295  				value, err = c.uiInput.Input(&InputOpts{
   296  					Id:          fmt.Sprintf("var.%s", n),
   297  					Query:       fmt.Sprintf("var.%s", n),
   298  					Description: v.Description,
   299  				})
   300  				if err != nil {
   301  					return fmt.Errorf(
   302  						"Error asking for %s: %s", n, err)
   303  				}
   304  
   305  				if value == "" && v.Required() {
   306  					// Redo if it is required, but abort if we keep getting
   307  					// blank entries
   308  					if retry > 2 {
   309  						return fmt.Errorf("missing required value for %q", n)
   310  					}
   311  					retry++
   312  					continue
   313  				}
   314  
   315  				break
   316  			}
   317  
   318  			// no value provided, so don't set the variable at all
   319  			if value == "" {
   320  				continue
   321  			}
   322  
   323  			decoded, err := parseVariableAsHCL(n, value, valueType)
   324  			if err != nil {
   325  				return err
   326  			}
   327  
   328  			if decoded != nil {
   329  				c.variables[n] = decoded
   330  			}
   331  		}
   332  	}
   333  
   334  	if mode&InputModeProvider != 0 {
   335  		// Build the graph
   336  		graph, err := c.Graph(&ContextGraphOpts{Validate: true})
   337  		if err != nil {
   338  			return err
   339  		}
   340  
   341  		// Do the walk
   342  		if _, err := c.walk(graph, nil, walkInput); err != nil {
   343  			return err
   344  		}
   345  	}
   346  
   347  	return nil
   348  }
   349  
   350  // Apply applies the changes represented by this context and returns
   351  // the resulting state.
   352  //
   353  // In addition to returning the resulting state, this context is updated
   354  // with the latest state.
   355  func (c *Context) Apply() (*State, error) {
   356  	v := c.acquireRun("apply")
   357  	defer c.releaseRun(v)
   358  
   359  	// Copy our own state
   360  	c.state = c.state.DeepCopy()
   361  
   362  	X_newApply := experiment.Enabled(experiment.X_newApply)
   363  	X_newDestroy := experiment.Enabled(experiment.X_newDestroy)
   364  	newGraphEnabled := (c.destroy && X_newDestroy) || (!c.destroy && X_newApply)
   365  
   366  	// Build the original graph. This is before the new graph builders
   367  	// coming in 0.8. We do this for shadow graphing.
   368  	oldGraph, err := c.Graph(&ContextGraphOpts{Validate: true})
   369  	if err != nil && X_newApply {
   370  		// If we had an error graphing but we're using the new graph,
   371  		// just set it to nil and let it go. There are some features that
   372  		// may work with the new graph that don't with the old.
   373  		oldGraph = nil
   374  		err = nil
   375  	}
   376  	if err != nil {
   377  		return nil, err
   378  	}
   379  
   380  	// Build the new graph. We do this no matter what so we can shadow it.
   381  	newGraph, err := (&ApplyGraphBuilder{
   382  		Module:       c.module,
   383  		Diff:         c.diff,
   384  		State:        c.state,
   385  		Providers:    c.components.ResourceProviders(),
   386  		Provisioners: c.components.ResourceProvisioners(),
   387  		Destroy:      c.destroy,
   388  	}).Build(RootModulePath)
   389  	if err != nil && !newGraphEnabled {
   390  		// If we had an error graphing but we're not using this graph, just
   391  		// set it to nil and record it as a shadow error.
   392  		c.shadowErr = multierror.Append(c.shadowErr, fmt.Errorf(
   393  			"Error building new graph: %s", err))
   394  
   395  		newGraph = nil
   396  		err = nil
   397  	}
   398  	if err != nil {
   399  		return nil, err
   400  	}
   401  
   402  	// Determine what is the real and what is the shadow. The logic here
   403  	// is straightforward though the if statements are not:
   404  	//
   405  	//   * Destroy mode - always use original, shadow with nothing because
   406  	//     we're only testing the new APPLY graph.
   407  	//   * Apply with new apply - use new graph, shadow is new graph. We can't
   408  	//     shadow with the old graph because the old graph does a lot more
   409  	//     that it shouldn't.
   410  	//   * Apply with old apply - use old graph, shadow with new graph.
   411  	//
   412  	real := oldGraph
   413  	shadow := newGraph
   414  	if newGraphEnabled {
   415  		log.Printf("[WARN] terraform: real graph is experiment, shadow is experiment")
   416  		real = shadow
   417  	} else {
   418  		log.Printf("[WARN] terraform: real graph is original, shadow is experiment")
   419  	}
   420  
   421  	// Determine the operation
   422  	operation := walkApply
   423  	if c.destroy {
   424  		operation = walkDestroy
   425  	}
   426  
   427  	// This shouldn't happen, so assert it. This is before any state changes
   428  	// so it is safe to crash here.
   429  	if real == nil {
   430  		panic("nil real graph")
   431  	}
   432  
   433  	// Walk the graph
   434  	walker, err := c.walk(real, shadow, operation)
   435  	if len(walker.ValidationErrors) > 0 {
   436  		err = multierror.Append(err, walker.ValidationErrors...)
   437  	}
   438  
   439  	// Clean out any unused things
   440  	c.state.prune()
   441  
   442  	return c.state, err
   443  }
   444  
   445  // Plan generates an execution plan for the given context.
   446  //
   447  // The execution plan encapsulates the context and can be stored
   448  // in order to reinstantiate a context later for Apply.
   449  //
   450  // Plan also updates the diff of this context to be the diff generated
   451  // by the plan, so Apply can be called after.
   452  func (c *Context) Plan() (*Plan, error) {
   453  	v := c.acquireRun("plan")
   454  	defer c.releaseRun(v)
   455  
   456  	p := &Plan{
   457  		Module:  c.module,
   458  		Vars:    c.variables,
   459  		State:   c.state,
   460  		Targets: c.targets,
   461  	}
   462  
   463  	var operation walkOperation
   464  	if c.destroy {
   465  		operation = walkPlanDestroy
   466  	} else {
   467  		// Set our state to be something temporary. We do this so that
   468  		// the plan can update a fake state so that variables work, then
   469  		// we replace it back with our old state.
   470  		old := c.state
   471  		if old == nil {
   472  			c.state = &State{}
   473  			c.state.init()
   474  		} else {
   475  			c.state = old.DeepCopy()
   476  		}
   477  		defer func() {
   478  			c.state = old
   479  		}()
   480  
   481  		operation = walkPlan
   482  	}
   483  
   484  	// Setup our diff
   485  	c.diffLock.Lock()
   486  	c.diff = new(Diff)
   487  	c.diff.init()
   488  	c.diffLock.Unlock()
   489  
   490  	// Used throughout below
   491  	X_newDestroy := experiment.Enabled(experiment.X_newDestroy)
   492  
   493  	// Build the graph. We have a branch here since for the pure-destroy
   494  	// plan (c.destroy) we use a much simpler graph builder that simply
   495  	// walks the state and reverses edges.
   496  	var graph *Graph
   497  	var err error
   498  	if c.destroy && X_newDestroy {
   499  		graph, err = (&DestroyPlanGraphBuilder{
   500  			Module:  c.module,
   501  			State:   c.state,
   502  			Targets: c.targets,
   503  		}).Build(RootModulePath)
   504  	} else {
   505  		graph, err = c.Graph(&ContextGraphOpts{Validate: true})
   506  	}
   507  	if err != nil {
   508  		return nil, err
   509  	}
   510  
   511  	// Do the walk
   512  	walker, err := c.walk(graph, graph, operation)
   513  	if err != nil {
   514  		return nil, err
   515  	}
   516  	p.Diff = c.diff
   517  
   518  	// If this is true, it means we're running unit tests. In this case,
   519  	// we perform a deep copy just to ensure that all context tests also
   520  	// test that a diff is copy-able. This will panic if it fails. This
   521  	// is enabled during unit tests.
   522  	//
   523  	// This should never be true during production usage, but even if it is,
   524  	// it can't do any real harm.
   525  	if contextTestDeepCopyOnPlan {
   526  		p.Diff.DeepCopy()
   527  	}
   528  
   529  	// We don't do the reverification during the new destroy plan because
   530  	// it will use a different apply process.
   531  	if !(c.destroy && X_newDestroy) {
   532  		// Now that we have a diff, we can build the exact graph that Apply will use
   533  		// and catch any possible cycles during the Plan phase.
   534  		if _, err := c.Graph(&ContextGraphOpts{Validate: true}); err != nil {
   535  			return nil, err
   536  		}
   537  	}
   538  
   539  	var errs error
   540  	if len(walker.ValidationErrors) > 0 {
   541  		errs = multierror.Append(errs, walker.ValidationErrors...)
   542  	}
   543  	return p, errs
   544  }
   545  
   546  // Refresh goes through all the resources in the state and refreshes them
   547  // to their latest state. This will update the state that this context
   548  // works with, along with returning it.
   549  //
   550  // Even in the case an error is returned, the state will be returned and
   551  // will potentially be partially updated.
   552  func (c *Context) Refresh() (*State, error) {
   553  	v := c.acquireRun("refresh")
   554  	defer c.releaseRun(v)
   555  
   556  	// Copy our own state
   557  	c.state = c.state.DeepCopy()
   558  
   559  	// Build the graph
   560  	graph, err := c.Graph(&ContextGraphOpts{Validate: true})
   561  	if err != nil {
   562  		return nil, err
   563  	}
   564  
   565  	// Do the walk
   566  	if _, err := c.walk(graph, graph, walkRefresh); err != nil {
   567  		return nil, err
   568  	}
   569  
   570  	// Clean out any unused things
   571  	c.state.prune()
   572  
   573  	return c.state, nil
   574  }
   575  
   576  // Stop stops the running task.
   577  //
   578  // Stop will block until the task completes.
   579  func (c *Context) Stop() {
   580  	c.l.Lock()
   581  	ch := c.runCh
   582  
   583  	// If we aren't running, then just return
   584  	if ch == nil {
   585  		c.l.Unlock()
   586  		return
   587  	}
   588  
   589  	// Tell the hook we want to stop
   590  	c.sh.Stop()
   591  
   592  	// Close the stop channel
   593  	close(c.stopCh)
   594  
   595  	// Wait for us to stop
   596  	c.l.Unlock()
   597  	<-ch
   598  }
   599  
   600  // Validate validates the configuration and returns any warnings or errors.
   601  func (c *Context) Validate() ([]string, []error) {
   602  	v := c.acquireRun("validate")
   603  	defer c.releaseRun(v)
   604  
   605  	var errs error
   606  
   607  	// Validate the configuration itself
   608  	if err := c.module.Validate(); err != nil {
   609  		errs = multierror.Append(errs, err)
   610  	}
   611  
   612  	// This only needs to be done for the root module, since inter-module
   613  	// variables are validated in the module tree.
   614  	if config := c.module.Config(); config != nil {
   615  		// Validate the user variables
   616  		if err := smcUserVariables(config, c.variables); len(err) > 0 {
   617  			errs = multierror.Append(errs, err...)
   618  		}
   619  	}
   620  
   621  	// If we have errors at this point, the graphing has no chance,
   622  	// so just bail early.
   623  	if errs != nil {
   624  		return nil, []error{errs}
   625  	}
   626  
   627  	// Build the graph so we can walk it and run Validate on nodes.
   628  	// We also validate the graph generated here, but this graph doesn't
   629  	// necessarily match the graph that Plan will generate, so we'll validate the
   630  	// graph again later after Planning.
   631  	graph, err := c.Graph(&ContextGraphOpts{Validate: true})
   632  	if err != nil {
   633  		return nil, []error{err}
   634  	}
   635  
   636  	// Walk
   637  	walker, err := c.walk(graph, graph, walkValidate)
   638  	if err != nil {
   639  		return nil, multierror.Append(errs, err).Errors
   640  	}
   641  
   642  	// Return the result
   643  	rerrs := multierror.Append(errs, walker.ValidationErrors...)
   644  	return walker.ValidationWarnings, rerrs.Errors
   645  }
   646  
   647  // Module returns the module tree associated with this context.
   648  func (c *Context) Module() *module.Tree {
   649  	return c.module
   650  }
   651  
   652  // Variables will return the mapping of variables that were defined
   653  // for this Context. If Input was called, this mapping may be different
   654  // than what was given.
   655  func (c *Context) Variables() map[string]interface{} {
   656  	return c.variables
   657  }
   658  
   659  // SetVariable sets a variable after a context has already been built.
   660  func (c *Context) SetVariable(k string, v interface{}) {
   661  	c.variables[k] = v
   662  }
   663  
   664  func (c *Context) acquireRun(phase string) chan<- struct{} {
   665  	c.l.Lock()
   666  	defer c.l.Unlock()
   667  
   668  	dbug.SetPhase(phase)
   669  
   670  	// Wait for no channel to exist
   671  	for c.runCh != nil {
   672  		c.l.Unlock()
   673  		ch := c.runCh
   674  		<-ch
   675  		c.l.Lock()
   676  	}
   677  
   678  	// Create the new channel
   679  	ch := make(chan struct{})
   680  	c.runCh = ch
   681  
   682  	// Reset the stop channel so we can watch that
   683  	c.stopCh = make(chan struct{})
   684  
   685  	// Reset the stop hook so we're not stopped
   686  	c.sh.Reset()
   687  
   688  	// Reset the shadow errors
   689  	c.shadowErr = nil
   690  
   691  	return ch
   692  }
   693  
   694  func (c *Context) releaseRun(ch chan<- struct{}) {
   695  	c.l.Lock()
   696  	defer c.l.Unlock()
   697  
   698  	// setting the phase to "INVALID" lets us easily detect if we have
   699  	// operations happening outside of a run, or we missed setting the proper
   700  	// phase
   701  	dbug.SetPhase("INVALID")
   702  
   703  	close(ch)
   704  	c.runCh = nil
   705  	c.stopCh = nil
   706  }
   707  
   708  func (c *Context) walk(
   709  	graph, shadow *Graph, operation walkOperation) (*ContextGraphWalker, error) {
   710  	// Keep track of the "real" context which is the context that does
   711  	// the real work: talking to real providers, modifying real state, etc.
   712  	realCtx := c
   713  
   714  	// If we don't want shadowing, remove it
   715  	if !experiment.Enabled(experiment.X_shadow) {
   716  		shadow = nil
   717  	}
   718  
   719  	// If we have a shadow graph, walk that as well
   720  	var shadowCtx *Context
   721  	var shadowCloser Shadow
   722  	if c.shadow && shadow != nil {
   723  		// Build the shadow context. In the process, override the real context
   724  		// with the one that is wrapped so that the shadow context can verify
   725  		// the results of the real.
   726  		realCtx, shadowCtx, shadowCloser = newShadowContext(c)
   727  	}
   728  
   729  	// Just log this so we can see it in a debug log
   730  	if !c.shadow {
   731  		log.Printf("[WARN] terraform: shadow graph disabled")
   732  	}
   733  
   734  	log.Printf("[DEBUG] Starting graph walk: %s", operation.String())
   735  
   736  	dg, _ := NewDebugGraph("walk", graph, nil)
   737  	walker := &ContextGraphWalker{
   738  		Context:    realCtx,
   739  		Operation:  operation,
   740  		DebugGraph: dg,
   741  	}
   742  
   743  	// Watch for a stop so we can call the provider Stop() API.
   744  	doneCh := make(chan struct{})
   745  	go c.watchStop(walker, c.stopCh, doneCh)
   746  
   747  	// Walk the real graph, this will block until it completes
   748  	realErr := graph.Walk(walker)
   749  
   750  	// Close the done channel so the watcher stops
   751  	close(doneCh)
   752  
   753  	// If we have a shadow graph and we interrupted the real graph, then
   754  	// we just close the shadow and never verify it. It is non-trivial to
   755  	// recreate the exact execution state up until an interruption so this
   756  	// isn't supported with shadows at the moment.
   757  	if shadowCloser != nil && c.sh.Stopped() {
   758  		// Ignore the error result, there is nothing we could care about
   759  		shadowCloser.CloseShadow()
   760  
   761  		// Set it to nil so we don't do anything
   762  		shadowCloser = nil
   763  	}
   764  
   765  	// If we have a shadow graph, wait for that to complete.
   766  	if shadowCloser != nil {
   767  		// create a debug graph for this walk
   768  		dg, err := NewDebugGraph("walk-shadow", shadow, nil)
   769  		if err != nil {
   770  			log.Printf("[ERROR] %v", err)
   771  		}
   772  
   773  		// Build the graph walker for the shadow. We also wrap this in
   774  		// a panicwrap so that panics are captured. For the shadow graph,
   775  		// we just want panics to be normal errors rather than to crash
   776  		// Terraform.
   777  		shadowWalker := GraphWalkerPanicwrap(&ContextGraphWalker{
   778  			Context:    shadowCtx,
   779  			Operation:  operation,
   780  			DebugGraph: dg,
   781  		})
   782  
   783  		// Kick off the shadow walk. This will block on any operations
   784  		// on the real walk so it is fine to start first.
   785  		log.Printf("[INFO] Starting shadow graph walk: %s", operation.String())
   786  		shadowCh := make(chan error)
   787  		go func() {
   788  			shadowCh <- shadow.Walk(shadowWalker)
   789  		}()
   790  
   791  		// Notify the shadow that we're done
   792  		if err := shadowCloser.CloseShadow(); err != nil {
   793  			c.shadowErr = multierror.Append(c.shadowErr, err)
   794  		}
   795  
   796  		// Wait for the walk to end
   797  		log.Printf("[DEBUG] Waiting for shadow graph to complete...")
   798  		shadowWalkErr := <-shadowCh
   799  
   800  		// Get any shadow errors
   801  		if err := shadowCloser.ShadowError(); err != nil {
   802  			c.shadowErr = multierror.Append(c.shadowErr, err)
   803  		}
   804  
   805  		// Verify the contexts (compare)
   806  		if err := shadowContextVerify(realCtx, shadowCtx); err != nil {
   807  			c.shadowErr = multierror.Append(c.shadowErr, err)
   808  		}
   809  
   810  		// At this point, if we're supposed to fail on error, then
   811  		// we PANIC. Some tests just verify that there is an error,
   812  		// so simply appending it to realErr and returning could hide
   813  		// shadow problems.
   814  		//
   815  		// This must be done BEFORE appending shadowWalkErr since the
   816  		// shadowWalkErr may include expected errors.
   817  		if c.shadowErr != nil && contextFailOnShadowError {
   818  			panic(multierror.Prefix(c.shadowErr, "shadow graph:"))
   819  		}
   820  
   821  		// Now, if we have a walk error, we append that through
   822  		if shadowWalkErr != nil {
   823  			c.shadowErr = multierror.Append(c.shadowErr, shadowWalkErr)
   824  		}
   825  
   826  		if c.shadowErr == nil {
   827  			log.Printf("[INFO] Shadow graph success!")
   828  		} else {
   829  			log.Printf("[ERROR] Shadow graph error: %s", c.shadowErr)
   830  
   831  			// If we're supposed to fail on shadow errors, then report it
   832  			if contextFailOnShadowError {
   833  				realErr = multierror.Append(realErr, multierror.Prefix(
   834  					c.shadowErr, "shadow graph:"))
   835  			}
   836  		}
   837  	}
   838  
   839  	return walker, realErr
   840  }
   841  
   842  func (c *Context) watchStop(walker *ContextGraphWalker, stopCh, doneCh <-chan struct{}) {
   843  	// Wait for a stop or completion
   844  	select {
   845  	case <-stopCh:
   846  		// Stop was triggered. Fall out of the select
   847  	case <-doneCh:
   848  		// Done, just exit completely
   849  		return
   850  	}
   851  
   852  	// If we're here, we're stopped, trigger the call.
   853  
   854  	// Copy the providers so that a misbehaved blocking Stop doesn't
   855  	// completely hang Terraform.
   856  	walker.providerLock.Lock()
   857  	ps := make([]ResourceProvider, 0, len(walker.providerCache))
   858  	for _, p := range walker.providerCache {
   859  		ps = append(ps, p)
   860  	}
   861  	defer walker.providerLock.Unlock()
   862  
   863  	for _, p := range ps {
   864  		// We ignore the error for now since there isn't any reasonable
   865  		// action to take if there is an error here, since the stop is still
   866  		// advisory: Terraform will exit once the graph node completes.
   867  		p.Stop()
   868  	}
   869  }
   870  
   871  // parseVariableAsHCL parses the value of a single variable as would have been specified
   872  // on the command line via -var or in an environment variable named TF_VAR_x, where x is
   873  // the name of the variable. In order to get around the restriction of HCL requiring a
   874  // top level object, we prepend a sentinel key, decode the user-specified value as its
   875  // value and pull the value back out of the resulting map.
   876  func parseVariableAsHCL(name string, input string, targetType config.VariableType) (interface{}, error) {
   877  	// expecting a string so don't decode anything, just strip quotes
   878  	if targetType == config.VariableTypeString {
   879  		return strings.Trim(input, `"`), nil
   880  	}
   881  
   882  	// return empty types
   883  	if strings.TrimSpace(input) == "" {
   884  		switch targetType {
   885  		case config.VariableTypeList:
   886  			return []interface{}{}, nil
   887  		case config.VariableTypeMap:
   888  			return make(map[string]interface{}), nil
   889  		}
   890  	}
   891  
   892  	const sentinelValue = "SENTINEL_TERRAFORM_VAR_OVERRIDE_KEY"
   893  	inputWithSentinal := fmt.Sprintf("%s = %s", sentinelValue, input)
   894  
   895  	var decoded map[string]interface{}
   896  	err := hcl.Decode(&decoded, inputWithSentinal)
   897  	if err != nil {
   898  		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL: %s", name, input, err)
   899  	}
   900  
   901  	if len(decoded) != 1 {
   902  		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. Only one value may be specified.", name, input)
   903  	}
   904  
   905  	parsedValue, ok := decoded[sentinelValue]
   906  	if !ok {
   907  		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. One value must be specified.", name, input)
   908  	}
   909  
   910  	switch targetType {
   911  	case config.VariableTypeList:
   912  		return parsedValue, nil
   913  	case config.VariableTypeMap:
   914  		if list, ok := parsedValue.([]map[string]interface{}); ok {
   915  			return list[0], nil
   916  		}
   917  
   918  		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. One value must be specified.", name, input)
   919  	default:
   920  		panic(fmt.Errorf("unknown type %s", targetType.Printable()))
   921  	}
   922  }