github.com/simonswine/terraform@v0.9.0-beta2/terraform/context.go (about)

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