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